kopia lustrzana https://github.com/projecthorus/wenet
Add sondehub-amateur upload for GPS telemetry
rodzic
3769fe2be4
commit
af5a101165
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
numpy
|
||||
crcmod
|
||||
flask
|
||||
flask-socketio
|
||||
simple-websocket
|
||||
requests
|
||||
sondehub
|
|
@ -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.")
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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=$!
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue