wenet/rx/rx_ssdv.py

190 wiersze
6.1 KiB
Python
Czysty Zwykły widok Historia

2016-03-05 10:06:28 +00:00
#!/usr/bin/env python
#
# SSDV Packet Receiver & Parser
# Decodes SSDV packets passed via stdin.
#
2018-01-25 03:04:43 +00:00
# Copyright (C) 2018 Mark Jessop <vk5qi@rfhead.net>
# Released under GNU GPL v3 or later
2016-03-05 10:06:28 +00:00
#
# Requires: ssdv (https://github.com/fsphil/ssdv)
#
import codecs
import json
import logging
import os
import sys
import datetime
import argparse
import socket
from WenetPackets import *
2016-03-05 10:06:28 +00:00
# Check if we are running in Python 2 or 3
PY3 = sys.version_info[0] == 3
2016-03-05 10:06:28 +00:00
parser = argparse.ArgumentParser()
parser.add_argument("--hex", action="store_true", help="Take Hex strings as input instead of raw data.")
parser.add_argument("--partialupdate", default=0, help="Push partial updates every N packets to GUI.")
parser.add_argument("-v", "--verbose", action='store_true', default=False, help="Verbose output")
2016-03-05 10:06:28 +00:00
args = parser.parse_args()
# Set up log output.
if args.verbose:
log_level = logging.DEBUG
else:
log_level = logging.INFO
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=log_level)
logging.getLogger("requests").setLevel(logging.CRITICAL)
logging.getLogger("urllib3").setLevel(logging.CRITICAL)
# GUI updates are only sent locally.
def trigger_gui_update(filename, text = "None"):
message = {'filename': filename,
'text': text}
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))
gui_socket.close()
# Telemetry packets are send via UDP broadcast in case there is other software on the local
# network that wants them.
def broadcast_telemetry_packet(data):
telemetry_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# Set up the telemetry socket so it can be re-used.
telemetry_socket.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
telemetry_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# We need the following if running on OSX.
try:
telemetry_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
except:
pass
# Place data into dictionary.
data = {'type': 'WENET', 'packet': list(bytearray(data))}
# Send to broadcast if we can.
try:
telemetry_socket.sendto(json.dumps(data).encode('ascii'), ('<broadcast>', WENET_TELEMETRY_UDP_PORT))
except socket.error:
telemetry_socket.sendto(json.dumps(data).encode('ascii'), ('127.0.0.1', WENET_TELEMETRY_UDP_PORT))
telemetry_socket.close()
2016-03-05 10:06:28 +00:00
# State variables
current_image = -1
current_callsign = ""
current_text_message = -1
2016-03-05 10:06:28 +00:00
current_packet_count = 0
current_packet_time = datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%SZ")
# Open temporary file for storing data.
temp_f = open("rxtemp.bin",'wb')
2016-03-05 10:06:28 +00:00
while True:
if args.hex:
# Incoming data is as a hexadecimal string.
# We can read these in safely using sys.stdin.readline(),
# and then pass them into codecs.decode to obtain either a
# str (Python 2), or bytes (python 3)
data = sys.stdin.readline().rstrip()
data = codecs.decode(data, 'hex')
2016-03-05 10:06:28 +00:00
else:
# If we are receiving raw binary data via stdin, we need
# to use the buffer interface under Python 3, and the 'regular' interface
# under python t.
if PY3:
data = sys.stdin.buffer.read(256)
else:
data = sys.stdin.read(256)
2016-03-05 10:06:28 +00:00
packet_type = decode_packet_type(data)
if packet_type == WENET_PACKET_TYPES.IDLE:
continue
elif packet_type == WENET_PACKET_TYPES.TEXT_MESSAGE:
broadcast_telemetry_packet(data)
logging.info(packet_to_string(data))
elif packet_type == WENET_PACKET_TYPES.SEC_PAYLOAD_TELEMETRY:
broadcast_telemetry_packet(data)
logging.info(packet_to_string(data))
elif packet_type == WENET_PACKET_TYPES.GPS_TELEMETRY:
broadcast_telemetry_packet(data)
logging.info(packet_to_string(data))
2017-01-05 10:42:40 +00:00
elif packet_type == WENET_PACKET_TYPES.ORIENTATION_TELEMETRY:
broadcast_telemetry_packet(data)
logging.info(packet_to_string(data))
elif packet_type == WENET_PACKET_TYPES.IMAGE_TELEMETRY:
broadcast_telemetry_packet(data)
logging.info(packet_to_string(data))
elif packet_type == WENET_PACKET_TYPES.SSDV:
# Extract packet information.
packet_info = ssdv_packet_info(data)
packet_as_string = ssdv_packet_string(data)
# Only proceed if there are no decode errors.
if packet_info['error'] != 'None':
logging.error(message['error'])
continue
if (packet_info['image_id'] != current_image) or (packet_info['callsign'] != current_callsign) :
# Attempt to decode current image if we have enough packets.
logging.info("New image - ID #%d" % packet_info['image_id'])
if current_packet_count > 0:
# Attempt to decode current image, and write out to a file.
temp_f.close()
# Run SSDV
returncode = os.system("ssdv -d rxtemp.bin ./rx_images/%s_%s_%d.jpg 2>/dev/null > /dev/null" % (current_packet_time,current_callsign,current_image))
if returncode == 1:
logging.error("ERROR: SSDV Decode failed!")
else:
logging.debug("SSDV Decoded OK!")
# Make a copy of the raw binary data.
os.system("mv rxtemp.bin ./rx_images/%s_%s_%d.bin" % (current_packet_time,current_callsign,current_image))
# Update live displays here.
trigger_gui_update("./rx_images/%s_%s_%d.jpg" % (current_packet_time,current_callsign,current_image), packet_as_string)
# Trigger upload to habhub here.
2016-03-05 10:06:28 +00:00
else:
logging.debug("Not enough packets to decode previous image.")
2016-03-05 10:06:28 +00:00
# Now set up for the new image.
current_image = packet_info['image_id']
current_callsign = packet_info['callsign']
current_packet_count = 1
current_packet_time = datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%SZ")
# Open file and write in first packet.
temp_f = open("rxtemp.bin" , "wb")
temp_f.write(data)
2016-03-05 10:06:28 +00:00
else:
# Write current packet into temp file.
temp_f.write(data)
current_packet_count += 1
if args.partialupdate != 0:
if current_packet_count % int(args.partialupdate) == 0:
# Run the SSDV decoder and push a partial update to the GUI.
temp_f.flush()
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("rxtemp.jpg", packet_as_string)
else:
logging.debug("Unknown Packet Format.")