Added dynamic config file support

This commit is contained in:
jacob.eva 2024-06-04 08:27:55 +01:00
parent 276359bf99
commit d34cf68736
No known key found for this signature in database
GPG Key ID: 0B92E083BBCCAA1E
2 changed files with 86 additions and 54 deletions

View File

@ -28,9 +28,6 @@ import time
import math import math
import RNS import RNS
# debug
import traceback
class KISS(): class KISS():
FEND = 0xC0 FEND = 0xC0
FESC = 0xDB FESC = 0xDB
@ -172,6 +169,17 @@ class KISS():
case KISS.CMD_INT11_DATA: case KISS.CMD_INT11_DATA:
return 11 return 11
def interface_type_to_str(interface_type):
match interface_type:
case KISS.SX1262:
return "SX1262"
case KISS.SX1276:
return "SX1276"
case KISS.SX1278:
return "SX1278"
case KISS.SX1280:
return "SX1280"
@staticmethod @staticmethod
def escape(data): def escape(data):
data = data.replace(bytes([0xdb]), bytes([0xdb, 0xdd])) data = data.replace(bytes([0xdb]), bytes([0xdb, 0xdd]))
@ -191,6 +199,8 @@ class RNodeMultiInterface(Interface):
RECONNECT_WAIT = 5 RECONNECT_WAIT = 5
MAX_SUBINTERFACES = 11
def __init__(self, owner, name, port, subint_config, id_interval = None, id_callsign = None): def __init__(self, owner, name, port, subint_config, id_interval = None, id_callsign = None):
if RNS.vendor.platformutils.is_android(): if RNS.vendor.platformutils.is_android():
raise SystemError("Invalid interface type. The Android-specific RNode interface must be used on Android") raise SystemError("Invalid interface type. The Android-specific RNode interface must be used on Android")
@ -236,7 +246,7 @@ class RNodeMultiInterface(Interface):
self.first_tx = None self.first_tx = None
self.reconnect_w = RNodeMultiInterface.RECONNECT_WAIT self.reconnect_w = RNodeMultiInterface.RECONNECT_WAIT
self.subinterfaces = [] self.subinterfaces = [0] * RNodeMultiInterface.MAX_SUBINTERFACES
self.subinterface_indexes = [] self.subinterface_indexes = []
self.subinterface_types = [] self.subinterface_types = []
self.subint_config = subint_config self.subint_config = subint_config
@ -330,22 +340,31 @@ class RNodeMultiInterface(Interface):
RNS.log("Serial port "+self.port+" is now open") RNS.log("Serial port "+self.port+" is now open")
RNS.log("Creating subinterfaces...", RNS.LOG_VERBOSE) RNS.log("Creating subinterfaces...", RNS.LOG_VERBOSE)
for subint in self.subinterface_indexes: index = None
for subint in self.subint_config:
for subint_type in self.subinterface_types:
if subint[0] == subint_type:
index = self.subinterface_types.index(subint_type)
# The interface type configured is not present on the RNode
if index is None:
raise ValueError("Interface type \""+subint[0]+"\" is not available on "+self.name)
# interface will add itself to the subinterfaces list automatically # interface will add itself to the subinterfaces list automatically
interface = (RNodeSubInterface( interface = RNodeSubInterface(
RNS.Transport, RNS.Transport,
self, self,
subint, index,
self.subinterface_types[subint], subint[0],
frequency = self.subint_config[subint][0], frequency = subint[1],
bandwidth = self.subint_config[subint][1], bandwidth = subint[2],
txpower = self.subint_config[subint][2], txpower = subint[3],
sf = self.subint_config[subint][3], sf = subint[4],
cr = self.subint_config[subint][4], cr = subint[5],
flow_control=self.subint_config[subint][5], flow_control=subint[6],
st_alock=self.subint_config[subint][6], st_alock=subint[7],
lt_alock=self.subint_config[subint][7] lt_alock=subint[8]
)) )
interface.OUT = True interface.OUT = True
interface.IN = self.IN interface.IN = self.IN
@ -816,7 +835,7 @@ class RNodeMultiInterface(Interface):
if (len(command_buffer) == 2): if (len(command_buffer) == 2):
# add the interface to the back of the lists # add the interface to the back of the lists
self.subinterface_indexes.append(command_buffer[0]) self.subinterface_indexes.append(command_buffer[0])
self.subinterface_types.append(command_buffer[1]) self.subinterface_types.append(KISS.interface_type_to_str(command_buffer[1]))
command_buffer = b"" command_buffer = b""
else: else:
@ -904,7 +923,7 @@ class RNodeSubInterface(Interface):
Q_SNR_MAX = 6 Q_SNR_MAX = 6
Q_SNR_STEP = 2 Q_SNR_STEP = 2
def __init__(self, owner, parent_interface, index, subinterface_type, frequency = None, bandwidth = None, txpower = None, sf = None, cr = None, flow_control = False, st_alock = None, lt_alock = None,): def __init__(self, owner, parent_interface, index, interface_type, frequency = None, bandwidth = None, txpower = None, sf = None, cr = None, flow_control = False, st_alock = None, lt_alock = None,):
if RNS.vendor.platformutils.is_android(): if RNS.vendor.platformutils.is_android():
raise SystemError("Invalid interface type. The Android-specific RNode interface must be used on Android") raise SystemError("Invalid interface type. The Android-specific RNode interface must be used on Android")
@ -959,21 +978,11 @@ class RNodeSubInterface(Interface):
sel_cmd = KISS.CMD_SEL_INT0 sel_cmd = KISS.CMD_SEL_INT0
data_cmd= KISS.CMD_INT0_DATA data_cmd= KISS.CMD_INT0_DATA
match subinterface_type:
case KISS.SX1262:
subinterface = "SX1262"
case KISS.SX1276:
subinterface = "SX1276"
case KISS.SX1278:
subinterface = "SX1278"
case KISS.SX1280:
subinterface = "SX1280"
self.owner = owner self.owner = owner
self.index = index self.index = index
self.sel_cmd = sel_cmd self.sel_cmd = sel_cmd
self.data_cmd = data_cmd self.data_cmd = data_cmd
self.subinterface= subinterface self.interface_type= interface_type
self.flow_control= flow_control self.flow_control= flow_control
self.speed = 115200 self.speed = 115200
self.databits = 8 self.databits = 8
@ -1028,7 +1037,7 @@ class RNodeSubInterface(Interface):
self.parent_interface = parent_interface self.parent_interface = parent_interface
# add this interface to the subinterfaces array # add this interface to the subinterfaces array
self.parent_interface.subinterfaces.append(self) self.parent_interface.subinterfaces.insert(index, self)
self.validcfg = True self.validcfg = True
if (self.frequency < RNodeSubInterface.FREQ_MIN or self.frequency > RNodeSubInterface.FREQ_MAX): if (self.frequency < RNodeSubInterface.FREQ_MIN or self.frequency > RNodeSubInterface.FREQ_MAX):
@ -1184,4 +1193,4 @@ class RNodeSubInterface(Interface):
self.interface_ready = True self.interface_ready = True
def __str__(self): def __str__(self):
return self.parent_interface.name+"["+self.subinterface+":"+str(self.index)+"]" return self.parent_interface.name+"["+self.interface_type+":"+str(self.index)+"]"

View File

@ -934,44 +934,67 @@ class Reticulum:
if c["type"] == "RNodeMultiInterface": if c["type"] == "RNodeMultiInterface":
count = 0 count = 0
enabled_count = 0
# Count how many interfaces are in the file
for subinterface in c: for subinterface in c:
# if the retrieved entry is not a string, it must be a dictionary, which is what we want # if the retrieved entry is not a string, it must be a dictionary, which is what we want
if not isinstance(c[subinterface], str): if not isinstance(c[subinterface], str):
count += 1 count += 1
# create an array with a row for each subinterface # Count how many interfaces are enabled to allow for appropriate matrix sizing
subint_config = [[0 for x in range(8)] for y in range(count)]
subint_index = 0
for subinterface in c: for subinterface in c:
# if the retrieved entry is not a string, it must be a dictionary, which is what we want # if the retrieved entry is not a string, it must be a dictionary, which is what we want
if not isinstance(c[subinterface], str): if not isinstance(c[subinterface], str):
subinterface_config = self.config["interfaces"][name][subinterface] subinterface_config = self.config["interfaces"][name][subinterface]
if (("interface_enabled" in subinterface_config) and subinterface_config.as_bool("interface_enabled") == True) or (("enabled" in c) and c.as_bool("enabled") == True):
enabled_count += 1
frequency = int(subinterface_config["frequency"]) if "frequency" in subinterface_config else None # Create an array with a row for each subinterface
subint_config[subint_index][0] = frequency subint_config = [[0 for x in range(9)] for y in range(enabled_count)]
bandwidth = int(subinterface_config["bandwidth"]) if "bandwidth" in subinterface_config else None subint_index = 0
subint_config[subint_index][1] = bandwidth
txpower = int(subinterface_config["txpower"]) if "txpower" in subinterface_config else None for subinterface in c:
subint_config[subint_index][2] = txpower # If the retrieved entry is not a string, it must be a dictionary, which is what we want
spreadingfactor = int(subinterface_config["spreadingfactor"]) if "spreadingfactor" in subinterface_config else None if not isinstance(c[subinterface], str):
subint_config[subint_index][3] = spreadingfactor subinterface_config = self.config["interfaces"][name][subinterface]
codingrate = int(subinterface_config["codingrate"]) if "codingrate" in subinterface_config else None if (("interface_enabled" in subinterface_config) and subinterface_config.as_bool("interface_enabled") == True) or (("enabled" in c) and c.as_bool("enabled") == True):
subint_config[subint_index][4] = codingrate subint_type = subinterface_config["type"] if "type" in subinterface_config else None
flow_control = subinterface_config.as_bool("flow_control") if "flow_control" in subinterface_config else False if subint_type is None:
subint_config[subint_index][5] = flow_control raise ValueError("No type defined for "+name+" subinterface!")
st_alock = float(subinterface_config["airtime_limit_short"]) if "airtime_limit_short" in subinterface_config else None
subint_config[subint_index][6] = st_alock subint_config[subint_index][0] = subint_type
lt_alock = float(subinterface_config["airtime_limit_long"]) if "airtime_limit_long" in subinterface_config else None frequency = int(subinterface_config["frequency"]) if "frequency" in subinterface_config else None
subint_config[subint_index][7] = lt_alock subint_config[subint_index][1] = frequency
subint_index += 1 bandwidth = int(subinterface_config["bandwidth"]) if "bandwidth" in subinterface_config else None
subint_config[subint_index][2] = bandwidth
txpower = int(subinterface_config["txpower"]) if "txpower" in subinterface_config else None
subint_config[subint_index][3] = txpower
spreadingfactor = int(subinterface_config["spreadingfactor"]) if "spreadingfactor" in subinterface_config else None
subint_config[subint_index][4] = spreadingfactor
codingrate = int(subinterface_config["codingrate"]) if "codingrate" in subinterface_config else None
subint_config[subint_index][5] = codingrate
flow_control = subinterface_config.as_bool("flow_control") if "flow_control" in subinterface_config else False
subint_config[subint_index][6] = flow_control
st_alock = float(subinterface_config["airtime_limit_short"]) if "airtime_limit_short" in subinterface_config else None
subint_config[subint_index][7] = st_alock
lt_alock = float(subinterface_config["airtime_limit_long"]) if "airtime_limit_long" in subinterface_config else None
subint_config[subint_index][8] = lt_alock
subint_index += 1
# if no subinterfaces are defined
if count == 0:
raise ValueError("No subinterfaces configured for "+name)
# if no subinterfaces are enabled
elif enabled_count == 0:
raise ValueError("No subinterfaces enabled for "+name)
id_interval = int(c["id_interval"]) if "id_interval" in c else None id_interval = int(c["id_interval"]) if "id_interval" in c else None
id_callsign = c["id_callsign"] if "id_callsign" in c else None id_callsign = c["id_callsign"] if "id_callsign" in c else None
port = c["port"] if "port" in c else None port = c["port"] if "port" in c else None
if port == None: if port == None:
raise ValueError("No port specified for RNodeMulti interface") raise ValueError("No port specified for "+name)
interface = RNodeMultiInterface.RNodeMultiInterface( interface = RNodeMultiInterface.RNodeMultiInterface(
RNS.Transport, RNS.Transport,