diff --git a/config-example.yml b/config-example.yml index 683ae72..20295df 100644 --- a/config-example.yml +++ b/config-example.yml @@ -162,6 +162,9 @@ alert_providers: - class: "BOTA" enabled: true + - class: "Hamsat" + enabled: true + - class: "NG3K" enabled: true diff --git a/core/constants.py b/core/constants.py index acadaad..e899c53 100644 --- a/core/constants.py +++ b/core/constants.py @@ -359,6 +359,14 @@ SIGS = [ region_flag="🇵🇱", refs_globally_unique=False, ), + SIG( + name="AMSAT", + comment_names=[], + description="Amateur Radio Satellites", + sig_type=SIGType.WORLDWIDE, + icon="fa-satellite", + refs_globally_unique=False, + ), SIG( name="Toilets", comment_names=[], diff --git a/core/enums.py b/core/enums.py index 770be24..c3e1b9a 100644 --- a/core/enums.py +++ b/core/enums.py @@ -116,6 +116,7 @@ class AlertType(str, Enum): """Type of an alert.""" XOTA = "XOTA" + SATELLITE = "SATELLITE" DXPEDITION = "DXPEDITION" CONTEST = "CONTEST" diff --git a/data/alert.py b/data/alert.py index 584f771..186273f 100644 --- a/data/alert.py +++ b/data/alert.py @@ -158,6 +158,8 @@ class Alert: self.icon = "fa-globe-africa" elif self.alert_type == AlertType.CONTEST: self.icon = "fa-trophy" + elif self.alert_type == AlertType.CONTEST: + self.icon = "fa-satellite" elif self.sig_refs and len(self.sig_refs) > 0 and self.sig_refs[0].icon: self.icon = self.sig_refs[0].icon diff --git a/data/spot.py b/data/spot.py index 0380916..2ff0a28 100644 --- a/data/spot.py +++ b/data/spot.py @@ -359,6 +359,12 @@ class Spot: self.propagation_mode = mode_tag logger.info(f"Seen a new propagation mode tag not yet in the system: {mode_tag}") + # Tag satellite contacts as AMSAT SIG + if self.propagation_mode == "Satellite": + if not self.sig: + self.sig = "AMSAT" + self.sig_refs.append(SIGRef(sig="AMSAT")) + # Parse "de_grid -> dx_grid" structures from the comment if self.comment: grid_mode_grid_match = re.search( diff --git a/providers/alert/hamsat.py b/providers/alert/hamsat.py new file mode 100644 index 0000000..d04302f --- /dev/null +++ b/providers/alert/hamsat.py @@ -0,0 +1,49 @@ +from datetime import datetime + +import pytz + +from core.enums import AlertType +from data.alert import Alert +from data.sig_ref import SIGRef +from providers.alert.http_alert_provider import HTTPAlertProvider + + +class Hamsat(HTTPAlertProvider): + """Alert provider for Hamsat (hams.at)""" + + POLL_INTERVAL_SEC = 1800 + ALERTS_URL = "https://hams.at/api/alerts" + + def __init__(self, provider_config): + super().__init__("Hamsat", provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) + + def _http_response_to_alerts(self, http_response): + new_alerts = [] + # Iterate through source data + for source_alert in http_response.json()["data"]: + # Convert to our alert format + alert = Alert( + source=self.name, + source_id=source_alert["id"], + dx_calls=[source_alert["callsign"].upper()], + freqs_modes=f"{source_alert['mhz']!s} {source_alert['mhz_direction']}, {source_alert['mode']}", + comment=source_alert["comment"], + # Fudge a SIG ref to provide the remaining bits of data we need: the satellite and the operator's grid + sig_refs=[ + SIGRef( + sig="AMSAT", + id=f"{source_alert['satellite']['name']} from {source_alert['grids'][0]}", + ) + ], + start_time=datetime.strptime(source_alert["aos_at"], "%Y-%m-%dT%H:%M:%SZ") + .replace(tzinfo=pytz.UTC) + .timestamp(), + end_time=datetime.strptime(source_alert["los_at"], "%Y-%m-%dT%H:%M:%SZ") + .replace(tzinfo=pytz.UTC) + .timestamp(), + alert_type=AlertType.SATELLITE, + ) + + # Add to our list + new_alerts.append(alert) + return new_alerts diff --git a/templates/add_spot.html b/templates/add_spot.html index 7316e43..55b3e2a 100644 --- a/templates/add_spot.html +++ b/templates/add_spot.html @@ -77,7 +77,7 @@ - + diff --git a/templates/alerts.html b/templates/alerts.html index 7ef5c42..bfdca7d 100644 --- a/templates/alerts.html +++ b/templates/alerts.html @@ -83,7 +83,7 @@ - + diff --git a/templates/bands.html b/templates/bands.html index c4e76a9..5b63416 100644 --- a/templates/bands.html +++ b/templates/bands.html @@ -76,8 +76,8 @@ - - + + diff --git a/templates/base.html b/templates/base.html index a7f180a..798a429 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,6 +1,6 @@ {% extends "skeleton.html" %} {% block head_extra %} - + @@ -16,10 +16,10 @@ window.fetchEventSource = fetchEventSource; - - - - + + + + {% end %} {% block body %}
diff --git a/templates/conditions.html b/templates/conditions.html index 84f97f1..a5587c1 100644 --- a/templates/conditions.html +++ b/templates/conditions.html @@ -284,7 +284,7 @@
- + diff --git a/templates/map.html b/templates/map.html index 398aafb..c8567e3 100644 --- a/templates/map.html +++ b/templates/map.html @@ -113,8 +113,8 @@ const CARTODB_API_KEY = "{{ web_ui_options.get('cartodb_api_key', '') }}"; - - + + diff --git a/templates/spots.html b/templates/spots.html index 5d13a32..37a66c8 100644 --- a/templates/spots.html +++ b/templates/spots.html @@ -113,8 +113,8 @@ - - + + diff --git a/templates/status.html b/templates/status.html index cc6b4c7..5a7ad3e 100644 --- a/templates/status.html +++ b/templates/status.html @@ -86,7 +86,7 @@ - +