From 1e4477dfe58a637294ab95abc558fcdb3dd26753 Mon Sep 17 00:00:00 2001 From: Evan Pratten Date: Thu, 21 Nov 2024 15:48:57 -0500 Subject: [PATCH] pskreporter adapter --- .../containers/pskreporter-to-mqtt.dockerfile | 13 ++++ ...qtt-ingest-radio-spots.docker-compose.yaml | 9 +++ scripts/pskreporter-to-mqtt | 59 +++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 docker/containers/pskreporter-to-mqtt.dockerfile create mode 100755 scripts/pskreporter-to-mqtt diff --git a/docker/containers/pskreporter-to-mqtt.dockerfile b/docker/containers/pskreporter-to-mqtt.dockerfile new file mode 100644 index 0000000..8e5be4e --- /dev/null +++ b/docker/containers/pskreporter-to-mqtt.dockerfile @@ -0,0 +1,13 @@ +FROM python:3.13 + +# External config +ENV MQTT_HOST= + +# Dependencies +RUN pip install paho-mqtt + +# The script itself +COPY ./scripts/pskreporter-to-mqtt /pskreporter-to-mqtt.py + +# Run config +CMD ["sh", "-c", "python /pskreporter-to-mqtt.py $MQTT_HOST"] \ No newline at end of file diff --git a/docker/stacks/mqtt-ingest-radio-spots.docker-compose.yaml b/docker/stacks/mqtt-ingest-radio-spots.docker-compose.yaml index e8bdd62..f1a43e7 100644 --- a/docker/stacks/mqtt-ingest-radio-spots.docker-compose.yaml +++ b/docker/stacks/mqtt-ingest-radio-spots.docker-compose.yaml @@ -18,3 +18,12 @@ services: environment: - MODE=ft8 - MQTT_HOST=${MQTT_HOST} + + pskreporter_to_mqtt: + build: + context: ../.. + dockerfile: docker/containers/pskreporter-to-mqtt.dockerfile + restart: unless-stopped + env_file: .env + environment: + - MQTT_HOST=${MQTT_HOST} \ No newline at end of file diff --git a/scripts/pskreporter-to-mqtt b/scripts/pskreporter-to-mqtt new file mode 100755 index 0000000..a48792a --- /dev/null +++ b/scripts/pskreporter-to-mqtt @@ -0,0 +1,59 @@ +#! /usr/bin/env python3 +import argparse +import sys +import logging +import json +import paho.mqtt.client as mqtt # pip install paho-mqtt +from datetime import datetime + +logger = logging.getLogger(__name__) + +def main() -> int: + # Handle program arguments + ap = argparse.ArgumentParser(prog='pskreporter-to-mqtt', description='Reflects pskreporter spots to an MQTT broker') + ap.add_argument("mqtt_broker", help="MQTT broker to connect to") + ap.add_argument('-v', '--verbose', help='Enable verbose logging', action='store_true') + args = ap.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.DEBUG if args.verbose else logging.INFO, + format='%(levelname)s: %(message)s', + ) + + # Connect to the MQTT broker + mqtt_client = mqtt.Client() + mqtt_client.connect(args.mqtt_broker) + + # Connect to the pskreporter MQTT broker + pskreporter_client = mqtt.Client() + pskreporter_client.connect("mqtt.pskreporter.info") + + # Subscribe to the pskreporter MQTT broker + pskreporter_client.subscribe("pskr/filter/v2/+/+/+/#") + + # Handle incoming pskreporter spots + def on_message(client, userdata, message): + payload = json.loads(message.payload) + logger.debug(f"Received spot: {payload}") + + # Sanitize the payload + sanitized = { + "frequency_khz": float(payload["f"]) / 1000, + "mode": payload["md"], + "db": int(payload["rp"]), + "timestamp": float(payload["t"]), + "spotter": payload["rc"], + "spotter_grid": payload["rl"], + "spotted": payload["sc"], + "spotted_grid": payload["sl"], + } + mqtt_client.publish(f"radio/spots/pskreporter/{sanitized['mode']}/{sanitized['spotted']}", json.dumps(sanitized)) + + pskreporter_client.on_message = on_message + pskreporter_client.loop_forever() + + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file