Implemented ID beaconing on RNode and KISS interfaces
This commit is contained in:
parent
88a956b4f5
commit
f275065b40
|
@ -39,7 +39,7 @@ class KISSInterface(Interface):
|
|||
stopbits = None
|
||||
serial = None
|
||||
|
||||
def __init__(self, owner, name, port, speed, databits, parity, stopbits, preamble, txtail, persistence, slottime, flow_control):
|
||||
def __init__(self, owner, name, port, speed, databits, parity, stopbits, preamble, txtail, persistence, slottime, flow_control, beacon_interval, beacon_data):
|
||||
self.serial = None
|
||||
self.owner = owner
|
||||
self.name = name
|
||||
|
@ -50,10 +50,15 @@ class KISSInterface(Interface):
|
|||
self.stopbits = stopbits
|
||||
self.timeout = 100
|
||||
self.online = False
|
||||
self.beacon_i = beacon_interval
|
||||
self.beacon_d = beacon_data.encode("utf-8")
|
||||
self.first_tx = None
|
||||
|
||||
self.packet_queue = []
|
||||
self.flow_control = flow_control
|
||||
self.interface_ready = False
|
||||
self.flow_control_timeout = 10
|
||||
self.flow_control_locked = time.time()
|
||||
|
||||
self.preamble = preamble if preamble != None else 350;
|
||||
self.txtail = txtail if txtail != None else 20;
|
||||
|
@ -174,12 +179,20 @@ class KISSInterface(Interface):
|
|||
if self.interface_ready:
|
||||
if self.flow_control:
|
||||
self.interface_ready = False
|
||||
self.flow_control_locked = time.time()
|
||||
|
||||
data = data.replace(bytes([0xdb]), bytes([0xdb])+bytes([0xdd]))
|
||||
data = data.replace(bytes([0xc0]), bytes([0xdb])+bytes([0xdc]))
|
||||
frame = bytes([KISS.FEND])+bytes([0x00])+data+bytes([KISS.FEND])
|
||||
|
||||
written = self.serial.write(frame)
|
||||
|
||||
if data == self.beacon_d:
|
||||
self.first_tx = None
|
||||
else:
|
||||
if self.first_tx == None:
|
||||
self.first_tx = time.time()
|
||||
|
||||
if written != len(frame):
|
||||
raise IOError("Serial interface only wrote "+str(written)+" bytes of "+str(len(data)))
|
||||
|
||||
|
@ -235,8 +248,6 @@ class KISSInterface(Interface):
|
|||
escape = False
|
||||
data_buffer = data_buffer+bytes([byte])
|
||||
elif (command == KISS.CMD_READY):
|
||||
# TODO: add timeout and reset if ready
|
||||
# command never arrives
|
||||
self.process_queue()
|
||||
else:
|
||||
time_since_last = int(time.time()*1000) - last_read_ms
|
||||
|
@ -247,6 +258,19 @@ class KISSInterface(Interface):
|
|||
escape = False
|
||||
sleep(0.08)
|
||||
|
||||
if self.flow_control:
|
||||
if not self.interface_ready:
|
||||
if time.time() > self.flow_control_locked + self.flow_control_timeout:
|
||||
RNS.log("Interface "+str(self)+" is unlocking flow control due to time-out. This should not happen. Your hardware might have missed a flow-control READY command.", RNS.LOG_WARNING)
|
||||
self.process_queue()
|
||||
|
||||
if self.beacon_i != None and self.beacon_d != None:
|
||||
if self.first_tx != None:
|
||||
if time.time() > self.first_tx + self.beacon_i:
|
||||
RNS.log("Interface "+str(self)+" is transmitting beacon data: "+str(self.beacon_d.decode("utf-8")), RNS.LOG_DEBUG)
|
||||
self.first_tx = None
|
||||
self.processOutgoing(self.beacon_d)
|
||||
|
||||
except Exception as e:
|
||||
self.online = False
|
||||
RNS.log("A serial port error occurred, the contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||
|
|
|
@ -92,6 +92,7 @@ class RNodeInterface(Interface):
|
|||
self.bitrate = 0
|
||||
|
||||
self.last_id = 0
|
||||
self.first_tx = None
|
||||
|
||||
self.r_frequency = None
|
||||
self.r_bandwidth = None
|
||||
|
@ -133,7 +134,7 @@ class RNodeInterface(Interface):
|
|||
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_callsign = id_callsign.encode("utf-8")
|
||||
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)
|
||||
|
@ -286,15 +287,15 @@ class RNodeInterface(Interface):
|
|||
if self.flow_control:
|
||||
self.interface_ready = False
|
||||
|
||||
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])
|
||||
if data == self.id_callsign:
|
||||
self.first_tx = None
|
||||
else:
|
||||
if self.first_tx == None:
|
||||
self.first_tx = time.time()
|
||||
|
||||
data = KISS.escape(data)
|
||||
frame += bytes([0xc0])+bytes([0x00])+data+bytes([0xc0])
|
||||
frame = bytes([0xc0])+bytes([0x00])+data+bytes([0xc0])
|
||||
|
||||
written = self.serial.write(frame)
|
||||
|
||||
if written != len(frame):
|
||||
|
@ -450,6 +451,13 @@ class RNodeInterface(Interface):
|
|||
in_frame = False
|
||||
command = KISS.CMD_UNKNOWN
|
||||
escape = False
|
||||
|
||||
if self.id_interval != None and self.id_callsign != None:
|
||||
if self.first_tx != None:
|
||||
if time.time() > self.first_tx + self.id_interval:
|
||||
RNS.log("Interface "+str(self)+" is transmitting beacon data: "+str(self.id_callsign.decode("utf-8")), RNS.LOG_DEBUG)
|
||||
self.processOutgoing(self.id_callsign)
|
||||
|
||||
sleep(0.08)
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
@ -256,6 +256,8 @@ class Reticulum:
|
|||
databits = int(c["databits"]) if "databits" in c else 8
|
||||
parity = c["parity"] if "parity" in c else "N"
|
||||
stopbits = int(c["stopbits"]) if "stopbits" in c else 1
|
||||
beacon_interval = int(c["id_interval"]) if "id_interval" in c else None
|
||||
beacon_data = c["id_callsign"] if "id_callsign" in c else None
|
||||
|
||||
if port == None:
|
||||
raise ValueError("No port specified for serial interface")
|
||||
|
@ -272,7 +274,9 @@ class Reticulum:
|
|||
txtail,
|
||||
persistence,
|
||||
slottime,
|
||||
flow_control
|
||||
flow_control,
|
||||
beacon_interval,
|
||||
beacon_data
|
||||
)
|
||||
|
||||
if "outgoing" in c and c["outgoing"].lower() == "true":
|
||||
|
@ -542,16 +546,22 @@ loglevel = 4
|
|||
# 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
|
||||
# ceiver will only ID if the set
|
||||
# interval has elapsed since it's last
|
||||
# ID. Interval is configured in seconds
|
||||
# actual transmission. The interval is
|
||||
# configured in seconds.
|
||||
# This option is commented out and not
|
||||
# used by default.
|
||||
# id_callsign = MYCALL-0
|
||||
# id_interval = 600
|
||||
|
||||
|
||||
# For certain homebrew RNode interfaces
|
||||
# with low amounts of RAM, using packet
|
||||
# flow control can be useful. By default
|
||||
# it is disabled.
|
||||
flow_control = False
|
||||
|
||||
|
||||
# An example KISS modem interface. Useful for running
|
||||
# Reticulum over packet radio hardware.
|
||||
|
||||
|
@ -574,11 +584,6 @@ loglevel = 4
|
|||
parity = none
|
||||
stopbits = 1
|
||||
|
||||
# Whether to use KISS flow-control.
|
||||
# This is useful for modems with a
|
||||
# small internal packet buffer.
|
||||
flow_control = false
|
||||
|
||||
# Set the modem preamble. A 150ms
|
||||
# preamble should be a reasonable
|
||||
# default, but may need to be
|
||||
|
@ -597,6 +602,25 @@ loglevel = 4
|
|||
persistence = 200
|
||||
slottime = 20
|
||||
|
||||
# You can configure the interface to send
|
||||
# out identification on the channel with
|
||||
# a set interval by configuring the
|
||||
# following two parameters. The KISS
|
||||
# interface will only ID if the set
|
||||
# interval has elapsed since it's last
|
||||
# actual transmission. The interval is
|
||||
# configured in seconds.
|
||||
# This option is commented out and not
|
||||
# used by default.
|
||||
# id_callsign = MYCALL-0
|
||||
# id_interval = 600
|
||||
|
||||
# Whether to use KISS flow-control.
|
||||
# This is useful for modems that have
|
||||
# a small internal packet buffer, but
|
||||
# support packet flow control instead.
|
||||
flow_control = false
|
||||
|
||||
|
||||
# If you're using Reticulum on amateur radio spectrum,
|
||||
# you might want to use the AX.25 KISS interface. This
|
||||
|
@ -607,6 +631,9 @@ loglevel = 4
|
|||
# Only do this if you really need to! Reticulum doesn't
|
||||
# need the AX.25 layer for anything, and it incurs extra
|
||||
# overhead on every packet to encapsulate in AX.25.
|
||||
#
|
||||
# A more efficient way is to use the plain KISS interface
|
||||
# with the beaconing functionality described above.
|
||||
|
||||
[[Packet Radio AX.25 KISS Interface]]
|
||||
type = AX25KISSInterface
|
||||
|
|
2
setup.py
2
setup.py
|
@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|||
|
||||
setuptools.setup(
|
||||
name="rns",
|
||||
version="0.1.7",
|
||||
version="0.1.8",
|
||||
author="Mark Qvist",
|
||||
author_email="mark@unsigned.io",
|
||||
description="Self-configuring, encrypted and resilient mesh networking stack for LoRa, packet radio, WiFi and everything in between",
|
||||
|
|
Loading…
Reference in New Issue