@@ -43,13 +43,16 @@ class KISS():
43
43
CMD_CR = 0x05
44
44
CMD_RADIO_STATE = 0x06
45
45
CMD_RADIO_LOCK = 0x07
46
+ CMD_ST_ALOCK = 0x0B
47
+ CMD_LT_ALOCK = 0x0C
46
48
CMD_DETECT = 0x08
47
49
CMD_LEAVE = 0x0A
48
50
CMD_READY = 0x0F
49
51
CMD_STAT_RX = 0x21
50
52
CMD_STAT_TX = 0x22
51
53
CMD_STAT_RSSI = 0x23
52
54
CMD_STAT_SNR = 0x24
55
+ CMD_STAT_CHTM = 0x25
53
56
CMD_BLINK = 0x30
54
57
CMD_RANDOM = 0x40
55
58
CMD_FB_EXT = 0x41
@@ -98,7 +101,7 @@ class RNodeInterface(Interface):
98
101
99
102
RECONNECT_WAIT = 5
100
103
101
- 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 ):
104
+ 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 , st_alock = None , lt_alock = None ):
102
105
if RNS .vendor .platformutils .is_android ():
103
106
raise SystemError ("Invlaid interface type. The Android-specific RNode interface must be used on Android" )
104
107
@@ -135,6 +138,8 @@ def __init__(self, owner, name, port, frequency = None, bandwidth = None, txpowe
135
138
self .cr = cr
136
139
self .state = KISS .RADIO_STATE_OFF
137
140
self .bitrate = 0
141
+ self .st_alock = st_alock
142
+ self .lt_alock = lt_alock
138
143
self .platform = None
139
144
self .display = None
140
145
self .mcu = None
@@ -158,7 +163,13 @@ def __init__(self, owner, name, port, frequency = None, bandwidth = None, txpowe
158
163
self .r_stat_tx = None
159
164
self .r_stat_rssi = None
160
165
self .r_stat_snr = None
166
+ self .r_st_alock = None
167
+ self .r_lt_alock = None
161
168
self .r_random = None
169
+ self .r_airtime_short = 0.0
170
+ self .r_airtime_long = 0.0
171
+ self .r_channel_load_short = 0.0
172
+ self .r_channel_load_long = 0.0
162
173
163
174
self .packet_queue = []
164
175
self .flow_control = flow_control
@@ -186,6 +197,14 @@ def __init__(self, owner, name, port, frequency = None, bandwidth = None, txpowe
186
197
RNS .log ("Invalid coding rate configured for " + str (self ), RNS .LOG_ERROR )
187
198
self .validcfg = False
188
199
200
+ if (self .st_alock and (self .st_alock < 0.0 or self .st_alock > 100.0 )):
201
+ RNS .log ("Invalid short-term airtime limit configured for " + str (self ), RNS .LOG_ERROR )
202
+ self .validcfg = False
203
+
204
+ if (self .lt_alock and (self .lt_alock < 0.0 or self .lt_alock > 100.0 )):
205
+ RNS .log ("Invalid long-term airtime limit configured for " + str (self ), RNS .LOG_ERROR )
206
+ self .validcfg = False
207
+
189
208
if id_interval != None and id_callsign != None :
190
209
if (len (id_callsign .encode ("utf-8" )) <= RNodeInterface .CALLSIGN_MAX_LEN ):
191
210
self .should_id = True
@@ -281,6 +300,8 @@ def initRadio(self):
281
300
self .setTXPower ()
282
301
self .setSpreadingFactor ()
283
302
self .setCodingRate ()
303
+ self .setSTALock ()
304
+ self .setLTALock ()
284
305
self .setRadioState (KISS .RADIO_STATE_ON )
285
306
286
307
def detect (self ):
@@ -385,6 +406,30 @@ def setCodingRate(self):
385
406
if written != len (kiss_command ):
386
407
raise IOError ("An IO error occurred while configuring coding rate for " + str (self ))
387
408
409
+ def setSTALock (self ):
410
+ if self .st_alock != None :
411
+ at = int (self .st_alock * 100 )
412
+ c1 = at >> 8 & 0xFF
413
+ c2 = at & 0xFF
414
+ data = KISS .escape (bytes ([c1 ])+ bytes ([c2 ]))
415
+
416
+ kiss_command = bytes ([KISS .FEND ])+ bytes ([KISS .CMD_ST_ALOCK ])+ data + bytes ([KISS .FEND ])
417
+ written = self .serial .write (kiss_command )
418
+ if written != len (kiss_command ):
419
+ raise IOError ("An IO error occurred while configuring short-term airtime limit for " + str (self ))
420
+
421
+ def setLTALock (self ):
422
+ if self .lt_alock != None :
423
+ at = int (self .lt_alock * 100 )
424
+ c1 = at >> 8 & 0xFF
425
+ c2 = at & 0xFF
426
+ data = KISS .escape (bytes ([c1 ])+ bytes ([c2 ]))
427
+
428
+ kiss_command = bytes ([KISS .FEND ])+ bytes ([KISS .CMD_LT_ALOCK ])+ data + bytes ([KISS .FEND ])
429
+ written = self .serial .write (kiss_command )
430
+ if written != len (kiss_command ):
431
+ raise IOError ("An IO error occurred while configuring long-term airtime limit for " + str (self ))
432
+
388
433
def setRadioState (self , state ):
389
434
self .state = state
390
435
kiss_command = bytes ([KISS .FEND ])+ bytes ([KISS .CMD_RADIO_STATE ])+ bytes ([state ])+ bytes ([KISS .FEND ])
@@ -622,6 +667,57 @@ def readLoop(self):
622
667
self .r_stat_rssi = byte - RNodeInterface .RSSI_OFFSET
623
668
elif (command == KISS .CMD_STAT_SNR ):
624
669
self .r_stat_snr = int .from_bytes (bytes ([byte ]), byteorder = "big" , signed = True ) * 0.25
670
+ elif (command == KISS .CMD_ST_ALOCK ):
671
+ if (byte == KISS .FESC ):
672
+ escape = True
673
+ else :
674
+ if (escape ):
675
+ if (byte == KISS .TFEND ):
676
+ byte = KISS .FEND
677
+ if (byte == KISS .TFESC ):
678
+ byte = KISS .FESC
679
+ escape = False
680
+ command_buffer = command_buffer + bytes ([byte ])
681
+ if (len (command_buffer ) == 2 ):
682
+ at = command_buffer [0 ] << 8 | command_buffer [1 ]
683
+ self .r_st_alock = at / 100.0
684
+ RNS .log (str (self )+ " Radio reporting short-term airtime limit is " + str (self .r_st_alock )+ "%" , RNS .LOG_DEBUG )
685
+ elif (command == KISS .CMD_LT_ALOCK ):
686
+ if (byte == KISS .FESC ):
687
+ escape = True
688
+ else :
689
+ if (escape ):
690
+ if (byte == KISS .TFEND ):
691
+ byte = KISS .FEND
692
+ if (byte == KISS .TFESC ):
693
+ byte = KISS .FESC
694
+ escape = False
695
+ command_buffer = command_buffer + bytes ([byte ])
696
+ if (len (command_buffer ) == 2 ):
697
+ at = command_buffer [0 ] << 8 | command_buffer [1 ]
698
+ self .r_lt_alock = at / 100.0
699
+ RNS .log (str (self )+ " Radio reporting long-term airtime limit is " + str (self .r_lt_alock )+ "%" , RNS .LOG_DEBUG )
700
+ elif (command == KISS .CMD_STAT_CHTM ):
701
+ if (byte == KISS .FESC ):
702
+ escape = True
703
+ else :
704
+ if (escape ):
705
+ if (byte == KISS .TFEND ):
706
+ byte = KISS .FEND
707
+ if (byte == KISS .TFESC ):
708
+ byte = KISS .FESC
709
+ escape = False
710
+ command_buffer = command_buffer + bytes ([byte ])
711
+ if (len (command_buffer ) == 8 ):
712
+ ats = command_buffer [0 ] << 8 | command_buffer [1 ]
713
+ atl = command_buffer [2 ] << 8 | command_buffer [3 ]
714
+ cus = command_buffer [4 ] << 8 | command_buffer [5 ]
715
+ cul = command_buffer [6 ] << 8 | command_buffer [7 ]
716
+
717
+ self .r_airtime_short = ats / 100.0
718
+ self .r_airtime_long = atl / 100.0
719
+ self .r_channel_load_short = cus / 100.0
720
+ self .r_channel_load_long = cul / 100.0
625
721
elif (command == KISS .CMD_RANDOM ):
626
722
self .r_random = byte
627
723
elif (command == KISS .CMD_PLATFORM ):
0 commit comments