Skip to content

Commit

Permalink
updates, adding support for seavision
Browse files Browse the repository at this point in the history
  • Loading branch information
ampledata committed Dec 26, 2024
1 parent cd90d90 commit 0879672
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 39 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# limitations under the License.
#

REPO_NAME ?= $(shell echo $(wildcard */classes.py) | awk -F'/' '{print $$1}')
REPO_NAME ?= $(shell echo $(wildcard */__init__.py) | awk -F'/' '{print $$1}')
SHELL := /bin/bash
.DEFAULT_GOAL := editable
# postinst = $(wildcard debian/*.postinst.sh)
Expand Down
4 changes: 0 additions & 4 deletions aiscot/ais_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@

import aiscot

__author__ = "Greg Albrecht <[email protected]>"
__copyright__ = "Copyright 2023 Sensors & Signals LLC"
__license__ = "Apache License, Version 2.0"


def read_known_craft_fd(csv_fd: TextIO) -> list:
"""Split a CSV file into an iterable key=value store.
Expand Down
65 changes: 37 additions & 28 deletions aiscot/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

# pylint: disable=too-many-instance-attributes
class AISNetworkClient(asyncio.Protocol):
"""Class for handling connections from network AIS feed."""
"""Network AIS feed client (receiver)."""

_logger = logging.getLogger(__name__)
if not _logger.handlers:
Expand Down Expand Up @@ -126,7 +126,7 @@ def connection_lost(self, exc) -> None:


class AISWorker(pytak.QueueWorker):
"""AIS Cursor-on-Target Class."""
"""AIS to TAK worker."""

def __init__(self, queue: asyncio.Queue, config: ConfigParser) -> None:
"""Initialize an instance of this class."""
Expand All @@ -137,12 +137,12 @@ def __init__(self, queue: asyncio.Queue, config: ConfigParser) -> None:
self.feed_url: Optional[str] = None

async def handle_data(self, data) -> None:
"""Handle received MMSI data."""
"""Handle received data."""
# self._logger.info("Received AIS: '%s'", msg)
mmsi: str = ""

for msg in data:
mmsi = str(msg.get("MMSI", ""))
mmsi = str(msg.get("MMSI", msg.get("mmsi", "")))
if not mmsi:
continue

Expand Down Expand Up @@ -178,19 +178,37 @@ async def handle_data(self, data) -> None:
async def get_feed(self) -> None:
"""Get AIS data from AISHub feed."""
if not self.session:
return
response = await self.session.request(method="GET", url=self.feed_url)
response.raise_for_status()
json_resp = await response.json()

api_report = json_resp[0]
if api_report.get("ERROR"):
self._logger.error("AISHub.com API returned an error: ")
self._logger.error(api_report)
raise ValueError("No session available.")
if not self.feed_url:
raise ValueError("Feed URL is not set.")

if "seavision" in self.feed_url:
self._logger.info("Using SeaVision API")
headers = {
"x-api-key": self.config.get("SEAVISION_API_KEY"),
"accept": "application/json",
}
response = await self.session.request(
method="GET", url=self.feed_url, headers=headers
)
response.raise_for_status()
json_resp = await response.json()
if json_resp:
self._logger.debug("Retrieved %s ships", len(json_resp))
await self.handle_data(json_resp)
else:
ships = json_resp[1]
self._logger.debug("Retrieved %s ships", len(ships))
await self.handle_data(ships)
response = await self.session.request(method="GET", url=self.feed_url)
response.raise_for_status()
json_resp = await response.json()

api_report = json_resp[0]
if api_report.get("ERROR"):
self._logger.error("AISHub.com API returned an error: ")
self._logger.error(api_report)
else:
ships = json_resp[1]
self._logger.debug("Retrieved %s ships", len(ships))
await self.handle_data(ships)

async def run(self, number_of_iterations=-1) -> None:
"""Run this Thread, reads AIS & outputs CoT."""
Expand All @@ -201,17 +219,8 @@ async def run(self, number_of_iterations=-1) -> None:
self._logger.info("Using KNOWN_CRAFT: %s", known_craft)
self.known_craft_db = aiscot.get_known_craft(known_craft)

self.feed_url = self.config.get("AISHUB_URL")
if self.feed_url:
warnings.warn(
(
"DEPRECATED: AISHUB_URL configuration parameter detected, "
"please use FEED_URL."
)
)
else:
self.feed_url = self.config.get("FEED_URL")

self.feed_url = self.config.get("FEED_URL")
self._logger.info("Using FEED_URL: %s", self.feed_url)
if self.feed_url:
await self.poll_feed()
else:
Expand Down Expand Up @@ -240,6 +249,6 @@ async def poll_feed(self) -> None:
)
async with aiohttp.ClientSession() as self.session:
while 1:
await asyncio.sleep(poll_interval)
self._logger.info("Polling every %ss: %s", poll_interval, self.feed_url)
await self.get_feed()
await asyncio.sleep(poll_interval)
15 changes: 11 additions & 4 deletions aiscot/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,14 @@ def ais_to_cot_xml(
config = config or {}
remarks_fields: list = []

lat: float = float(craft.get("lat", craft.get("LATITUDE", "0")))
lon: float = float(craft.get("lon", craft.get("LONGITUDE", "0")))
lat: float = float(
craft.get("lat", craft.get("LATITUDE", craft.get("latitude", "0")))
)
lon: float = float(
craft.get("lon", craft.get("LONGITUDE", craft.get("longitude", "0")))
)
mmsi: str = str(craft.get("mmsi", craft.get("MMSI", "")))

# At least these three must exist, but may have different names depending on the
# AIS source:
if not all([lat, lon, mmsi]):
Expand Down Expand Up @@ -113,7 +118,9 @@ def ais_to_cot_xml(
str(craft.get("name", craft.get("NAME", ""))).replace("@", "").strip()
)
shipname: str = str(craft.get("shipname", aisfunc.get_shipname(mmsi)))
vessel_type: str = str(craft.get("type", craft.get("TYPE", "")))
vessel_type: str = str(
craft.get("type", craft.get("TYPE", craft.get("veselType", "")))
)

cot_icon = config.get("COT_ICON")

Expand Down Expand Up @@ -185,7 +192,7 @@ def ais_to_cot_xml(
# AIS Speed over ground: 0.1-knot (0.19 km/h) resolution from
# 0 to 102 knots (189 km/h)
# COT Speed is meters/second
sog: Optional[float] = craft.get("speed", craft.get("SPEED"))
sog: Optional[float] = craft.get("speed", craft.get("SPEED", craft.get("SOG", "0")))
if sog:
sog = float(sog) * 0.1 / 1.944
if sog and sog != 0.0:
Expand Down
4 changes: 2 additions & 2 deletions debian/aiscot.postinst
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ systemctl enable aiscot.service

echo "---- AISCOT Install Complete ----"
echo "Documentation: https://aiscot.rtfd.io/"
echo "Configure aiscot: sudo nano /etc/default/aiscot"
echo "Start aiscot: sudo systemctl start aiscot.service"
echo "Configure: sudo nano /etc/default/aiscot"
echo "Start: sudo systemctl start aiscot.service"
echo "Logs: sudo journalctl -fu aiscot"

exit 0

0 comments on commit 0879672

Please sign in to comment.