Skip to content

Commit

Permalink
major updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ampledata committed Jan 28, 2023
1 parent 848740b commit 5b1b4ff
Show file tree
Hide file tree
Showing 17 changed files with 804 additions and 191 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
INRCOT 5.2.0
------------
Major updates.
- Updated copyrights, etc.
- Documentation & Readme updates.
- Now supports Data Package server configuration.
- Fixed custom user icon support.
- Added unit tests.
- Now requires PyTAK >= 5.6.1.
- Refactoring, style improvements, linting, black.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2022 Greg Albrecht <[email protected]>
Copyright 2023 Greg Albrecht <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
8 changes: 3 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright 2022 Greg Albrecht <[email protected]>
# Copyright 2023 Greg Albrecht <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -13,9 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author:: Greg Albrecht W2GMD <[email protected]>
# Copyright:: Copyright 2022 Greg Albrecht
# License:: Apache License, Version 2.0
# Author:: Greg Albrecht <[email protected]>
#

this_app = inrcot
Expand Down Expand Up @@ -72,7 +70,7 @@ pytest:
test: editable install_test_requirements pytest

test_cov:
pytest --cov=$(this_app)
pytest --cov=$(this_app) --cov-report term-missing

black:
black .
76 changes: 43 additions & 33 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,25 @@ Garmin inReach to Cursor on Target Gateway
* Pictured: Screenshot of INRCOT being used on a Search & Rescue mission in Arizona.

The inReach to Cursor on Target Gateway (INRCOT) transforms Garmin inReach
position messages into Cursor on Target (CoT) Points for display on TAK Products
like ATAK, WinTAK, iTAK, et al. Single or multi-device feeds are supported.
position messages into Cursor on Target (CoT) for display on TAK Products such as
ATAK, WinTAK, iTAK, et al. Single or multi-device feeds are supported.

Other situational awareness products, including as RaptorX, TAKX & COPERS have been tested.
Other situational awareness products, including as RaptorX, TAKX & COPERS have been
tested.

INRCOT requires a `Garmin inReach <https://discover.garmin.com/en-US/inreach/personal/>`_ device with service.
INRCOT requires a `Garmin inReach <https://discover.garmin.com/en-US/inreach/personal/>`_
device with service.

.. image:: https://raw.githubusercontent.com/ampledata/inrcot/main/docs/inrcot-conops.png
:alt: Diagram of INRCOT's Concept of Operations (CONOPS).
:target: https://raw.githubusercontent.com/ampledata/inrcot/main/docs/inrcot-conops.png
.. image:: https://raw.githubusercontent.com/ampledata/inrcot/main/docs/inrcot-conop.png
:alt: Diagram of INRCOT's Concept of Operations (CONOP).
:target: https://raw.githubusercontent.com/ampledata/inrcot/main/docs/inrcot-conop.png

* Pictured: Diagram of INRCOT's Concept of Operations (CONOP).

* Pictured: Diagram of INRCOT's Concept of Operations (CONOPS).

Support Development
===================

**Tech Support**: Email [email protected] or Signal/WhatsApp: +1-310-621-9598

This tool has been developed for the Disaster Response, Public Safety and
Frontline Healthcare community. This software is currently provided at no-cost
to users. Any contribution you can make to further this project's development
efforts is greatly appreciated.

.. image:: https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png
:target: https://www.buymeacoffee.com/ampledata
:alt: Support Development: Buy me a coffee!
Expand All @@ -42,14 +38,14 @@ Use Cases
There are numerous applications for satellite based position location information,
including:

1. Blue Force Tracking
2. Search & Rescue (SAR)
3. Partner Forces PLI
4. Asset Tracking
5. Data diode, CDS & cybersecurity considerations
1. Wildland fire unit tracking
2. Blue Force Tracking
3. Search & Rescue (SAR)
4. Partner Forces PLI
5. Asset Tracking
6. Data diode, CDS & cybersecurity considerations

INRCOT may also be of use in wildland firefighting, see Section 1114.d of
the `Dingell Act <https://www.congress.gov/bill/116th-congress/senate-bill/47/text>`_::
See also Section 1114.d of the `Dingell Act <https://www.congress.gov/bill/116th-congress/senate-bill/47/text>`_::

Location Systems for Wildland Firefighters.--
(1) In general.--Not later than 2 years after the date of
Expand Down Expand Up @@ -108,24 +104,38 @@ Usage
The ``inrcot`` program has two command-line arguments::

$ inrcot -h
usage: inrcot [-h] [-c CONFIG_FILE]
usage: inrcot [-h] [-c CONFIG_FILE] [-p PREF_PACKAGE]

optional arguments:
-h, --help show this help message and exit
-c CONFIG_FILE, --CONFIG_FILE Sets the path to a config file. Default: config.ini
-h, --help show this help message and exit
-c CONFIG_FILE, --CONFIG_FILE CONFIG_FILE
Optional configuration file. Default: config.ini
-p PREF_PACKAGE, --PREF_PACKAGE PREF_PACKAGE
Optional connection preferences package zip file (aka data package).


Configuration
=============

Configuration parameters can be specified either via environment variables or in
a INI-stile configuration file. You must create a configuration file, see
`example-config.ini` in the source respository.
a INI-stile configuration file. An example configuration file, click here for an
example configuration file `example-config.ini <https://github.com/ampledata/inrcot/blob/main/example-config.ini>`_.

Global Config Parameters:

* **POLL_INTERVAL**: How many seconds between checking for new messages at the Spot API? Default: ``120`` (seconds).
* **COT_STALE**: How many seconds until CoT is stale? Default: ``600`` (seconds)
* **COT_TYPE**: CoT Type. Default: ``a-f-g-e-s``

Parameters:
For each feed (1 inReach = 1 feed, multiple feeds supported), these config params can be set:

* **DEFAULT_POLL_INTERVAL**: How many seconds between checking for new messages at the Spot API? Default: 120 (seconds).
* **DEFAULT_COT_STALE**: How many seconds until CoT is stale? Default: 600 (seconds)
* **DEFAULT_COT_TYPE**: CoT Event Type / 2525 type / SIDC-like. Default: neutral ground
* **FEED_URL**: URL to the MapShare KML.
* **COT_STALE**: How many seconds until CoT is stale? Default: ``600`` (seconds)
* **COT_TYPE**: CoT Type. Default: ``a-f-g-e-s``
* **COT_NAME**: CoT Callsign. Defaults to the MapShare KML Placemark name.
* **COT_ICON**: CoT User Icon. If set, will set the CoT ``usericon`` element, for use with custom TAK icon sets.
* **FEED_USERNAME**: MapShare username, for use with protected MapShare.
* **FEED_PASSWORD**: MapShare password, for use with protected MapShare.

TLS & other configuration parameters available via `PyTAK <https://github.com/ampledata/pytak#configuration-parameters>`_.

Expand Down Expand Up @@ -194,12 +204,12 @@ https://ampledata.org/

Copyright
=========
INRCOT is Copyright 2022 Greg Albrecht
INRCOT is Copyright 2023 Greg Albrecht


License
=======
Copyright 2022 Greg Albrecht <[email protected]>
Copyright 2023 Greg Albrecht <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
File renamed without changes
19 changes: 8 additions & 11 deletions inrcot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2022 Greg Albrecht <[email protected]>
# Copyright 2023 Greg Albrecht <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -13,25 +13,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author:: Greg Albrecht W2GMD <[email protected]>
#

"""
inReach to Cursor-on-Target Gateway.
~~~~

:author: Greg Albrecht W2GMD <[email protected]>
:copyright: Copyright 2022 Greg Albrecht
"""inReach to Cursor on Target Gateway.
:author: Greg Albrecht <[email protected]>
:copyright: Copyright 2023 Greg Albrecht
:license: Apache License, Version 2.0
:source: <https://github.com/ampledata/inrcot>
"""

from .constants import DEFAULT_POLL_INTERVAL, DEFAULT_COT_STALE, DEFAULT_COT_TYPE

from .functions import create_tasks, inreach_to_cot, split_feed
from .functions import create_tasks, inreach_to_cot, split_feed, create_feeds

from .classes import Worker

__author__ = "Greg Albrecht W2GMD <[email protected]>"
__copyright__ = "Copyright 2022 Greg Albrecht"
__author__ = "Greg Albrecht <[email protected]>"
__copyright__ = "Copyright 2023 Greg Albrecht"
__license__ = "Apache License, Version 2.0"
109 changes: 50 additions & 59 deletions inrcot/classes.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2022 Greg Albrecht <[email protected]>
# Copyright 2023 Greg Albrecht <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -13,94 +13,85 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author:: Greg Albrecht W2GMD <[email protected]>
#


"""INRCOT Class Definitions."""

import asyncio

from typing import Optional

import aiohttp

import pytak
import inrcot


__author__ = "Greg Albrecht W2GMD <[email protected]>"
__copyright__ = "Copyright 2022 Greg Albrecht"
__author__ = "Greg Albrecht <[email protected]>"
__copyright__ = "Copyright 2023 Greg Albrecht"
__license__ = "Apache License, Version 2.0"


class Worker(pytak.QueueWorker):
"""Read inReach Feed, renders to CoT, and puts on a TX queue."""

"""Reads inReach Feed, renders to CoT, and puts on a TX queue."""

def __init__(self, queue: asyncio.Queue, config, original_config) -> None:
def __init__(self, queue: asyncio.Queue, config, orig_config) -> None:
super().__init__(queue, config)
self.inreach_feeds: list = []
self._create_feeds(original_config)

def _create_feeds(self, config: dict = None) -> None:
"""Creates a list of feed configurations."""
for feed in config.sections():
if "inrcot_feed_" in feed:
feed_conf = {
"feed_url": config[feed].get("FEED_URL"),
"cot_stale": config[feed].get(
"COT_STALE", inrcot.DEFAULT_COT_STALE
),
"cot_type": config[feed].get("COT_TYPE", inrcot.DEFAULT_COT_TYPE),
"cot_icon": config[feed].get("COT_ICON"),
"cot_name": config[feed].get("COT_NAME"),
}

# Support "private" MapShare feeds:
if config[feed].get("FEED_PASSWORD") and config[feed].get(
"FEED_USERNAME"
):
feed_conf["feed_auth"] = aiohttp.BasicAuth(
config[feed].get("FEED_USERNAME"),
config[feed].get("FEED_PASSWORD"),
)

self.inreach_feeds.append(feed_conf)

async def handle_data(self, data: str, feed_conf: dict) -> None:
"""Handles the response from the inReach API."""
for feed in inrcot.split_feed(data):
event: str = inrcot.inreach_to_cot(feed, feed_conf)
if event:
await self.put_queue(event)
else:
self._logger.debug("Empty COT Event")

async def get_inreach_feeds(self):
"""Gets inReach Feed from API."""
self.inreach_feeds: list = inrcot.create_feeds(orig_config)

async def handle_data(self, data: bytes, feed_conf: dict) -> None:
"""Handle the response from the inReach API."""
feeds: Optional[list] = inrcot.split_feed(data)
if not feeds:
return None
for feed in feeds:
event: Optional[bytes] = inrcot.inreach_to_cot(feed, feed_conf)
if not event:
self._logger.debug("Empty CoT Event")
continue
await self.put_queue(event)

async def get_inreach_feeds(self) -> None:
"""Get inReach Feed from API."""
for feed_conf in self.inreach_feeds:
feed_auth = feed_conf.get("feed_auth")
if not feed_auth:
self._logger.warning("No feed_auth specified.")
continue

feed_url = feed_conf.get("feed_url")
if not feed_url:
self._logger.warning("No feed_url specified.")
continue

async with aiohttp.ClientSession() as session:
try:
response = await session.request(
method="GET", auth=feed_auth, url=feed_conf.get("feed_url")
method="GET", auth=feed_auth, url=feed_url
)
except Exception as exc: # NOQA pylint: disable=broad-except
self._logger.error("Exception raised while polling inReach API.")
self._logger.warning("Exception raised while polling inReach API.")
self._logger.exception(exc)
return
continue

status: int = response.status
if status != 200:
self._logger.warning(
"No valid response from inReach API: status=%s", status
)
self._logger.debug(response)
continue

if response.status == 200:
await self.handle_data(await response.content.read(), feed_conf)
else:
self._logger.error("No valid response from inReach API.")
await self.handle_data(await response.content.read(), feed_conf)

async def run(self) -> None:
"""Runs this Worker, Reads from Pollers."""
async def run(self, number_of_iterations=-1) -> None:
"""Run this Worker, Reads from Pollers."""
self._logger.info("Run: %s", self.__class__)

poll_interval: str = self.config.get(
"POLL_INTERVAL", inrcot.DEFAULT_POLL_INTERVAL
poll_interval: int = int(
self.config.get("POLL_INTERVAL", inrcot.DEFAULT_POLL_INTERVAL)
)

while 1:
await self.get_inreach_feeds()
await asyncio.sleep(int(poll_interval))
await asyncio.sleep(poll_interval)
Loading

0 comments on commit 5b1b4ff

Please sign in to comment.