diff --git a/RNS/Interfaces/RNodeInterface.py b/RNS/Interfaces/RNodeInterface.py index 14d3cf7..b11013a 100644 --- a/RNS/Interfaces/RNodeInterface.py +++ b/RNS/Interfaces/RNodeInterface.py @@ -70,7 +70,9 @@ class RNodeInterface(Interface): RSSI_OFFSET = 157 SNR_OFFSET = 128 - def __init__(self, owner, name, port, frequency = None, bandwidth = None, txpower = None, sf = None, cr = None, flow_control = False): + CALLSIGN_MAX_LEN = 32 + + def __init__(self, owner, name, port, frequency = None, bandwidth = None, txpower = None, sf = None, cr = None, flow_control = False, id_interval = None, id_callsign = None): self.serial = None self.owner = owner self.name = name @@ -90,6 +92,8 @@ class RNodeInterface(Interface): self.state = KISS.RADIO_STATE_OFF self.bitrate = 0 + self.last_id = 0 + self.r_frequency = None self.r_bandwidth = None self.r_txpower = None @@ -123,10 +127,22 @@ class RNodeInterface(Interface): RNS.log("Invalid spreading factor configured for "+str(self), RNS.LOG_ERROR) self.validcfg = False - if (self.cr < 5 or self.sf > 8): + if (self.cr < 5 or self.cr > 8): RNS.log("Invalid coding rate configured for "+str(self), RNS.LOG_ERROR) self.validcfg = False + if id_interval != None and id_callsign != None: + if (len(id_callsign.encode("utf-8")) <= RNodeInterface.CALLSIGN_MAX_LEN): + self.should_id = True + self.id_callsign = id_callsign + self.id_interval = id_interval + else: + RNS.log("The encoded ID callsign for "+str(self)+" exceeds the max length of "+str(RNodeInterface.CALLSIGN_MAX_LEN)+" bytes.", RNS.LOG_ERROR) + self.validcfg = False + else: + self.id_interval = None + self.id_callsign = None + if (not self.validcfg): raise ValueError("The configuration for "+str(self)+" contains errors, interface is offline") @@ -259,7 +275,7 @@ class RNodeInterface(Interface): try: self.bitrate = self.r_sf * ( (4.0/self.cr) / (math.pow(2,self.r_sf)/(self.r_bandwidth/1000)) ) * 1000 self.bitrate_kbps = round(self.bitrate/1000.0, 2) - RNS.log(str(self)+" On-air bitrate is now "+str(self.bitrate_kbps)+ " kbps", RNS.LOG_DEBUG) + RNS.log(str(self)+" On-air bitrate is now "+str(self.bitrate_kbps)+ " kbps", RNS.LOG_INFO) except: self.bitrate = 0 @@ -273,9 +289,17 @@ class RNodeInterface(Interface): if self.flow_control: self.interface_ready = False - data = KISS.escape(data) - frame = bytes([0xc0])+bytes([0x00])+data+bytes([0xc0]) + frame = b"" + + if self.id_interval != None and self.id_callsign != None: + if self.last_id + self.id_interval < time.time(): + self.last_id = time.time() + frame = bytes([0xc0])+bytes([0x00])+KISS.escape(self.id_callsign.encode("utf-8"))+bytes([0xc0]) + + data = KISS.escape(data) + frame += bytes([0xc0])+bytes([0x00])+data+bytes([0xc0]) written = self.serial.write(frame) + if written != len(frame): raise IOError("Serial interface only wrote "+str(written)+" bytes of "+str(len(data))) else: @@ -408,7 +432,7 @@ class RNodeInterface(Interface): elif (command == KISS.CMD_STAT_RSSI): self.r_stat_rssi = byte-RNodeInterface.RSSI_OFFSET elif (command == KISS.CMD_STAT_SNR): - self.r_stat_snr = byte-RNodeInterface.SNR_OFFSET + self.r_stat_snr = int.from_bytes(bytes([byte]), byteorder="big", signed=True) * 0.25 elif (command == KISS.CMD_RANDOM): self.r_random = byte elif (command == KISS.CMD_ERROR): diff --git a/RNS/Reticulum.py b/RNS/Reticulum.py index 959fff3..4a84456 100755 --- a/RNS/Reticulum.py +++ b/RNS/Reticulum.py @@ -248,8 +248,7 @@ class Reticulum: txtail = int(c["txtail"]) if "txtail" in c else None persistence = int(c["persistence"]) if "persistence" in c else None slottime = int(c["slottime"]) if "slottime" in c else None - flow_control = (True if c["flow_control"] == "true" else False) if "flow_control" in c else False - + flow_control = c.as_bool("flow_control") if "flow_control" in c else False port = c["port"] if "port" in c else None speed = int(c["speed"]) if "speed" in c else 9600 databits = int(c["databits"]) if "databits" in c else 8 @@ -286,8 +285,7 @@ class Reticulum: txtail = int(c["txtail"]) if "txtail" in c else None persistence = int(c["persistence"]) if "persistence" in c else None slottime = int(c["slottime"]) if "slottime" in c else None - flow_control = (True if c["flow_control"] == "true" else False) if "flow_control" in c else False - + flow_control = c.as_bool("flow_control") if "flow_control" in c else False port = c["port"] if "port" in c else None speed = int(c["speed"]) if "speed" in c else 9600 databits = int(c["databits"]) if "databits" in c else 8 @@ -330,7 +328,9 @@ class Reticulum: txpower = int(c["txpower"]) if "txpower" in c else None spreadingfactor = int(c["spreadingfactor"]) if "spreadingfactor" in c else None codingrate = int(c["codingrate"]) if "codingrate" in c else None - flow_control = (True if c["flow_control"] == "true" else False) if "flow_control" in c else False + flow_control = c.as_bool("flow_control") if "flow_control" in c else False + 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 port = c["port"] if "port" in c else None @@ -341,11 +341,14 @@ class Reticulum: RNS.Transport, name, port, - frequency, - bandwidth, - txpower, - spreadingfactor, - flow_control + frequency = frequency, + bandwidth = bandwidth, + txpower = txpower, + sf = spreadingfactor, + cr = codingrate, + flow_control = flow_control, + id_interval = id_interval, + id_callsign = id_callsign ) if "outgoing" in c and c["outgoing"].lower() == "true": @@ -355,7 +358,7 @@ class Reticulum: RNS.Transport.interfaces.append(interface) else: - RNS.log("Skipping disabled interface \""+name+"\"", RNS.LOG_VERBOSE) + RNS.log("Skipping disabled interface \""+name+"\"", RNS.LOG_NOTICE) except Exception as e: RNS.log("The interface \""+name+"\" could not be created. Check your configuration file for errors!", RNS.LOG_ERROR) @@ -533,6 +536,19 @@ loglevel = 4 # fastest, and 8 the longest range. codingrate = 5 + # You can configure the RNode to send + # out identification on the channel with + # a set interval by configuring the + # following two parameters. The trans- + # ceiver will only ID before making an + # actual transmission, and if the set + # interval has elapsed since it's last + # ID. Interval is configured in seconds + # This option is commented out and not + # used by default. + # id_callsign = MYCALL-0 + # id_interval = 600 + # An example KISS modem interface. Useful for running # Reticulum over packet radio hardware.