27
27
28
28
import time
29
29
from random import randint
30
- from micropython import const
30
+
31
31
import adafruit_bus_device .spi_device
32
+ from micropython import const
33
+
32
34
from adafruit_tinylora .adafruit_tinylora_encryption import AES
33
35
36
+ try : # typing
37
+ from typing import Annotated , Optional , TypeAlias , Union
38
+
39
+ import busio .SPI
40
+ import digitalio .DigitalInOut
41
+ from typing_extensions import Self # Python <3.11
42
+
43
+ # type aliases
44
+ bytearray2 : TypeAlias = Annotated [bytearray , 2 ]
45
+ bytearray4 : TypeAlias = Annotated [bytearray , 4 ]
46
+ bytearray16 : TypeAlias = Annotated [bytearray , 16 ]
47
+
48
+ registeraddress : TypeAlias = Union [const , int ]
49
+ except ImportError :
50
+ pass
51
+
52
+
34
53
__version__ = "0.0.0+auto.0"
35
54
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_TinyLoRa.git"
36
55
70
89
class TTN :
71
90
"""TTN Class"""
72
91
73
- def __init__ (self , dev_address , net_key , app_key , country = "US" ):
92
+ def __init__ (
93
+ self ,
94
+ dev_address : bytearray4 ,
95
+ net_key : bytearray16 ,
96
+ app_key : bytearray16 ,
97
+ country : str = "US" ,
98
+ ):
74
99
"""Interface for TheThingsNetwork
75
100
:param bytearray dev_address: TTN Device Address.
76
101
:param bytearray net_key: TTN Network Key.
@@ -83,22 +108,22 @@ def __init__(self, dev_address, net_key, app_key, country="US"):
83
108
self .region = country
84
109
85
110
@property
86
- def country (self ):
111
+ def country (self ) -> str :
87
112
"""Returns the TTN Frequency Country."""
88
113
return self .region
89
114
90
115
@property
91
- def device_address (self ):
116
+ def device_address (self ) -> bytearray4 :
92
117
"""Returns the TTN Device Address."""
93
118
return self .dev_addr
94
119
95
120
@property
96
- def application_key (self ):
121
+ def application_key (self ) -> bytearray16 :
97
122
"""Returns the TTN Application Key."""
98
123
return self .app_key
99
124
100
125
@property
101
- def network_key (self ):
126
+ def network_key (self ) -> bytearray16 :
102
127
"""Returns the TTN Network Key."""
103
128
return self .net_key
104
129
@@ -108,10 +133,18 @@ class TinyLoRa:
108
133
"""TinyLoRa Interface"""
109
134
110
135
# SPI Write Buffer
111
- _BUFFER = bytearray (2 )
136
+ _BUFFER : bytearray2 = bytearray (2 )
112
137
113
138
# pylint: disable=too-many-arguments,invalid-name
114
- def __init__ (self , spi , cs , irq , rst , ttn_config , channel = None ):
139
+ def __init__ (
140
+ self ,
141
+ spi : busio .SPI ,
142
+ cs : digitalio .DigitalInOut ,
143
+ irq : digitalio .DigitalInOut ,
144
+ rst : digitalio .DigitalInOut ,
145
+ ttn_config : digitalio .DigitalInOut ,
146
+ channel : Optional [int ] = None ,
147
+ ):
115
148
"""Interface for a HopeRF RFM95/6/7/8(w) radio module. Sets module up for sending to
116
149
The Things Network.
117
150
@@ -141,13 +174,13 @@ def __init__(self, spi, cs, irq, rst, ttn_config, channel=None):
141
174
if self ._version != 18 :
142
175
raise TypeError ("Can not detect LoRa Module. Please check wiring!" )
143
176
# Set Frequency registers
144
- self ._rfm_msb = None
145
- self ._rfm_mid = None
146
- self ._rfm_lsb = None
177
+ self ._rfm_msb : Optional [ registeraddress ] = None
178
+ self ._rfm_mid : Optional [ registeraddress ] = None
179
+ self ._rfm_lsb : Optional [ registeraddress ] = None
147
180
# Set datarate registers
148
- self ._sf = None
149
- self ._bw = None
150
- self ._modemcfg = None
181
+ self ._sf : Optional [ registeraddress ] = None
182
+ self ._bw : Optional [ registeraddress ] = None
183
+ self ._modemcfg : Optional [ registeraddress ] = None
151
184
self .set_datarate ("SF7BW125" )
152
185
# Set regional frequency plan
153
186
# pylint: disable=import-outside-toplevel
@@ -201,13 +234,13 @@ def __init__(self, spi, cs, irq, rst, ttn_config, channel=None):
201
234
# Give the lora object ttn configuration
202
235
self ._ttn_config = ttn_config
203
236
204
- def __enter__ (self ):
237
+ def __enter__ (self ) -> Self :
205
238
return self
206
239
207
- def __exit__ (self , exception_type , exception_value , traceback ):
240
+ def __exit__ (self , exception_type , exception_value , traceback ) -> None :
208
241
self .deinit ()
209
242
210
- def deinit (self ):
243
+ def deinit (self ) -> None :
211
244
"""Deinitializes the TinyLoRa object properties and pins."""
212
245
self ._irq = None
213
246
self ._rst = None
@@ -220,7 +253,9 @@ def deinit(self):
220
253
self ._bw = None
221
254
self ._modemcfg = None
222
255
223
- def send_data (self , data , data_length , frame_counter , timeout = 2 ):
256
+ def send_data (
257
+ self , data : bytearray , data_length : int , frame_counter : int , timeout : int = 2
258
+ ) -> None :
224
259
"""Function to assemble and send data
225
260
:param data: data to send
226
261
:param data_length: length of data to send
@@ -258,15 +293,15 @@ def send_data(self, data, data_length, frame_counter, timeout=2):
258
293
# recalculate packet length
259
294
lora_pkt_len += data_length
260
295
# Calculate MIC
261
- mic = bytearray (4 )
296
+ mic : bytearray4 = bytearray (4 )
262
297
mic = aes .calculate_mic (lora_pkt , lora_pkt_len , mic )
263
298
# load mic in package
264
299
lora_pkt [lora_pkt_len : lora_pkt_len + 4 ] = mic [0 :4 ]
265
300
# recalculate packet length (add MIC length)
266
301
lora_pkt_len += 4
267
302
self .send_packet (lora_pkt , lora_pkt_len , timeout )
268
303
269
- def send_packet (self , lora_packet , packet_length , timeout ) :
304
+ def send_packet (self , lora_packet : bytearray , packet_length : int , timeout : int ) -> None :
270
305
"""Sends a LoRa packet using the RFM Module
271
306
:param bytearray lora_packet: assembled LoRa packet from send_data
272
307
:param int packet_length: length of LoRa packet to send
@@ -312,10 +347,11 @@ def send_packet(self, lora_packet, packet_length, timeout):
312
347
if timed_out :
313
348
raise RuntimeError ("Timeout during packet send" )
314
349
315
- def set_datarate (self , datarate ) :
350
+ def set_datarate (self , datarate : str ) -> None :
316
351
"""Sets the RFM Datarate
317
352
:param datarate: Bandwidth and Frequency Plan
318
353
"""
354
+ # TODO: Convert these to enum
319
355
data_rates = {
320
356
"SF7BW125" : (0x74 , 0x72 , 0x04 ),
321
357
"SF7BW250" : (0x74 , 0x82 , 0x04 ),
@@ -330,13 +366,15 @@ def set_datarate(self, datarate):
330
366
except KeyError as err :
331
367
raise KeyError ("Invalid or Unsupported Datarate." ) from err
332
368
333
- def set_channel (self , channel ) :
369
+ def set_channel (self , channel : int ) -> None :
334
370
"""Sets the RFM Channel (if single-channel)
335
371
:param int channel: Transmit Channel (0 through 7).
336
372
"""
337
373
self ._rfm_msb , self ._rfm_mid , self ._rfm_lsb = self ._frequencies [channel ]
338
374
339
- def _read_into (self , address , buf , length = None ):
375
+ def _read_into (
376
+ self , address : registeraddress , buf : bytearray2 , length : Optional [int ] = None
377
+ ) -> None :
340
378
"""Read a number of bytes from the specified address into the
341
379
provided buffer. If length is not specified (default) the entire buffer
342
380
will be filled.
@@ -353,14 +391,14 @@ def _read_into(self, address, buf, length=None):
353
391
device .write (self ._BUFFER , end = 1 )
354
392
device .readinto (buf , end = length )
355
393
356
- def _read_u8 (self , address ) :
394
+ def _read_u8 (self , address : registeraddress ) -> int :
357
395
"""Read a single byte from the provided address and return it.
358
396
:param bytearray address: Register Address.
359
397
"""
360
398
self ._read_into (address , self ._BUFFER , length = 1 )
361
399
return self ._BUFFER [0 ]
362
400
363
- def _write_u8 (self , address , val ) :
401
+ def _write_u8 (self , address : registeraddress , val : int ) -> None :
364
402
"""Writes to the RFM register given an address and data.
365
403
:param bytearray address: Register Address.
366
404
:param val: Data to write.
@@ -370,3 +408,6 @@ def _write_u8(self, address, val):
370
408
self ._BUFFER [1 ] = val
371
409
# pylint: disable=no-member
372
410
device .write (self ._BUFFER , end = 2 )
411
+ # pylint: disable=no-member
412
+ device .write (self ._BUFFER , end = 2 )
413
+ device .write (self ._BUFFER , end = 2 )
0 commit comments