Add sondehub-amateur upload for GPS telemetry

sondehub
Mark Jessop 2023-07-28 19:58:42 +09:30
rodzic 3769fe2be4
commit af5a101165
8 zmienionych plików z 86 dodań i 12 usunięć

Wyświetl plik

@ -45,7 +45,8 @@ RUN --mount=type=cache,target=/root/.cache/pip pip3 install \
flask \
flask-socketio \
simple-websocket \
requests
requests \
sondehub
# Copy in wenet.
COPY . /root/wenet

Wyświetl plik

@ -19,8 +19,7 @@ from base64 import b64encode
# Check if we are running in Python 2 or 3
PY3 = sys.version_info[0] == 3
WENET_VERSION = "1.1.0"
WENET_IMAGE_UDP_PORT = 7890
WENET_TELEMETRY_UDP_PORT = 55672

Wyświetl plik

@ -0,0 +1,7 @@
numpy
crcmod
flask
flask-socketio
simple-websocket
requests
sondehub

Wyświetl plik

@ -49,9 +49,10 @@ LOG_FILENAME = os.path.join(args.rximages,datetime.datetime.utcnow().strftime("%
# GUI updates are only sent locally.
def trigger_gui_update(filename, text = "None"):
def trigger_gui_update(filename, text = "None", metadata = None):
message = {'filename': filename,
'text': text}
'text': text,
'metadata': metadata}
gui_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
gui_socket.sendto(json.dumps(message).encode('ascii'),("127.0.0.1",WENET_IMAGE_UDP_PORT))
@ -231,7 +232,7 @@ while True:
os.system(f"mv rxtemp.bin {_dessdv_filename}.bin")
# Update live displays here.
trigger_gui_update(os.path.abspath(_dessdv_filename+".jpg"), packet_as_string)
trigger_gui_update(os.path.abspath(_dessdv_filename+".jpg"), packet_as_string, packet_info)
# Trigger upload to habhub here.
else:
@ -258,7 +259,7 @@ while True:
returncode = os.system("ssdv -d rxtemp.bin rxtemp.jpg 2>/dev/null > /dev/null")
if returncode == 0:
logging.debug("Wrote out partial update of image ID #%d" % current_image)
trigger_gui_update(os.path.abspath("rxtemp.jpg"), packet_as_string)
trigger_gui_update(os.path.abspath("rxtemp.jpg"), packet_as_string, packet_info)
else:
logging.debug("Unknown Packet Format.")

Wyświetl plik

@ -29,7 +29,7 @@ python3 ssdvuploader.py "$MYCALL" &
SSDV_UPLOAD_PID=$!
# Start the Web Interface Server
python3 wenetserver.py &
python3 wenetserver.py "$MYCALL" &
WEB_VIEWER_PID=$!
# Calculate the SDR sample rate required.

Wyświetl plik

@ -27,6 +27,8 @@ from io import BytesIO
from WenetPackets import *
from sondehub.amateur import Uploader
# Define Flask Application, and allow automatic reloading of templates for dev
app = flask.Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
@ -36,12 +38,20 @@ app.jinja_env.auto_reload = True
# SocketIO instance
socketio = SocketIO(app)
# PySondeHub Uploader, instantiated later.
sondehub = None
# Latest Image
latest_image = None
latest_image_lock = Lock()
# Data we need for uploading telemetry to SondeHub-Amateur
my_callsign = "N0CALL"
current_callsign = None
current_modem_stats = None
#
# Flask Routes
#
@ -69,14 +79,12 @@ def serve_latest_image():
as_attachment=False)
def flask_emit_event(event_name="none", data={}):
""" Emit a socketio event to any clients. """
socketio.emit(event_name, data, namespace='/update_status')
# SocketIO Handlers
@socketio.on('client_connected', namespace='/update_status')
def update_client_display(data):
pass
@ -102,6 +110,47 @@ def update_image(filename, description):
logging.error("Error loading new image %s - %s" % (filename, str(e)))
def handle_gps_telemetry(gps_data):
global current_callsign, current_modem_stats
if current_callsign is None:
# No callsign yet, can't do anything with the GPS data
return
if current_modem_stats is None:
# No modem stats, don't want to upload without that info.
return
# Only upload telemetry if we have GPS lock.
if gps_data['gpsFix'] != 3:
logging.debug("No GPS lock - discarding GPS telemetry.")
return
if sondehub:
# Add to the SondeHub-Amateur uploader!
sondehub.add_telemetry(
current_callsign + "-Wenet",
gps_data['timestamp'] + "Z",
round(gps_data['latitude'],6),
round(gps_data['longitude'],6),
round(gps_data['altitude'],1),
sats = gps_data['numSV'],
heading = round(gps_data['heading'],1),
extra_fields = {
'ascent_rate': round(gps_data['ascent_rate'],1),
'speed': round(gps_data['ground_speed'],1)
},
modulation = "Wenet",
frequency = round(current_modem_stats['fcentre']/1e6, 5),
snr = round(current_modem_stats['snr'],1)
)
# TODO - Emit as a Horus UDP Payload Summary packet.
def handle_telemetry(packet):
""" Handle GPS and Text message packets from the wenet receiver """
@ -114,6 +163,8 @@ def handle_telemetry(packet):
if gps_data['error'] == 'None':
flask_emit_event('gps_update', data=gps_data)
handle_gps_telemetry(gps_data)
elif packet_type == WENET_PACKET_TYPES.TEXT_MESSAGE:
# A text message from the payload.
text_data = decode_text_message(packet)
@ -138,6 +189,7 @@ def handle_telemetry(packet):
def process_udp(packet):
global current_callsign, current_modem_stats
packet_dict = json.loads(packet.decode('ascii'))
@ -145,6 +197,11 @@ def process_udp(packet):
# New image to load
update_image(packet_dict['filename'], packet_dict['text'])
new_callsign = packet_dict['metadata']['callsign']
if current_callsign != new_callsign:
logging.info(f"Received new payload callsign data: {new_callsign}")
current_callsign = new_callsign
elif 'uploader_status' in packet_dict:
# Information from the uploader process.
flask_emit_event('uploader_update', data=packet_dict)
@ -152,6 +209,7 @@ def process_udp(packet):
elif 'snr' in packet_dict:
# Modem statistics packet
flask_emit_event('modem_stats', data=packet_dict)
current_modem_stats = packet_dict
elif 'type' in packet_dict:
# Generic telemetry packet from the wenet RX.
@ -197,8 +255,10 @@ if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("callsign", help="SondeHub-Amateur Uploader Callsign")
parser.add_argument("-l", "--listen_port",default=5003,help="Port to run Web Server on. (Default: 5003)")
parser.add_argument("-v", "--verbose", action='store_true', help="Enable debug output.")
parser.add_argument("--no_sondehub", action='store_true', help="Disable SondeHub-Amateur position upload.")
args = parser.parse_args()
@ -209,6 +269,12 @@ if __name__ == "__main__":
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=log_level)
my_callsign = args.callsign
# Instantiate the SondeHub-Amateur Uploader
if not args.no_sondehub:
sondehub = Uploader(my_callsign, software_name="pysondehub-wenet", software_version=WENET_VERSION)
logging.getLogger("werkzeug").setLevel(logging.ERROR)
logging.getLogger("socketio").setLevel(logging.ERROR)
logging.getLogger("engineio").setLevel(logging.ERROR)

Wyświetl plik

@ -94,7 +94,7 @@ python ssdvuploader.py $MYCALL &
SSDV_UPLOAD_PID=$!
# Start the Web Interface Server
python wenetserver.py &
python wenetserver.py $MYCALL &
WEB_VIEWER_PID=$!

Wyświetl plik

@ -1139,7 +1139,7 @@ class UBloxGPS(object):
msg_name = msg.name()
#print(msg_name)
except Exception as e:
self.debug_message("WARNING: GPS Failure. Attempting to reconnect.")
self.debug_message("WARNING: GPS Failure - " + str(e))
self.write_state('numSV',0)
# Attempt to re-open GPS.
time.sleep(5)