From 09e294e240921cc8af73677a273abcbaf447b8de Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Thu, 13 Jul 2023 11:23:58 +0200 Subject: Add raspi igate script --- README.md | 15 +++++++ python/igate.py | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100755 python/igate.py diff --git a/README.md b/README.md index 9219919..260cb0b 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,18 @@ Try to follow https://aprs434.github.io/ Contains STM32F103, u-blox NEO-M8N, RFM98W 433MHz LoRa Module and AFT09MS007NT1 PA: ![3d view](tracker-kicad/20230709-tracker-kicad-3d.png) + +## i-gate + +`python/igate.py` contains an APRS-IS i-gate that uses a RFM98W on a Raspberry Pi. +It only forwards position reports. + +### Installation + +Configuration: Modify the CALLSIGN and PASSCODE inside `igate.py` + + cd python + python3 -m venv venv + venv/bin/pip install -r requirements.txt + ./igate.py + diff --git a/python/igate.py b/python/igate.py new file mode 100755 index 0000000..9466304 --- /dev/null +++ b/python/igate.py @@ -0,0 +1,120 @@ +#!venv/bin/python +# +# This script is a very simple APRS-IS LoRa igate that +# runs on a raspberry pi and expects a RFM9x on the SPI bus. +# +# Also, there are two status LEDs on D23 and D24 that count +# the incoming messages. +# +# It is a send-only i-gate that uses the HTTP POST mechanism described +# on http://aprs-is.net/SendOnlyPorts.aspx +# +import datetime +import socket +import struct +import time + +import busio +from digitalio import DigitalInOut, Direction, Pull +import board +# Import the RFM9x radio module. +import adafruit_rfm9x + +# For APRS-IS +APRS_IS_SERVER = "france.aprs2.net" +APRS_IS_PORT = 8080 +#APRS_IS_PORT = 14580 +CALLSIGN = "HB9EGM-10" +PASSCODE = "22681" +REPORTING_DISTANCE = "10" + +def decode_encoded_position_report(packet): + """Returns a string with decoded latitude and longitude, or raises ValueError""" + ix = packet.index(b":!/") + gps_packet = packet[ix+3:] + encoded_latitude = gps_packet[:4] + encoded_longitude = gps_packet[4:8] + + (y1, y2, y3, y4) = struct.unpack(" 16: + rfm9x.low_datarate_optimize = 1 + else: + rfm9x.low_datarate_optimize = 0 + + print("Waiting for packets...") + while True: + packet = rfm9x.receive(timeout=4, with_header=True) + if packet is not None: + packet = bytes(packet) # otherwise it's a bytearray + + print("{}: {}".format(datetime.datetime.now(), packet)) + #print(" {}".format(" ".join(hex(x) for x in packet))) + + if b":!/" in packet: + print(decode_encoded_position_report(packet)) + try: + send_frame_to_aprs_is(packet) + except Exception as ex: + print("Error sending to APRS-IS") + print(ex) + + print(" RSSI: {}".format(rfm9x.last_rssi)) + print() + + update_leds() +except RuntimeError as error: + print(f'RFM9x Error: {error}') -- cgit v1.2.3