Beter error detection in encoding LoRa RX frames
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
# Changes by PE1RXF
|
||||
#
|
||||
# 2022-01-23: - in encode_address() added correct handling of has_been_repeated flag '*'
|
||||
# 2022-01-28: - in encode_kiss() and encode_address(): better exeption handling for corrupted or mal-formatted APRS frames
|
||||
#
|
||||
|
||||
import struct
|
||||
@@ -56,12 +57,23 @@ def encode_address(s, final):
|
||||
# print("Message has been repeated")
|
||||
ssid = ssid[:-1]
|
||||
encoded_ssid |= 0b10000000
|
||||
|
||||
encoded_ssid |= (int(ssid) << 1) | 0b01100000 | (0b00000001 if final else 0)
|
||||
|
||||
|
||||
# If SSID was not pressent (and we added the default -0 to it), the has_been_repeated flag could be at the end of the call, so check that as well
|
||||
# Also, there is a lot of bad software around (including this code) and ignorance of the specifications (are there any specs for LoRa APRS?), so always check for the has_been_repeated flag
|
||||
if call[-1] == 42:
|
||||
call = call[:-1]
|
||||
encoded_ssid |= 0b10000000
|
||||
|
||||
# SSID should now be one or two postions long and contain a number (idealy between 0 and 15).
|
||||
if len(ssid) == 1 and ssid[0] > 47 and ssid[0] < 58:
|
||||
encoded_ssid |= (int(ssid) << 1) | 0b01100000 | (0b00000001 if final else 0)
|
||||
elif len(ssid) == 2 and ssid[0] > 47 and ssid[0] < 58 and ssid[1] > 47 and ssid[2] < 58:
|
||||
encoded_ssid |= (int(ssid) << 1) | 0b01100000 | (0b00000001 if final else 0)
|
||||
else:
|
||||
return None
|
||||
|
||||
return encoded_call + [encoded_ssid]
|
||||
|
||||
|
||||
def decode_address(data, cursor):
|
||||
(a1, a2, a3, a4, a5, a6, a7) = struct.unpack("<BBBBBBB", data[cursor:cursor + 7])
|
||||
hrr = a7 >> 5
|
||||
@@ -74,22 +86,56 @@ def decode_address(data, cursor):
|
||||
call = addr
|
||||
return (call, hrr, ext)
|
||||
|
||||
|
||||
########################################################################
|
||||
# Encode string from LoRa radio to AX.25 over KISS
|
||||
#
|
||||
# We must make no assumptions as the incomming frame could be carbage.
|
||||
# So make sure we think of everthing in order to prevent crashes.
|
||||
#
|
||||
# The original code from Thomas Kottek did a good job encoding propper APRS frames.
|
||||
# But when the frames where not what they should be, the program could crash.
|
||||
#
|
||||
########################################################################
|
||||
def encode_kiss(frame):
|
||||
# Ugly frame disassembling
|
||||
|
||||
# First check: do we have a semi column (seperator path field and data field)
|
||||
# Note that we could still be wrong: for example when the field seperator is corrupted and we now find a semi column from, lets say, an internet address in the data field...
|
||||
if not b":" in frame:
|
||||
return None
|
||||
|
||||
# Split the frame in a path field and a data field
|
||||
path = frame.split(b":")[0]
|
||||
data_field = frame[frame.find(b":") + 1:]
|
||||
|
||||
# The source address is always followed by a greather than sign, so lets see if its there.
|
||||
# There is always a change that there is another greather than sign because the frame could be corrupted...
|
||||
if not b">" in path:
|
||||
return None
|
||||
|
||||
# Split the path into a source address and a digi-path array (because digis should be seperated by commas, but again, corruption....)
|
||||
src_addr = path.split(b">")[0]
|
||||
digis = path[path.find(b">") + 1:].split(b",")
|
||||
|
||||
# destination address
|
||||
packet = encode_address(digis.pop(0).upper(), False)
|
||||
return_value = encode_address(digis.pop(0).upper(), False)
|
||||
if return_value is None:
|
||||
return None
|
||||
packet = return_value
|
||||
|
||||
# source address
|
||||
packet += encode_address(path.split(b">")[0].upper(), len(digis) == 0)
|
||||
return_value = encode_address(src_addr.upper(), len(digis) == 0)
|
||||
if return_value is None:
|
||||
return None
|
||||
packet += return_value
|
||||
|
||||
# digipeaters
|
||||
for digi in digis:
|
||||
final_addr = digis.index(digi) == len(digis) - 1
|
||||
packet += encode_address(digi.upper(), final_addr)
|
||||
return_value = encode_address(digi.upper(), final_addr)
|
||||
if return_value is None:
|
||||
return None
|
||||
packet += return_value
|
||||
|
||||
# control field
|
||||
packet += [0x03] # This is an UI frame
|
||||
# protocol ID
|
||||
|
Reference in New Issue
Block a user