pecanpico9/decoder/decoder.py

177 wiersze
4.4 KiB
Python
Executable File

#!/usr/bin/python3
import serial,re
import base91
import sys
import argparse
import telnetlib
import time
import sqlite3
import image
import position
# Parse arguments from terminal
parser = argparse.ArgumentParser(description='APRS/SSDV decoder')
parser.add_argument('-c', '--call', help='Callsign of the station', required=True)
parser.add_argument('-n', '--grouping', help='Amount packets that will be sent to the SSDV server in one request', default=1, type=int)
parser.add_argument('-d', '--device', help='Serial device (\'-\' for stdin)', default='-')
parser.add_argument('-b', '--baudrate', help='Baudrate for serial device', default=9600, type=int)
parser.add_argument('-s', '--server', help='SSDV server URL', default='https://ssdv.habhub.org/api/v0/packets')
args = parser.parse_args()
# Open SQLite database
sqlite = sqlite3.connect("decoder.sqlite")
sqlite.cursor().execute("""
CREATE TABLE IF NOT EXISTS position
(
call TEXT,
time INTEGER,
org TEXT,
lat FLOAT,
lon FLOAT,
alt INTEGER,
comment TEXT,
sequ INTEGER,
tel1 INTEGER,
tel2 INTEGER,
tel3 INTEGER,
tel4 INTEGER,
tel5 INTEGER,
PRIMARY KEY (call, time)
)
""")
sqlite.cursor().execute("""
CREATE TABLE IF NOT EXISTS image
(
call TEXT,
time INTEGER,
imageID INTEGER,
packetID INTEGER,
lat FLOAT,
lon FLOAT,
alt INTEGER,
data TEXT,
PRIMARY KEY (call, time, imageID, packetID)
)
""")
""" Packet handler for received APRS packets"""
def received_data(data):
# Debug
print('====================================================================================================')
print(data)
print('----------------------------------------------------------------------------------------------------')
# Parse line and detect data
# Position (.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})(.*?)\|(.*)\|
# Image (.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})I(.*)
# Log (.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})L(.*)
all = re.search("(.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})", data)
pos = re.search("(.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})(.*?)\|(.*)\|", data)
dat = re.search("(.*)\>APECAN(.*?):\/([0-9]{6}h)(.{13})(I|L)(.*)", data)
if all:
call = all.group(1)
rxer = all.group(2).split(',')[-1]
tim = all.group(3)
posi = all.group(4)
if pos: # Position packet (with comment and telementry)
comm = pos.group(5)
tel = pos.group(6)
position.insert_position(sqlite, call, tim, posi, comm, tel)
elif dat: # Data packet
typ = dat.group(5)
data_b91 = dat.group(6)
data = base91.decode(data_b91) # Decode Base91
if typ is 'I': # Image packet
image.insert_image(sqlite, rxer, call, tim, posi, data, args.server, args.grouping)
elif typ is 'L': # Log packet
position.insert_log(sqlite, call, data)
if args.device == 'I': # Source APRS-IS
print('Connect to APRS-IS')
try:
tn = telnetlib.Telnet("rotate.aprs2.net", 14580, 3)
tn.write(("user %s filter u/APECAN\n" % args.call).encode('ascii'))
print('Connected')
except Exception as e:
print('Could not connect to APRS-IS: %s' % str(e))
print('exit...')
sys.exit(1)
wdg = time.time() + 1 # Connection watchdog
buf = ''
while True:
# Read data
try:
buf += tn.read_eager().decode('ascii')
except EOFError: # Server has connection closed
wdg = 0 # Tell watchdog to restart connection
# Line handler
if '\n' in buf:
pbuf = buf.split('\n')
for i in range(len(pbuf)-1):
# Separate lines handled here
# Watchdog reload
if '# aprsc' in pbuf[i]:
print('Ping from APRS-IS')
wdg = time.time() + 30
continue
# Data handling
received_data(pbuf[i])
buf = pbuf[-1]
# Watchdog reconnection
if wdg < time.time():
print('APRS-IS connection lost... reconnect')
try:
tn = telnetlib.Telnet("rotate.aprs2.net", 14580, 3)
tn.write(("user %s filter u/APECAN\n" % args.call).encode('ascii'))
print('Connected')
wdg = time.time() + 1
except Exception as e:
print('Could not connect to APRS-IS: %s' % str(e))
print('Try again...')
time.sleep(0.1)
elif args.device is '-': # Source stdin
while True:
data = sys.stdin.readline()
received_data(data)
else: # Source Serial connection
try:
serr = serial.Serial(
port=args.device,
baudrate=args.baudrate,
)
except:
sys.stderr.write('Error: Could not open serial port\n')
sys.exit(1)
while True:
data = ''
while True:
b = serr.read(1)
if b == '\r' or b == '\n':
break
data += b
received_data(data)