Benutzer-Werkzeuge

Webseiten-Werkzeuge


users:dl9sau:programme:decode_ft8_telemetry_datagram

FT8 Telemetry Datagram Decoder, written in python

#!/usr/bin/python

# decode my ft8 data telegram format
# (c) 2021 Thomas dl9sau  <dl9sau@darc.de>
# License: gpl

import sys

def i_base36_to_char(n):
  if not ( ( chr(n)>= 0 and chr(n) <= '9' ) or ( chr(n)>= 'A' or chr(n) <= 'Z' ) ) :
    raise TypeError("Error whle parsing input: only digits and numbers are valid.")
  if n <10:
    return chr(ord('0') + n)
  else:
    return chr(ord('A') + n-10)

#-----------------------------------------------------------------------------

def char_base36_to_i(c):
  if not ( ( c>= '0' and c <= '9' ) or ( c>= 'A' or c <= 'Z' ) ) :
    raise TypeError("Error whle parsing input: only digits and numbers are valid.")
  if c <= '9':
    return ord(c) - ord('0')
  else:
    return ord(c) - ord('A') + 10

#-----------------------------------------------------------------------------

def decode_telegram(msgnum, data):
  global last_msgnum, locatorA, locatorB, locatorC, altitudeA, call_ssid, last_call_ssid

  if last_msgnum>= msgnum or not call_ssid == last_call_ssid:
    locatorA = ""
    locatorB = ""
    locatorC = ""
    altitudeA="?"
  last_msgnum = msgnum

  if msgnum == 0:
    locatorA = data
    print "Locator: %sxxxxxxxx" % locatorA
  elif msgnum == 1:
    locatorB = data
    if locatorA == "":
      tmpA = "xxxx"
    else:
      tmpA = locatorA
    print "Locator: %s%sxxxx" % (tmpA, locatorB)
  elif msgnum == 2:
    if locatorA == "":
      tmpA = "xxxx"
    else:
      tmpA = locatorA
    if locatorB == "":
      tmpB = "xxxx"
    else:
      tmpB = locatorB
    locatorC = data
    print "Locator: %s%s%s" % ( tmpA, tmpB, locatorC )

  elif msgnum == 3:
    sats = ord(data[0]) - ord('A')
    print "sats: %d" % (sats % 13)
    if sats> 12:
      print "sat signal not valid"
    else:
      print "sat signal valid"
    txc = char_base36_to_i(data[1]) *36 + char_base36_to_i(data[2])
    print "Telegram blocks sent: %d" % txc
    alt_c = data[3]
    if alt_c == 'A':
      print "Altitude: 100.000 feet + value from next frame (4)"
      altitudeA="1"
    elif alt_c == 'B':
      print "Negative altitute follows (or invalid measurement (BZZZZ)"
      altitudeA="-"
    elif alt_c == '0':
      print "Altitude: <10.000 feet"
      altitudeA=""
    else:
      print "Altitude: %c * 10.000 feet + value from next frame (4)" % alt_c
      altitudeA=alt_c

  elif msgnum == 4:
    if (altitudeA == "" or altitudeA == "-") and data == "ZZZZ":
      print "Altitude: invalid measurement (Keyword BZZZ)"
    else:
      print "Altitude: %s%s feet" % (altitudeA , data)
      if not altitudeA == "":
        print "          ^came frome previous telegram"

  elif msgnum == 5:
    print "Speed: %d kn" % int(data[0:2])
    if data[2:] == "ZZ":
      print "Course: invaild measurement"
    else:
      print "Course: %d Deg" % (char_base36_to_i(data[2]) * 36 + char_base36_to_i(data[3]))

  elif msgnum == 6:
    print "Pressure: %d hPa" % (char_base36_to_i(data[0]) * 36 + char_base36_to_i(data[1]))
    c = int( (char_base36_to_i(data[2]) * 36 + char_base36_to_i(data[3])) )
    c = (c - 695) * 1.25
    cA = c / 10
    cB = c % 10
    print "Temperature: %d.%d C" % ( cA, cB )

  elif msgnum == 7:
    v = int( (char_base36_to_i(data[0]) * 36 + char_base36_to_i(data[1])) ) * 2
    vA = v / 100
    vB = v % 100
    print "Voltage: %d.%2.2d V" % (vA, vB)
    print "PEP: %d dBm" % int(data[2:])

#-----------------------------------------------------------------------------

def ft8_hex_to_string(buf, outlen):
  s = ""
  if not buf or buf == "":
    return s
  u32 = int(buf, 16)
  for i in range(0, outlen):
    n = u32 % 37
    if n == 36:
      s = " " + s
    else:
      s = i_base36_to_char(n) + s
    u32 = u32 / 37
  return s

#-----------------------------------------------------------------------------

def process_input(msg):
  global last_msgnum, locatorA, locatorB, locatorC, altitudeA, call_ssid, last_call_ssid

  call = ""
  hexcall = ""
  aprs_symbol = ""
  aprs_alt_table = False
  ssid = 0
  msgnum = 0
  data = ""
  hexdata = ""

  plain_text__do_not_process = False

  if msg.find(' ')> 0:
    msgnum = int(msg[2])
    data, call = msg.split()
    if not len(data) == 6 or not (data[0] == 'Q' or data[0] == '0'):
      if len(data) == 4 and data[0]> 9 and data[0] <= 'R':
        print "Locator: %s" % data
        locatorA = data
        locatorB = ""
        locatorC = ""
        altitudeA = "?"
        last_msgnum = 0
        plain_text__do_not_process = True
    else:
      if (msg[0] == 'Q'):
        ssid = 1
      data = data[1] + data[3:]
  elif len(msg) == 18 and msg.find(' ') == -1:
    hexcall = msg[0:8]
    call = ft8_hex_to_string(hexcall, 6)
    ssid = int(msg[8], 16)
    i = int(msg[9:11], 16)
    if (i> 127):
      aprs_alt_table = True
      i = i-128
    aprs_symbol = chr(i)
    msgnum = int(msg[17], 16)
    hexdata = msg[11:17]
    # pos 0: upper 3 bits re-used. 2 of them for protocol version
    ft8_protocol_version = ((int(hexdata[0], 16)>> 1) % 4 + 1)
    print "ft protocol version: %d" % ft8_protocol_version
    c = "%d" % (int(hexdata[0], 16) & 0x01)
    hexdata = c + hexdata[1:]
    data = ft8_hex_to_string(hexdata, 4)

  call_ssid = "%s-%d" % (call, ssid)

  print "hexcall: " + hexcall
  print "call: " + call
  print "ssid: %d " % ssid
  print "aprs symbol: %s" % aprs_symbol
  if aprs_alt_table:
    print "aprs alt table"
  else:
    print "aprs primary table"
  print "msgnum: %d" % msgnum
  print "hexdata: " + hexdata
  print "data: " + data

  if not plain_text__do_not_process:
    decode_telegram(msgnum, data)

  print "EOM"
  print

  last_call_ssid = call_ssid

#-----------------------------------------------------------------------------

# main()

last_msgnum = -1
locatorA = ""
locatorB = ""
locatorC = ""
altitudeA = "?"
call_ssid = ""
last_call_ssid = ""

argv = sys.argv[1:]
if len(argv)> 0:
  while len(argv)> 0:
    msg = argv[0]
    process_input(msg)
    argv = argv[1:]

else:
  while True:
    msg = sys.stdin.readline().strip()
    if msg == "":
      break
    process_input(msg)
users/dl9sau/programme/decode_ft8_telemetry_datagram.txt · Zuletzt geändert: 2021/08/21 12:38 von dl9sau