def main(): gps = setup_gps() # setup lopy4 pins sensor = setup_adc() power = setup_power_pin() #intialize lora object lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.US915) lora = setup_single_lora_channel(lora) lora.nvram_restore() if not lora.has_joined(): join_via_abp(lora) while not lora.has_joined(): utime.sleep(2.5) print('Not yet joined...') print('Join successful!') sensor_reading = read_sensor(sensor, power) send_message(sensor_reading, gps) utime.sleep(1) lora.nvram_save() machine.deepsleep(int(READING_FREQ_IN_MIN * 60 * 1000))
class LoRaWANNode: def __init__(self, app_eui, app_key): """setup LoRaWAN for the European 868 MHz region with OTAA""" self.app_eui = ubinascii.unhexlify(app_eui) self.app_key = ubinascii.unhexlify(app_key) self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) self.socket = None self.setup() @property def has_joined(self): return self.lora.has_joined() def setup(self): """Try to restore from nvram or join the network with OTAA""" self.lora.nvram_restore() if not self.has_joined: self.join() else: self.open_socket() def join(self, timeout=30): try: timeout = timeout * 1000 self.lora.join( activation=LoRa.OTAA, auth=(self.app_eui, self.app_key), timeout=timeout, dr=DR, ) if self.has_joined: self.lora.nvram_save() self.open_socket() except TimeoutError: pass def open_socket(self, timeout=6): self.socket = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW) self.socket.setsockopt(usocket.SOL_LORA, usocket.SO_DR, DR) self.socket.settimeout(timeout) def reset(self): self.socket.close() self.lora.nvram_erase() self.join() def send(self, data): """Send out data as bytes""" if self.has_joined: if isinstance(data, (float, str, int)): data = bytes([data]) self.socket.send(data) utime.sleep(2) self.lora.nvram_save()
class EasyLoraConnect(object): def __init__(self, resetOnFailure=True): self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AS923, tx_retries=config.N_TX, device_class=LoRa.CLASS_A) self.resetOnFailure = resetOnFailure self._join_lora() def _join_lora(self, force_join=True): # create an OTA authentication params app_eui = binascii.unhexlify(config.APP_EUI.replace(' ', '')) app_key = binascii.unhexlify(config.APP_KEY.replace(' ', '')) # Switch the red led on pycom.rgbled(0xFF0000) # join a network using OTAA if not previously done self.lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) print(binascii.hexlify(self.lora.mac()).upper().decode('utf-8')) print("Joining Lora") # wait until the module has joined the network nb_try = 0 while not self.lora.has_joined(): time.sleep(2.5) print("Not joined yet in try " + str(nb_try)) if self.resetOnFailure and nb_try > config.MAX_TRY: print("Cannot join so rebooting") machine.reset() nb_try = nb_try + 1 print("LoRa Joined") # Switch the red led off pycom.rgbled(0x006400) def send(self, payload): '''Sending data over LoraWan ''' pycom.rgbled(0xFF8C00) # create a LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate s.setsockopt(socket.SOL_LORA, socket.SO_DR, config.DATA_RATE) # make the socket blocking s.setblocking(True) s.send(payload) pycom.rgbled(0x006400) # closing the socket and saving the LoRa state s.close() self.lora.nvram_save()
def connect(appeui, appkey, force=False, max_retry=20, grace_period=2.5): """ Create and connect Socket for LoRa application using OTAA mechanism """ # Initialise LoRa in LORAWAN mode. lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) #lora.nvram_erase() lora.nvram_restore() if not lora.has_joined() or force: # create an OTAA authentication parameters app_eui = ubinascii.unhexlify(appeui) app_key = ubinascii.unhexlify(appkey) # join a network using OTAA (Over the Air Activation) lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) # wait until the module has joined the network i = 0 while not lora.has_joined(): time.sleep(grace_period) i += 1 print('LORA/OTAA [EUI={}]: Application Join request pending ({}/{})...'.format(appeui, i, max_retry)) if i >= max_retry: break else: print('LORA/OTAA [EUI={}]: Application Join request accepted'.format(appeui)) # create a LoRa socket sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) # make the socket blocking # (waits for the data to be sent and for the 2 receive windows to expire) sock.setblocking(True) #sock.send(b'') # make the socket non-blocking # (because if there's no data received it will block forever...) sock.setblocking(False) #sock.recv(64) # Save LoRa State: # https://forum.pycom.io/topic/1668/has-anyone-successfully-used-lora-nvram_save-and-restore/16 lora.nvram_save() print('LORA/OTAA [EUI={}]: LoRa state saved'.format(appeui)) return sock, lora
class TtnClient: def __init__(self, app_eui, app_key, join_timeout, debug=False): self.app_eui = unhexlify(app_eui) self.app_key = unhexlify(app_key) self.join_timeout = join_timeout self.debug = debug if self.debug: print("Turning on LoRa radio...") self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868, adr=False) if self.debug: print("Restoring state from NVRAM") self.lora.nvram_restore() def _join(self): if self.debug: print("Joining new session...") self.lora.join(activation=LoRa.OTAA, auth=(self.app_eui, self.app_key), timeout=0) chrono = Timer.Chrono() chrono.start() while not self.lora.has_joined() and chrono.read() < self.join_timeout: if self.debug: print(".", end='') sleep(1) chrono.stop() if not self.lora.has_joined(): if self.debug: print("Could not join a new session") raise JoinException else: if self.debug: print("Joined new session") def send(self, payload, datarate=5): if not self.lora.has_joined(): self._join() s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, False) s.setsockopt(socket.SOL_LORA, socket.SO_DR, datarate) s.bind(1) s.setblocking(True) if self.debug: print("Sending payload...") s.send(payload) if self.debug: print("Payload sent") s.setblocking(False) if self.debug: print("Saving state to NVRAM...") self.lora.nvram_save()
s.setblocking(True) while (True): print(".") # save the coordinates in a new variable coord = l76.coordinates() # verify the coordinates received if coord == (None, None): print("Getting Location...") pycom.rgbled(0x7f7f00) #jaune print(utime.time()) #utime continue # send the Coordinates to LoRA print("sending") pycom.rgbled(0x0000ff) #bleu s.send( struct.pack("<i", int(coord[0] * 100000)) + struct.pack("<i", int(coord[1] * 100000)) + struct.pack("<H", int(utime.time()))) time.sleep(1) lora.nvram_save() #nvram print("sent") print(time.time()) print(utime.localtime()) #utime print(utime.time()) #utime pycom.rgbled(0x000000) #sleep print("sleep") py.setup_sleep(600 - time.time()) py.go_to_sleep()
class LoRa(OutputModule): """ Example of an output module that prints the output to the log. """ def __init__(self): super(LoRa, self).__init__() # check if safety variable is true if not self.config().get("antenna_connected"): raise Exception("configuration variable 'antenna_connected' is not true") # get the reset cause import machine reset_cause = machine.reset_cause() # initialize lora network from network import LoRa as LoRa_drv self.lora = LoRa_drv(mode=LoRa_drv.LORAWAN, region=LoRa_drv.EU868, adr=self.config().get("adr")) # try to load previous lora connection if waking up from deep sleep if reset_cause == machine.DEEPSLEEP_RESET: self.lora.nvram_restore() if reset_cause == machine.DEEPSLEEP_RESET and self.lora.has_joined(): log_info("Restored previous LoRaWAN join.") else: # get authentication parameters import ubinascii app_eui = ubinascii.unhexlify(self.config().get("app_eui")) app_key = ubinascii.unhexlify(self.config().get("app_key")) # join a network using OTAA (Over the Air Activation) self.lora.join(activation=LoRa_drv.OTAA, auth=(app_eui, app_key), timeout=0, dr=self.config().get("data_rate")) # wait until the module has joined the network log_debug("Waiting until LoRa has joined.") while not self.lora.has_joined(): time.sleep(2.5) log_debug("Not joined yet.") log_info("Joined LoRa network.") # create a lora socket to send data import socket self.socket = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate #self.socket.setsockopt(socket.SOL_LORA, socket.SO_DR, self.config().get("data_rate")) # timer variable for measuring time between send commands self.chrono = None def send(self, binary, base64, json, json_base64): # check minimum time between messages min = self.config().get("minimum_time") if min != 0: # first send call if self.chrono == None: log_debug("Starting LoRa sending timer.") # Import timer from machine import Timer import time self.chrono = Timer.Chrono() #Start timer self.chrono.start() else: if self.chrono.read() > min: self.chrono.reset() else: log_debug("Minimal time between LoRa sending not reached, skipping.") return try: # make the socket blocking # (waits for the data to be sent and for the 2 receive windows to expire) if self.config().get("blocking"): self.socket.setblocking(True) # send some data #s.send(bytes([0x01, 0x02, 0x03])) self.socket.send(binary) # make the socket non-blocking # (because if there's no data received it will block forever...) if self.config().get("blocking"): self.socket.setblocking(False) # get any data received (if any...) data = self.socket.recv(64) # TODO activate ota mode # save lora connection self.lora.nvram_save() except: log_error("LoRa send failed!") def test(self): pass def get_config_definition(): return ( "output_lora_otaa", "LoRaWAN output module using OTAA.", ( ("antenna_connected", "false", "This variable is for safety reasons to ensure a antenna is connected before LoRa is initialzed.\nWARNING: Setting this to true without an actual antenna connected can destroy your device!", ConfigFile.VariableType.bool), #("region", "EU868", "Pick the region that matches where you are using the device:\n\tAsia = 'AS923'\n\tAustralia = 'AU915'\n\tEurope = 'EU868'\n\tUnited States = 'US915'", ConfigFile.VariableType.string), ("app_eui", "UNSET", "app eui", ConfigFile.VariableType.string), ("app_key", "UNSET", "app key", ConfigFile.VariableType.string), ("data_rate", "5", "LoRa data rate. Use a value between 0 and 5.", ConfigFile.VariableType.uint), ("adr", "False", "Enables LoRa adaptive data rate. True / False", ConfigFile.VariableType.bool), ("blocking", "true", "Wait for data to be sent before continuing.", ConfigFile.VariableType.bool), ("minimum_time", "0", "Set minimum time between LoRa messages in seconds", ConfigFile.VariableType.uint) ) )
class LORA(object): 'Wrapper class for LoRa' def __init__(self, dr=2): # LoRa and socket instances # Initialize LoRa in LORAWAN mode self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) self.callback = None self.sockets = [] self.dr = dr # socket dr self.LED = None self.debug = False def connect(self, method, ports=1, callback=None, myLED=None, dr=None, debug=False): """ Connect device to LoRa. Set the socket and lora instances. myLED is led object, on resume use lora nvram """ self.callback = callback # call back routine on LoRa reply callback(port,response) self.debug = debug self.LED = myLED if myLED: myLED.heartbeat(False) self.restore sleep_ms(100) if self.lora.has_joined() or self.status: # resume LoRa OTAA or ABP self.getPorts(ports) return True if self.debug: print("No previous LoRa join. Try to join.") if (not type(method) is dict): raise ValueError("No activation method defined.") fnd = False try: if not method['OTAA'][0]: raise ValueError() fnd = True except: try: # OTAA from Config import dev_eui except: from machine import unique_id from ubinascii import hexlify dev_eui = 'AAAA' + hexlify(unique_id()) # use dflt try: from Config import app_eui, app_key method['OTAA'] = (dev_eui, app_eui, app_key) fnd = True except: pass if not fnd: try: if not method['ABP'][0]: raise ValueError() fnd = True except: # ABP try: from Config import dev_addr, nwk_swkey, app_swkey method['ABP'] = (dev_addr, nwk_swkey, app_swkey) fnd = True except: pass if not fnd: raise ValueError("No LoRa keys defined") if self.debug: print("LoRa keys load from Config") count = 0 if self.debug: print("Try to join LoRa/%s" % str(method.keys())) if 'OTAA' in method.keys(): # first OTAA from ubinascii import unhexlify # Join a network using OTAA (Over the Air Activation) next code looks strange dev_eui = method['OTAA'][0] dev_eui = unhexlify(dev_eui) app_eui = method['OTAA'][1] app_eui = unhexlify(app_eui) app_key = method['OTAA'][2] app_key = unhexlify(app_key) self.lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=dr) # Wait until the module has joined the network if myLED: myLED.blink(4, 2.5, 0x04acf6) else: sleep_ms(10000) while not self.lora.has_joined(): if count > 15: break # machine.reset()? print("Wait for OTAA join: ", count) count += 1 if myLED: myLED.blink(2, 2.5, 0xff0000) else: sleep_ms(5000) if self.lora.has_joined(): count = 1 print("LoRa OTAA join.") else: count = 0 if not count: # if not ABP if not 'ABP' in method.keys(): print("No ABP TTN keys defined.") return False import struct from ubinascii import unhexlify # next code is strange. ABP method is not yet operational dev_addr = method['ABP'][0] dev_addr = unhexlify(dev_addr) dev_addr = struct.unpack('>l', dev_addr)[0] nwk_swkey = method['ABP'][1] nwk_swkey = unhexlify(nwk_swkey) app_swkey = method['ABP'][2] app_swkey = unhexlify(app_swkey) print("LoRa ABP join.") self.lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey)) self.getPorts(ports) if myLED: myLED.blink(2, 0.1, 0x009900) self.dump return True def getPorts(self, ports): # Create a LoRa sockets self.sockets = [] self.sockets.append(socket.socket(socket.AF_LORA, socket.SOCK_RAW)) # Set the LoRaWAN data rate self.sockets[0].setsockopt(socket.SOL_LORA, socket.SO_DR, self.dr) # Make the socket non-blocking self.sockets[0].setblocking(False) # Create a raw LoRa socket # default port 2 self.sockets.append(None) for nr in range(ports): self.sockets.append(socket.socket(socket.AF_LORA, socket.SOCK_RAW)) self.sockets[nr + 2].setblocking(False) if nr: self.sockets[nr + 2].bind(nr + 2) if self.debug: print("Installed LoRa port %d" % (nr + 2)) return True def send(self, data, port=2): """ Send data over the network. """ if (port < 2) or (port > len(self.sockets)): raise ValueError('Unknown LoRa port %d' % port) if not self.sockets[port]: raise OSError('No socket') rts = True try: self.sockets[port].send(data) if self.LED: self.LED.blink(2, 0.1, 0x0000ff) if self.debug: print("Sending data") # print(data) except OSError as e: if e.errno == 11: print("Caught exception while sending") print("errno: ", e.errno) else: print("Lora ERROR: %s" % e) rts = False if self.LED: self.LED.off data = self.sockets[port].recv(64) if self.debug: print("Received data:", data) if self.callback and data: self.callback(port, data) sleep_ms(1000) self.dump # save status return rts @property def dump(self): from time import sleep_ms sleep_ms(2000) if self.debug: print("Save LoRa keys") return self.lora.nvram_save() @property def restore(self): self.lora.nvram_restore() if self.debug: print("Restore LoRa keys") return self.lora.stats().tx_counter @property def status(self): return self.lora.stats().tx_counter @property def clear(self): if self.debug: print("Clear LoRa keys") self.lora.nvram_erase()
class Startiot: def __init__(self): self.dev_eui = binascii.unhexlify("YOUR DEV_EUI") self.app_eui = binascii.unhexlify("YOUR APP_EUI") self.app_key = binascii.unhexlify("YOUR APP_KEY") self.lora = LoRa(mode=LoRa.LORAWAN) def connect(self, timeout=0, function=None, blocking=False): self.lora.nvram_restore() if not self.lora.has_joined(): # No saved connetion state pycom.rgbled(0x0f0000) self.lora.join(activation=LoRa.OTAA, auth=( self.dev_eui, self.app_eui, self.app_key), timeout=0) if timeout == 0: while not self.lora.has_joined(): if function == None: sleep(2.5) else: function() else: for x in range(timeout): if self.lora.has_joined(): break if function == None: sleep(2.5) else: function() if not self.lora.has_joined(): return False pycom.rgbled(0x000000) else: # Connection state restored pycom.rgbled(0x0000ff) pass self.lora.nvram_save() self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) # make the socket non-blocking self.s.setblocking(blocking) pycom.rgbled(0x000000) return True def send(self, data): self.s.setblocking(True) self.s.send(data) def recv(self, length=64): self.s.setblocking(False) return self.s.recv(length)
def initialize_lora(name): print("first connection") lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.US915, tx_power=20, bandwidth=LoRa.BW_500KHZ, sf=7, frequency=903900000) #remove all channels gateway doesn't use for channel in range(16, 72): lora.remove_channel(channel) for channel in range(0, 7): lora.remove_channel(channel) #create an OTAA authentication parameters for no ring lopy if name == 1: dev_eui = ubinascii.unhexlify( '70B3D549952757BF') # these settings can be found from TTN app_eui = ubinascii.unhexlify('70B3D57ED0028A4F') app_key = ubinascii.unhexlify('88397B010F71D34BEDF77DA003C3A54C') elif name == NO_RING: dev_eui = ubinascii.unhexlify( '70B3D54990435DFE') # these settings can be found from TTN app_eui = ubinascii.unhexlify('70B3D57ED0028A4F') app_key = ubinascii.unhexlify('CE46C01958A612D102F0D106AB415862') else: dev_eui = ubinascii.unhexlify( '70B3D54990435DFE') # these settings can be found from TTN app_eui = ubinascii.unhexlify('70B3D57ED0028A4F') app_key = ubinascii.unhexlify('CE46C01958A612D102F0D106AB415862') if not lora.has_joined(): lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) pycom.rgbled(green) time.sleep(2.5) handshk_time = Timer.Chrono() handshk_time.start() # wait until the module has joined the network while not lora.has_joined(): pycom.rgbled(off) time.sleep(0.1) pycom.rgbled(red) time.sleep(2.4) print('Not yet joined...') lora.nvram_save() handshk_time.stop() print("Total handshake time: {0}".format(handshk_time.read())) print('Joined!') pycom.rgbled(blue) # create a LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) #set to confirmed type of messages # set the LoRaWAN data rate s.setsockopt(socket.SOL_LORA, socket.SO_DR, 3) # make the socket blocking # (waits for the data to be sent and for the 2 receive windows to expire) s.setblocking(True) # send some data s.send(make_payload()) # make the socket non-blocking s.setblocking(False) # get any data received (if any...) data = s.recvfrom(128) print("received message: {0}".format(data)) return
class LORAWAN(object): """ Class to sent messages via LORAWAN network. """ def __init__(self, mode=LoRa.LORAWAN, activation=LoRa.OTAA, region=LoRa.EU868, data_rate=5, join_timeout=0, tx_retries=3, adr=True, public=True, device_class=LoRa.CLASS_A, app_eui=None, app_key=None, dev_addr=None, nwk_swkey=None, app_swkey=None): # OTAA authentication parameters if activation == LoRa.OTAA: if app_eui: self.__app_eui = binascii.unhexlify(app_eui.replace(' ', '')) if app_key: self.__app_key = binascii.unhexlify(app_key.replace(' ', '')) # ABP authentication parameters if activation == LoRa.ABP: if dev_addr: self.__dev_addr = binascii.unhexlify(dev_addr.replace(' ', '')) if nwk_swkey: self.__nwk_swkey = binascii.unhexlify( nwk_swkey.replace(' ', '')) if app_swkey: self.__nwk_appkey = binascii.unhexlify( app_swkey.replace(' ', '')) self.__join_timeout = join_timeout * 1000 self.__data_rate = data_rate self.__activation = activation self.__lora = None self.__socket = None self.__mode = mode self.__lora = LoRa(mode=mode, region=region, adr=adr, public=public, tx_retries=tx_retries, device_class=device_class) # Restore self.__lora.nvram_restore() time.sleep(1) log.debug('Device EUI: {}', binascii.hexlify(self.__lora.mac()).upper().decode('utf-8')) log.debug('Frequency: {}', self.__lora.frequency()) def start(self): """ Start the LORAWAN connection """ try: # When device isn't joined if not self.__lora.has_joined(): # Join network using OTAA if self.__activation == LoRa.OTAA: log.debug('Join network using OTAA') self.__lora.join(activation=LoRa.OTAA, auth=(self.__app_eui, self.__app_key), timeout=self.__join_timeout) while not self.__lora.has_joined(): log.debug('Wait for joining LoRa network...') time.sleep(2.5) # Join network using ABP if self.__activation == LoRa.ABP: log.debug('Join network using ABP') self.__lora.join(activation=LoRa.ABP, auth=(self.__dev_addr, self.__nwk_swkey, self.__nwk_appkey), timeout=self.__join_timeout) except Exception as e: log.error('Exception {} accesssing or joining LoRa network', e) def send_str(self, message=None): 'Send the message' self.__socket = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.__socket.setsockopt(socket.SOL_LORA, socket.SO_DR, self.__data_rate) if self.__lora and self.__socket: # make the socket blocking # (waits for the data to be sent and for the 2 receive windows to expire) self.__socket.setblocking(True) try: if message: log.debug('Send: ', message) self.__socket.send(message) self.__lora.nvram_save() time.sleep(1) except OSError as e: log.error('OSError {}', e) self.__lora.nvram_erase() time.sleep(1) # make the socket non-blocking # (because if there's no data received it will block forever...) self.__socket.setblocking(False) def receive(self): 'Receive a message' if self.__socket: # get any data received (if any...) data = self.__socket.recv(64) return data def stop(self): ' Stop the LORAWAN connection' log.debug('Stop the LORAWAN connection') if self.__socket: self.__socket.close() self.__socket = None
class LoRaDriverPycom: """ LoRa driver for Pycom MicroPython """ def __init__(self, network_manager, settings): self.network_manager = network_manager self.settings = settings def start(self): """ Start driver """ from network import LoRa if self.settings.get('networking.lora.region') == 'AS923': lora_region = LoRa.AS923 elif self.settings.get('networking.lora.region') == 'AU915': lora_region = LoRa.AU915 elif self.settings.get('networking.lora.region') == 'EU868': lora_region = LoRa.EU868 elif self.settings.get('networking.lora.region') == 'US915': lora_region = LoRa.US915 lora_adr = self.settings.get('networking.lora.adr') or False self.lora_socket = None self.lora = LoRa(mode=LoRa.LORAWAN, region=lora_region, adr=lora_adr) # Restore LoRa state from NVRAM after waking up from DEEPSLEEP. # Otherwise, reset LoRa NVRAM and rejoin. if platform_info.vendor in [ platform_info.MICROPYTHON.Vanilla, platform_info.MICROPYTHON.Pycom ]: import machine # Restore LoRaWAN status after wake up from deep sleep if machine.reset_cause() == machine.DEEPSLEEP_RESET: self.lora.nvram_restore() log.info( '[LoRa] LoRaWAN state restored from NVRAM after deep sleep' ) # Otherwise reset LoRaWAN status and deep sleep interval from NVRAM else: self.lora.nvram_erase() log.info( '[LoRa] LoRaWAN state erased from NVRAM. Rejoin forced') if platform_info.vendor == platform_info.MICROPYTHON.Pycom: import pycom nvram_get = pycom.nvs_get nvram_erase = pycom.nvs_erase elif platform_info.vendor == platform_info.MICROPYTHON.Vanilla: import esp32 nvram_get = esp32.nvs_get nvram_erase = esp32.nvs_erase try: if nvram_get('deepsleep') is not None: nvram_erase('deepsleep') log.info( '[LoRa] Deep sleep interval erased from NVRAM. Return to settings value' ) except: pass if not self.lora.has_joined(): import binascii datarate_join = self.settings.get('networking.lora.datarate_join') # Over-the-Air Activation (OTAA) if self.settings.get('networking.lora.activation') == 'otaa': app_eui = binascii.unhexlify( self.settings.get('networking.lora.otaa.application_eui')) app_key = binascii.unhexlify( self.settings.get('networking.lora.otaa.application_key')) log.info('[LoRa] Attaching to the LoRaWAN network using OTAA') if self.settings.get( 'networking.lora.otaa.device_eui') is None: self.lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0, dr=datarate_join) else: dev_eui = binascii.unhexlify( self.settings.get('networking.lora.otaa.device_eui')) self.lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=datarate_join) # Activation by Personalization (ABP) elif self.settings.get('networking.lora.activation') == 'abp': import struct dev_addr = struct.unpack( ">l", binascii.unhexlify( self.settings.get( 'networking.lora.abp.device_address')))[0] nwk_swkey = binascii.unhexlify( self.settings.get( 'networking.lora.abp.network_session_key')) app_swkey = binascii.unhexlify( self.settings.get('networking.lora.abp.app_session_key')) log.info('[LoRa] Attaching to the LoRaWAN network using ABP') self.lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey), timeout=0, dr=datarate_join) def ensure_connectivity(self): self.wait_for_join() if self.lora_joined: if self.lora_socket is None: try: self.create_socket() except: log.exception("[LoRa] Could not create LoRa socket") else: log.error("[LoRa] Could not join network") def wait_for_join(self): """ wait for device activation to complete """ self.lora_joined = None while not self.lora.has_joined(): log.info('[LoRa] Not joined yet...') time.sleep( self.settings.get('networking.lora.otaa.join_check_interval', 2.5)) self.lora_joined = self.lora.has_joined() if self.lora_joined: log.info('[LoRa] Joined successfully') else: log.info('[LoRa] Failed to join network') return self.lora_joined def create_socket(self): """ Create socket for LoRa communication """ # create a lora socket self.socket = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.socket.settimeout(6.0) self.lora_socket = True log.info('[LoRa] Socket created') return self.lora_socket def send(self, payload): """ Send a LoRa packet. :param payload: """ self.socket.setblocking(True) success = self.socket.send(payload) self.socket.setblocking(False) self.lora.nvram_save() return success def receive(self): """ Receive a LoRa packet. """ try: rx, port = self.socket.recvfrom(256) except socket.timeout: log.info('[LoRa] No packet received within receive window') if rx: log.info('[LoRa] Received: {} on port: {}'.format(rx, port)) return rx, port
class PybytesConnection: def __init__(self, config, message_callback): if config is not None: self.__conf = config try: self.__host = pycom.nvs_get('pybytes_server') except: self.__host = config.get('server') self.__ssl = config.get('ssl', False) self.__ssl_params = config.get('ssl_params', {}) self.__user_name = config.get('username') self.__device_id = config.get('device_id') self.__mqtt_download_topic = "d" + self.__device_id self.__mqtt_upload_topic = "u" + self.__device_id self.__pybytes_protocol = PybytesProtocol( config, message_callback, pybytes_connection=self ) self.__connection = None self.__connection_status = constants.__CONNECTION_STATUS_DISCONNECTED self.__lora_socket = None self.lora = None self.lora_lock = _thread.allocate_lock() self.__sigfox_socket = None self.lte = None self.wlan = None self.__network_type = None self.__wifi_lte_watchdog = None def lte_ping_routine(self, delay): while True: self.send_ping_message() time.sleep(delay) def print_pretty_response(self, rsp): lines = rsp.split('\r\n') for line in lines: if line: if line not in ['OK']: print(line) def __initialise_watchdog(self): if self.__conf.get('connection_watchdog', True): self.__wifi_lte_watchdog = WDT( timeout=constants.__WDT_TIMEOUT_MILLISECONDS ) print('Initialized watchdog for WiFi and LTE connection with timeout {} ms'.format(constants.__WDT_TIMEOUT_MILLISECONDS)) # noqa else: print('Watchdog for WiFi and LTE was disabled, enable with "connection_watchdog": true in pybytes_config.json') # noqa # Establish a connection through WIFI before connecting to mqtt server def connect_wifi(self, reconnect=True, check_interval=0.5, timeout=120): self.__initialise_watchdog() if self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED: # noqa print("Error connect_wifi: Connection already exists. Disconnect First") # noqa return False try: from network import WLAN antenna = self.__conf.get('wlan_antenna', WLAN.INT_ANT) known_nets = [((self.__conf['wifi']['ssid'], self.__conf['wifi']['password']))] # noqa if antenna == WLAN.EXT_ANT: print("WARNING! Using external WiFi antenna.") '''to connect it to an existing network, the WiFi class must be configured as a station''' self.wlan = WLAN(mode=WLAN.STA, antenna=antenna) attempt = 0 print_debug(3, 'WLAN connected? {}'.format(self.wlan.isconnected())) while not self.wlan.isconnected() and attempt < 3: attempt += 1 print_debug(3, "Wifi connection attempt: {}".format(attempt)) print_debug(3, 'WLAN connected? {}'.format(self.wlan.isconnected())) available_nets = None while available_nets is None: try: available_nets = self.wlan.scan() for x in available_nets: print_debug(5, x) time.sleep(1) except: pass nets = frozenset([e.ssid for e in available_nets]) known_nets_names = frozenset([e[0]for e in known_nets]) net_to_use = list(nets & known_nets_names) try: net_to_use = net_to_use[0] pwd = dict(known_nets)[net_to_use] sec = [e.sec for e in available_nets if e.ssid == net_to_use][0] # noqa print_debug(99, "Connecting with {} and {}".format(net_to_use, pwd)) if sec == 0: self.wlan.connect(net_to_use, timeout=10000) else: self.wlan.connect(net_to_use, (sec, pwd), timeout=10000) start_time = time.time() while not self.wlan.isconnected(): if time.time() - start_time > timeout: raise TimeoutError('Timeout trying to connect via WiFi') time.sleep(0.1) except Exception as e: if str(e) == "list index out of range" and attempt == 3: print("Please review Wifi SSID and password inside config") self.wlan.deinit() return False elif attempt == 3: print("Error connecting using WIFI: %s" % e) return False self.__network_type = constants.__NETWORK_TYPE_WIFI print("WiFi connection established") try: self.__connection = MQTTClient( self.__device_id, self.__host, self.__mqtt_download_topic, self.__pybytes_protocol, user=self.__user_name, password=self.__device_id ) self.__connection.connect() self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI # noqa self.__pybytes_protocol.start_MQTT( self, constants.__NETWORK_TYPE_WIFI ) return True except Exception as ex: if '{}'.format(ex) == '4': print('MQTT ERROR! Bad credentials when connecting to server: "{}"'.format(self.__host)) # noqa else: print("MQTT ERROR! {}".format(ex)) return False except Exception as ex: print("Exception connect_wifi: {}".format(ex)) return False # Establish a connection through LTE before connecting to mqtt server def connect_lte(self, activation_info=False, start_mqtt=True): if activation_info: lte_cfg = activation_info else: lte_cfg = self.__conf.get('lte') self.__initialise_watchdog() if lte_cfg is not None: if (os.uname()[0] not in ['FiPy', 'GPy']): print("You need a device with FiPy or GPy firmware to connect via LTE") # noqa return False try: from network import LTE time.sleep(3) if lte_cfg.get('carrier', 'standard') == 'standard': carrier = None else: carrier = lte_cfg.get('carrier') print_debug(1, 'LTE init(carrier={}, cid={})'.format(carrier, lte_cfg.get('cid', 1))) # noqa # instantiate the LTE object self.lte = LTE(carrier=carrier, cid=lte_cfg.get('cid', 1)) try: lte_type = lte_cfg.get('type') if len(lte_cfg.get('type')) > 0 else None except: lte_type = None try: lte_apn = lte_cfg.get('apn') if len(lte_cfg.get('type')) > 0 else None except: lte_apn = None try: lte_band = int(lte_cfg.get('band')) except: lte_band = None print_debug( 1, 'LTE attach(band={}, apn={}, type={})'.format( lte_band, lte_apn, lte_type ) ) self.lte.attach(band=lte_band, apn=lte_apn, type=lte_type) # noqa # attach the cellular modem to a base station while not self.lte.isattached(): time.sleep(0.25) time.sleep(1) print_debug(1, 'LTE connect()') # start a data session and obtain an IP address self.lte.connect() print_debug(1, 'LTE is_connected()') while not self.lte.isconnected(): time.sleep(0.25) print("LTE connection established") self.__network_type = constants.__NETWORK_TYPE_LTE if start_mqtt: try: self.__connection = MQTTClient( self.__device_id, self.__host, self.__mqtt_download_topic, self.__pybytes_protocol, user=self.__user_name, password=self.__device_id ) self.__connection.connect() self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE # noqa self.__pybytes_protocol.start_MQTT( self, constants.__NETWORK_TYPE_LTE ) print("Connected to MQTT {}".format(self.__host)) return True except Exception as ex: if '{}'.format(ex) == '4': print('MQTT ERROR! Bad credentials when connecting to server: "{}"'.format(self.__host)) # noqa else: print("MQTT ERROR! {}".format(ex)) return False except Exception as ex: print("Exception connect_lte: {}".format(ex)) sys.print_exception(ex) return False else: print("Error... missing configuration!") return False # LORA def connect_lora_abp(self, lora_timeout, nanogateway): print_debug(1,'Attempting to connect via LoRa') if (self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED): # noqa print("Error connect_lora_abp: Connection already exists. Disconnect First") # noqa return False try: from network import LoRa except Exception as ex: print("This device does not support LoRa connections: %s" % ex) return False lora_class = self.__conf.get('lora', {}).get('class', 0) if self.__conf.get('lora', {}).get('region') is not None: self.lora = LoRa(mode=LoRa.LORAWAN, region=self.__conf.get('lora').get('region'), device_class=lora_class) else: self.lora = LoRa(mode=LoRa.LORAWAN, device_class=lora_class) self.lora.nvram_restore() try: dev_addr = self.__conf['lora']['abp']['dev_addr'] nwk_swkey = self.__conf['lora']['abp']['nwk_skey'] app_swkey = self.__conf['lora']['abp']['app_skey'] except Exception as ex: print("Invalid LoRaWAN ABP configuration!") print_debug(1, ex) return False timeout_ms = self.__conf.get('lora_timeout', lora_timeout) * 1000 dev_addr = struct.unpack(">l", binascii.unhexlify(dev_addr.replace(' ', '')))[0] # noqa nwk_swkey = binascii.unhexlify(nwk_swkey.replace(' ', '')) app_swkey = binascii.unhexlify(app_swkey.replace(' ', '')) try: print("Trying to join LoRa.ABP for %d seconds..." % self.__conf.get('lora_timeout', lora_timeout)) self.lora.join( activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey), timeout=timeout_ms ) # if you want, uncomment this code, but timeout must be 0 # while not self.lora.has_joined(): # print("Joining...") # time.sleep(5) self.__open_lora_socket(nanogateway) # print_debug(5, 'Stack size: {}'.format(self.__thread_stack_size)) # _thread.stack_size(self.__thread_stack_size) # _thread.start_new_thread(self.__check_lora_messages, ()) return True except Exception as e: message = str(e) if message == 'timed out': print("LoRa connection timeout: %d seconds" % self.__conf.get('lora_timeout', lora_timeout)) else: print_debug(3, 'Exception in LoRa connect: {}'.format(e)) return False def connect_lora_otaa(self, lora_timeout, nanogateway): print_debug(1,'Attempting to connect via LoRa') if (self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED): # noqa print("Error connect_lora_otaa: Connection already exists. Disconnect First") # noqa return False try: from network import LoRa except Exception as ex: print("This device does not support LoRa connections: %s" % ex) return False try: dev_eui = self.__conf['lora']['otaa']['app_device_eui'] app_eui = self.__conf['lora']['otaa']['app_eui'] app_key = self.__conf['lora']['otaa']['app_key'] except Exception as ex: print("Invalid LoRaWAN OTAA configuration!") print_debug(1, ex) return False timeout_ms = self.__conf.get('lora_timeout', lora_timeout) * 1000 lora_class = self.__conf.get('lora', {}).get('class', 0) if self.__conf.get('lora', {}).get('region') is not None: self.lora = LoRa(mode=LoRa.LORAWAN, region=self.__conf.get('lora', {}).get('region'), device_class=lora_class) else: self.lora = LoRa(mode=LoRa.LORAWAN, device_class=lora_class) self.lora.nvram_restore() dev_eui = binascii.unhexlify(dev_eui.replace(' ', '')) app_eui = binascii.unhexlify(app_eui.replace(' ', '')) app_key = binascii.unhexlify(app_key.replace(' ', '')) try: if not self.lora.has_joined(): print("Trying to join LoRa.OTAA for %d seconds..." % self.__conf.get('lora_timeout', lora_timeout)) self.lora.join( activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=timeout_ms ) # if you want, uncomment this code, but timeout must be 0 # while not self.lora.has_joined(): # print("Joining...") # time.sleep(5) self.__open_lora_socket(nanogateway) # print_debug(5, 'Stack size: {}'.format(self.__thread_stack_size)) # _thread.stack_size(self.__thread_stack_size) # _thread.start_new_thread(self.__check_lora_messages, ()) return True except Exception as e: message = str(e) if message == 'timed out': print("LoRa connection timeout: %d seconds" % self.__conf.get('lora_timeout', lora_timeout)) else: print_debug(3, 'Exception in LoRa connect: {}'.format(e)) return False def __open_lora_socket(self, nanogateway): if (nanogateway): for i in range(3, 16): self.lora.remove_channel(i) self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) print("Setting up LoRa socket...") self.__lora_socket = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.__lora_socket.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_LORA self.__pybytes_protocol.start_Lora(self) print("Connected using LoRa") # SIGFOX def connect_sigfox(self): if (self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED): # noqa print("Error: Connection already exists. Disconnect First") pass try: from network import Sigfox except Exception: print("This device does not support Sigfox connections") return sigfox_config = self.__conf.get('sigfox', {}) if sigfox_config is None or sigfox_config.get('RCZ') is None: print(constants.__SIGFOX_WARNING) try: sf_rcz = int(sigfox_config.get('RCZ', 1)) - 1 if sf_rcz >= 0 and sf_rcz <= 3: Sigfox(mode=Sigfox.SIGFOX, rcz=sf_rcz) self.__sigfox_socket = socket.socket(socket.AF_SIGFOX, socket.SOCK_RAW) # noqa self.__sigfox_socket.setblocking(True) self.__sigfox_socket.setsockopt(socket.SOL_SIGFOX, socket.SO_RX, False) # noqa self.__network_type = constants.__NETWORK_TYPE_SIGFOX self.__connection_status = constants.__CONNECTION_STATUS_CONNECTED_SIGFOX # noqa self.__pybytes_protocol.start_Sigfox(self) print( "Connected using Sigfox. Only upload stream is supported" ) return True else: print('Invalid Sigfox RCZ specified in config!') return False except Exception as e: print('Exception in connect_sigfox: {}'.format(e)) return False # COMMON def disconnect(self, keep_wifi=False, force=False): if self.__wifi_lte_watchdog is not None: self.__wifi_lte_watchdog = WDT(timeout=constants.__WDT_MAX_TIMEOUT_MILLISECONDS) print('Watchdog timeout has been increased to {} ms'.format(constants.__WDT_MAX_TIMEOUT_MILLISECONDS)) # noqa print_debug( 1, 'self.__connection_status={} | self.__network_type={}'.format( self.__connection_status, self.__network_type ) ) if (self.__connection_status == constants.__CONNECTION_STATUS_DISCONNECTED): # noqa print_debug(3, "Already disconnected") if (constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI <= self.__connection_status <= constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE): # noqa print_debug(1, 'MQTT over WIFI||LTE... disconnecting MQTT') try: self.__connection.disconnect(force=force) self.__connection_status = constants.__CONNECTION_STATUS_DISCONNECTED # noqa except Exception as e: print("Error disconnecting: {}".format(e)) if (self.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_LORA): # noqa print_debug(1, 'Connected over LORA... closing socket and saving nvram') # noqa try: self.__lora_socket.close() self.lora.nvram_save() except Exception as e: print("Error disconnecting: {}".format(e)) if (self.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_SIGFOX): # noqa print_debug(1, 'Connected over SIGFOX... closing socket') try: self.__sigfox_socket.close() except Exception as e: print("Error disconnecting: {}".format(e)) if (self.__network_type == constants.__NETWORK_TYPE_WIFI and not keep_wifi): print_debug(1, 'Connected over WIFI... disconnecting') try: self.wlan.deinit() except Exception as e: print("Error disconnecting: {}".format(e)) if (self.__network_type == constants.__NETWORK_TYPE_LTE): print_debug(1, 'Connected over LTE... disconnecting') try: lte_cfg = self.__conf.get('lte') print_debug(1, 'lte.deinit(reset={})'.format(lte_cfg.get('reset', False))) # noqa self.lte.deinit(reset=lte_cfg.get('reset', False)) except Exception as e: print("Error disconnecting: {}".format(e)) self.__network_type = None self.__connection_status = constants.__CONNECTION_STATUS_DISCONNECTED def is_connected(self): return not (self.__connection_status == constants.__CONNECTION_STATUS_DISCONNECTED) # noqa # Added for convention with other connectivity classes def isconnected(self): return not (self.__connection_status == constants.__CONNECTION_STATUS_DISCONNECTED) # noqa
class Node: def __init__(self,sleep_time,data_rate,pysense): self.lora = None # Instancia de Lora (sin inicializar) self.s = None # Instancia Socket (sin inicializar) self.sleep_time = sleep_time # Intervalo de inactividad self.dr = data_rate # Data Rate (defecto 5) self.py = pysense # Instancia de Pysense self.lt = LTR329ALS01(self.py) # Instancia Sensor de Luminosidad self.mp = MPL3115A2(self.py,mode=PRESSURE) # Instancia Sensor de Presión self.si = SI7006A20(self.py) # Instancia Sensor de Humedad y tempertura #------------------------------------------------------------------------------# def connect(self,dev_eui,app_eui, app_key): """ Connect device to LoRa. Set the socket and lora instances. """ # Initialize LoRa in LORAWAN mode self.lora = LoRa(mode = LoRa.LORAWAN,device_class=LoRa.CLASS_A,region=LoRa.EU868) # Set the 3 default channels to the same frequency (must be before # sending the OTAA join request) self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) # Join a network using OTAA (Over the Air Activation) self.lora.join(activation = LoRa.OTAA, auth = (dev_eui,app_eui, app_key), timeout = 0, dr=self.dr) #login for TheThingsNetwork see here: #https://www.thethingsnetwork.org/forum/t/lopy-otaa-example/4471 # Wait until the module has joined the network while not self.lora.has_joined(): print("Trying to join LoraWAN with OTAA") time.sleep(2.5) print ("LoraWAN joined! ") # save the LoRaWAN connection state self.lora.nvram_save() #------------------------------------------------------------------------------# def send(self,data): """ Send data over the network. """ if py.get_wake_reason() == WAKE_REASON_TIMER: #Si despierta tras deepsleep # Initialize LoRa in LORAWAN mode self.lora = LoRa(mode = LoRa.LORAWAN,adr=True,device_class=LoRa.CLASS_A,region=LoRa.EU868) # restore the LoRaWAN connection state try: self.lora.nvram_restore() except OSError: print("Error: LoRa Configuration could not be restored") self.connect(dev_eui,app_eui,app_key) print("LoRa Connection Parameters Recovered") # remove all the non-default channels for i in range(3, 16): self.lora.remove_channel(i) # Set the 3 default channels to the same frequency # (must be before sending the OTAA join request) self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) # Create a LoRa socket self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) print("Created LoRaWAN socket") # Make the socket blocking self.s.setblocking(True) #Necesario para gurdar el contador de mensajes try: self.s.send(data) #Envio de datos self.s.setblocking(False) # make the socket non-blocking (necesario para no dejar colgado el dispositivo) rx = bytes(self.s.recv(128)) # (because if there's no data received it will block forever...) self.receive(rx=rx) self.lora.nvram_save() print('Lora Config Saved!') except OSError as e: if e.errno == 11: print("Caught exception while sending") print("errno: ", e.errno) pass #------------------------------------------------------------------------------# #Función de recepción de datos.Es activada tras la ventana de recepción #posterior al envío. def receive(self,rx=None): if len(rx) == 0: #No hay mensaje de recepción print('No incoming message') pass else: if rx[0] == 73: #Orden de Cambio de intervalo (ASCII hex I=0x49 dec 73) print("Recibido cambio de intervalo %d" %(int.from_bytes(rx[1:],'big'))) self.sleep_time = int.from_bytes(rx[1:],'big') #Decodifica el valor del nuevo intervalo pycom.nvs_set('sleep_time',self.sleep_time) #Lo guarda en NVRAM elif rx[0] == 82: #Orden de Cambio Data Rate (ASCII hex R=0x52 dec 87) print("Cambiando Data Rate %d" %(int.from_bytes(rx[1:],'big'))) self.dr = int.from_bytes(rx[1:],'big') #Decodifica el valor del nuevo data Rate pycom.nvs_set('data_rate',self.data_rate) #Lo guarda en NVRAM elif rx[0] == 79: #4Fh ota = WiFiOTA('MBP_JuanMa','MBP_JuanMa',"54.154.225.138",8000) #Amazon Web Services Server print("Updating via OTA...") print('- ' * 20) ota.connect() ota.update() else: pass #------------------------------------------------------------------------------# #Función de lectura de medidas. Los sensores ya han sido inicializados al #crear la instancia de la clase Node def readsens(self): pressure = (int(self.mp.pressure())-90000).to_bytes(2,'little') #Segundo Elemento Lista: Presión (entero) humidity = int(round(self.si.humidity(),2)*100).to_bytes(2,'little') #Tercer Elemento Lista: Humedad (dos decimales) temperature = int(round(self.si.temperature(),2)*100).to_bytes(2,'little') #Cuarto Elemento Lista: Temperatura (dos decimales) battery = int(round(self.py.read_battery_voltage(),4)*10000-33000).to_bytes(2,'little') #Quinto Elemento Lista: Voltaje (cuatro decimales) light = int(self.lt.light()[0]).to_bytes(2,'little') #Primer Elemento Lista: Luminosidad (entero) reading = light+pressure+humidity+temperature+battery #Union de tipos bytes return reading
class Transceiver: def __init__(self, app_eui=0, app_key=0, dev_addr=0, nwk_swkey=0, app_swkey=0, dataRate=0, adr=False, useSavedState=True): self.app_eui = app_eui self.app_key = app_key self.dev_addr = dev_addr self.nwk_swkey = nwk_swkey self.app_swkey = app_swkey self.dataRate = dataRate self.adr = adr self.useSavedState = useSavedState # Initialize LoRa in LORAWAN mode self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868, power_mode=LoRa.TX_ONLY, adr=self.adr) # Restore LoRa state from memory (join state, frame counter) if self.useSavedState: self.lora.nvram_restore() else: self.lora.nvram_erase() # Only (re)join if not joined before if not self.lora.has_joined(): if self.app_eui != 0 and self.app_key != 0: # join a network using OTAA (Over the Air Activation). Start with sf12 self.lora.join(activation=LoRa.OTAA, auth=(self.app_eui, self.app_key), dr=0, timeout=0) elif self.dev_addr != 0 and self.nwk_swkey != 0 and self.app_swkey != 0: # join a network using ABP (Authentication By Personalization) self.lora.join(activation=LoRa.ABP, auth=(self.dev_addr, self.nwk_swkey, self.app_swkey)) else: print("Invalid ABP or OTAA keys") return # wait until the module has joined the network (ToDo: timeout to prevent indefinite loop) while not self.lora.has_joined(): time.sleep(2.5) print('.', end='') return def transmit(self, payload): self.lora.set_battery_level(self.__getLoraBattLevel()) # create a LoRa socket self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, self.dataRate) # selecting non-confirmed type of messages self.s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, False) # make the socket blocking # (waits for the data to be sent and for the 2 receive windows to expire) self.s.setblocking(True) # select port self.s.bind(1) # Send the LoRa message self.s.send(payload) # make the socket non-blocking # (because if there's no data received it will block forever...) self.s.setblocking(False) # get any data received (if any...) self.receivePayload = self.s.recv(64) #print("Store LoRa state in memory") self.lora.nvram_save() return def receive(self): return self.receivePayload def getMac(self): return binascii.hexlify(self.lora.mac()).upper().decode('utf-8') def stats(self): return self.lora.stats() def __getLoraBattLevel(self): adc = machine.ADC() battReg = adc.channel(pin='P16', attn=1) #print('Battery voltage:', battReg() * 3 * 1.334 / 4095) loraBattLevel = int(battReg() / 14.9) if loraBattLevel > 254: loraBattLevel = 0 battVoltage = battReg() * 3 * 1.334 / 4095 #print("Battery level: %d (%f V)" % (loraBattLevel, battVoltage)) return loraBattLevel
def loraTask(): global lora_wdt_lock, lora_stop_flag global QueueDelay logger = Logger(name='LORA ' + __version__, level=logging.DEBUG, filename=None) logger.debug('** LORA Task started **') lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868, adr=True, public=True, device_class=LoRa.CLASS_C) lorawan_socket = socket.socket(socket.AF_LORA, socket.SOCK_RAW) lorawan_socket.setblocking(False) RadioOffset = getConfigurationVariable(NVS_RADIO_DELAY) # defautl is OTAA (old config file may not have this defined) JM = 0 try: from deviceid import lora_join_method JM = lora_join_method except: pass #add the multicasts try: from deviceid import multicasts for multicast_address in multicasts: multicast_devAddr = multicast_address[0] multicast_NwkSKey = multicast_address[1] multicast_AppSKey = multicast_address[2] try: lora.join_multicast_group(multicast_devAddr, multicast_NwkSKey, multicast_AppSKey) except: pass except: pass # define the reserved Downlink minutes if it exists DRM = [8] try: from deviceid import downlinks_reserved_minutes DRM = downlinks_reserved_minutes except: pass if pycom.nvs_get(POWER_FAIL_STATE) == MODE_POWER_FAIL: # SPECIAL CASE FOR POWER FAIL AFTER DEEP SLEEP WAKE UP lora.nvram_restore() processMsgImmediate( LoraQueueImmediate, logger, lora, lorawan_socket) # the PF message should already be in the queue if lora_queue_immediate_semaphore.locked(): lora_queue_immediate_semaphore.release( ) # tell the main thread we are done time.sleep(10) if JM == OTAA_JOIN: logger.debug("Attempting OTAA Join Kotahi.net...using device EUI " + str(binascii.hexlify(dev_eui))) lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0) counter = 0 while not lora.has_joined(): time.sleep(1) counter = counter + 1 if lora_wdt_lock.locked(): lora_wdt_lock.release( ) # tell the WDT that LoRa task is busy waiting to join logger.debug("Join successful after " + str(counter) + "s") elif JM == ABP_JOIN: from deviceid import dev_addr, nwk_swkey, app_swkey logger.debug("Joined Kotahi.net using ABP with EUI " + str(binascii.hexlify(dev_eui))) lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey)) #time.sleep(3) # save the state in NVS lora.nvram_save() #lora.nvram_save() # Lora loop starts here, processing the QOS queues while not lora_stop_flag.locked(): # wait 1s while checking for any message to be sent immediately (e.g PF Alarm) counter = 10 while counter > 0: if processMsgImmediate(LoraQueueImmediate, logger, lora, lorawan_socket) == True: if lora_queue_immediate_semaphore.locked(): lora_queue_immediate_semaphore.release( ) # signal that the immediate msg has been sent time.sleep(1) counter = counter - 1 time.sleep_ms(100) # Process any downlinks lora_rx_data(lora, lorawan_socket, logger) if lora_wdt_lock.locked(): lora_wdt_lock.release( ) # tell the WDT that LoRa task is doing just fine unixLocalTime = time.time() + time.timezone() timetuple = time.localtime() maskUplinks = False for minute in DRM: if (timetuple[4] % 10 == minute): maskUplinks = True break # process the uplinks using basic QOS Queues if maskUplinks == False: processQOSQueue(LoraQueueP5, 5, unixLocalTime, logger, lora, lorawan_socket, RadioOffset) processQOSQueue(LoraQueueP4, 4, unixLocalTime, logger, lora, lorawan_socket, RadioOffset) processQOSQueue(LoraQueueP3, 3, unixLocalTime, logger, lora, lorawan_socket, RadioOffset) processQOSQueue(LoraQueueP2, 2, unixLocalTime, logger, lora, lorawan_socket, RadioOffset) processQOSQueue(LoraQueueP1, 1, unixLocalTime, logger, lora, lorawan_socket, RadioOffset) logger.error('** LORA Task ended **')
class LoRaWANNode: def __init__(self, app_eui, app_key, frequency=868100000, dr=5): '''setup LoRaWAN for the European 868 MHz region with OTAA''' self.dr = dr self.frequency = frequency self.app_eui = ubinascii.unhexlify(app_eui) self.app_key = ubinascii.unhexlify(app_key) self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) self.socket = None self.setup() @property def has_joined(self): return self.lora.has_joined() def default_channels(self): ''' Remove all non-default channels and set the 3 default channels to the same frequency (must be before ending the OTAA join request) ''' for i in range(3, 16): self.lora.remove_channel(i) self.lora.add_channel(0, frequency=self.frequency, dr_min=0, dr_max=self.dr) self.lora.add_channel(1, frequency=self.frequency, dr_min=0, dr_max=self.dr) self.lora.add_channel(2, frequency=self.frequency, dr_min=0, dr_max=self.dr) def setup(self): '''Try to restore from nvram or join the network with otaa''' self.default_channels() self.lora.nvram_restore() if not self.has_joined: self.join() else: self.open_socket() def join(self, timeout=10): try: timeout = timeout * 1000 self.lora.join(activation=LoRa.OTAA, auth=(self.app_eui, self.app_key), timeout=timeout, dr=self.dr) if self.has_joined: self.lora.nvram_save() self.open_socket() except TimeoutError: pass def open_socket(self, timeout=6): self.socket = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW) self.socket.setsockopt(usocket.SOL_LORA, usocket.SO_DR, self.dr) self.socket.settimeout(timeout) def reset(self): self.socket.close() self.lora.nvram_erase() self.join() def send(self, data): '''Send out data as bytes''' if self.has_joined: if isinstance(data, (float, str, int)): data = bytes([data]) self.socket.send(data) utime.sleep(2) self.lora.nvram_save()
class LoRaWAN: DEBUG = False def __init__(self, app_eui, app_key, region=LoRa.EU868, sf=7, adr=True, dr=5, timeout=15): """Setup LoRaWAN""" self._timeout = timeout self._app_eui = ubinascii.unhexlify(app_eui) self._app_key = ubinascii.unhexlify(app_key) self._socket = None self._dr = dr self.lora = LoRa(mode=LoRa.LORAWAN, region=region, sf=sf, adr=adr) self.setup() def setup(self): """Try to restore from nvram or join the network with OTAA""" self.lora.nvram_restore() if not self.lora.has_joined(): self.join() else: self.open_socket() def join(self): try: self.dprint("Send join request") timeout = self._timeout * 1000 self.lora.join( activation=LoRa.OTAA, auth=(self._app_eui, self._app_key), timeout=timeout, dr=self._dr, ) if self.lora.has_joined(): self.lora.nvram_save() self.open_socket() self.dprint("Joined network") except LoRa.timeout: self.dprint("Timeout error") raise def open_socket(self, timeout=6): self._socket = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW) self._socket.setsockopt(usocket.SOL_LORA, usocket.SO_DR, self._dr) self._socket.settimeout(timeout) def reset(self): """Reset socket, clear on device stored LoRaWAN session and re-join the network""" self._socket.close() self.lora.lora_erase() self.join() def send(self, payload, port=1): """Send out uplink data as bytes""" self._socket.bind(port) if self.lora.has_joined(): if isinstance(payload, (float, str, int)): payload = bytes([payload]) self.dprint("Send payload: {}".format(payload)) self._socket.setblocking(True) self._socket.send(payload) self._socket.setblocking(False) self.lora.nvram_save() def recv(self, rbytes=1): """Receive bytes from downlink""" retval = self._socket.recvfrom(rbytes) self.dprint("Recv payload: {}, port: {}".format(retval[0], retval[1])) return retval def shutdown(self): """Shutdown LoRa modem""" self._socket.close() self.lora.power_mode(LoRa.SLEEP) def dprint(self, message): if self.DEBUG: print("LoRaWAN: {}".format(message))
class LoraController: def __init__(self, options, logger, eventLog, ledController): self.options = options self.logger = logger self.eventLog = eventLog self.led = ledController self.lora = LoRa(mode=LoRa.LORA, power_mode=LoRa.SLEEP) self.tx_runner = None # thread which sends events over lora self.lastJoin = 0 # when did we join the lora network self.isJoinLogged = False # did we log the initial LORA join self.lastEventId = 0 # last sent event id self.sendLock = _thread.allocate_lock() self.socketLock = _thread.allocate_lock() self.isAckingCounter = 0 self.noDownlinkCounter = 0 self.lastUplinkTime = 0 self.isAcking = False # logging def log(self, *text): self.logger.log("LORA", *text) # start lora connectivity def start(self): # setup lorawan self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868, device_class=LoRa.CLASS_A, tx_retries=3, adr=True, sf=12) self.lora.nvram_restore() self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT | LoRa.TX_FAILED_EVENT), handler=self.lora_callback) self.log('Lora DevEUI is', self.getDeviceEUI()) self.log('Lora AppEUI is', self.options['lora_app_eui']) if len(self.options['lora_app_eui']) != 16: self.log("ERROR", "Setting 'lora_app_eui' is invalid:", self.options['lora_app_eui']) return # issue join if self.options['lora_mode'] == "abp": self.join() elif self.lora.has_joined(): self.log("Lora network is already joined, re-joining anyway") else: self.join() def lora_callback(self, lora): events = lora.events() if events & LoRa.TX_FAILED_EVENT: self.log('Lora TX FAILED') # determines the LORA MAC address (string) def getDeviceEUI(self): return ubinascii.hexlify(self.lora.mac()).decode('ascii').upper() # joins the lora network via OTAA def joinOTAA(self): app_eui = ubinascii.unhexlify(self.options['lora_app_eui']) app_key = ubinascii.unhexlify(self.options['lora_app_key']) self.lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) self.log("Joining via OTAA") self.lastJoin = time.time() # joins the lora network via ABP def joinABP(self): net_key = ubinascii.unhexlify(self.options['lora_net_key']) app_key = ubinascii.unhexlify(self.options['lora_app_key']) # note: TTN seems to want the reverse bytes of this address device_address = ubinascii.unhexlify(self.options['lora_dev_adr']) self.lora.join(activation=LoRa.ABP, auth=(device_address, net_key, app_key)) self.log("Joining via ABP with device address", device_address) self.lastJoin = time.time() # joins the lora network via ABP or OTAA def join(self): if self.options['lora_mode'] == "abp": self.joinABP() else: self.joinOTAA() def hasJoined(self): return self.lora.has_joined() def stats(self): return self.lora.stats() def makePayload(self, event): payload = None command = event['Command'] idbytes = event['ID'].to_bytes(2, 'little') event_ts = event['Time'] try: if command == eventlog.CMD_TAG_DETECTED: # Tag with 4-Byte UID detected # <0x01> <Event ID 0..1> <Timestamp 0..3> <UID 0..3/6/9> timeBytes = event_ts.to_bytes(4, 'little') uid = event['Data'][0:10] # remove trailing 0x00 uid_size = 10 for i in range(uid_size - 1, 3, -1): if uid[i] != 0x00: break uid_size = uid_size - 1 uid = uid[:uid_size] payload = bytes([0x01]) + idbytes + timeBytes + uid uidText = ubinascii.hexlify(uid).decode() self.log("CMD 0x01 [NFC_DETECTED] SEQ#", event['ID'], ". uid =", uidText, ", ts =", event_ts) if command == eventlog.CMD_TIME_REQUEST2: # ask backend for current time (new) # <0x04> <ID 0..1> <Our Time 0..3> mytime = time.time().to_bytes(4, 'little') payload = bytes([command]) + idbytes + mytime self.log("CMD 0x04 [TIME_REQUEST] ID#", event['ID'], ". our_time =", time.time(), utime.gmtime(time.time())) if command == eventlog.CMD_TIME_CHANGED: # <0x05> <Event ID 0..1> <Our Time 0..3> <Old Time 0..3> mytime = event_ts.to_bytes(4, 'little') oldTime = event['Data'][0:4] payload = bytes([eventlog.CMD_TIME_CHANGED ]) + idbytes + mytime + oldTime self.log("CMD 0x05 [TIME_CHANGED] SEQ#", event['ID'], ". our_time =", event_ts, utime.gmtime(event_ts), ", old_time =", oldTime) except Exception as e: self.log("ERROR: Unable to prepare LORA payload:", e.args[0], e) return payload # attempts to send the given event def sendEvent(self, event): with self.sendLock: eventId = event['ID'] command = event['Command'] self.log("Preparing to send CMD =", command, ", SEQ_NO =", eventId) if self.lastEventId > 0 and eventId > self.lastEventId + 1: self.log("ERROR", "Event IDs are not in sequence - last:", self.lastEventId, ", current:", eventId) self.lastEventId = eventId # prepare lora payload for supported event log entries payload = self.makePayload(event) if payload == None: self.log( "WARN: Event payload is None and therefore ignored for lora transmission" ) return True # send payload return self.sendAndHandleResponse(payload) # sends the payload and handles the optional response def sendAndHandleResponse(self, payload): if not self.hasJoined(): self.log("ERROR", "Unable to send LORA payload because not joined") return False # send responseData = self.sendPayload(payload) if responseData == False: self.noDownlinkCounter = self.noDownlinkCounter + 1 return False # handle response if responseData != None and len(responseData) > 0: try: return True except Exception as e: self.log("ERROR: Unable to handle LORA payload: ", e.args[0], e) self.noDownlinkCounter = self.noDownlinkCounter + 1 else: self.noDownlinkCounter = self.noDownlinkCounter + 1 # the message has been sent return True def sendTimeRequest(self, clockSyncEvent, clockSyncRequests): clockSyncEvent['Command'] = eventlog.CMD_TIME_REQUEST2 payload = self.makePayload(clockSyncEvent) try: with self.sendLock: # send lora uplink responseData = self.sendPayload(payload, False) if responseData == False: return None except Exception as e: self.log("ERROR", "Unable to sync clock via LORA:", e.args[0], e) return None # send the specified payload def sendPayload(self, data, updateTime=True): try: with self.socketLock: self.log("> sending", len(data), "bytes:", binascii.hexlify(data)) responseData = None # create a LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setblocking(False) try: """free_memory = gc.mem_free() allocated_memory = gc.mem_alloc() print("Free Memory: " + str(free_memory) + " -- Allocated Memory : " + str(allocated_memory))""" s.send(data) time.sleep(5) responseData = s.recv(64) except Exception as e: self.log("ERROR", "LORA Socket Exception", e) s.close() if responseData != None: responseLen = len(responseData) if responseLen > 0: self.log("< received", responseLen, "bytes:", binascii.hexlify(responseData)) else: self.log("< no downlink") # log if updateTime == True: self.lastUplinkTime = time.time() self.log(self.stats()) time.sleep_ms(10) # save frame counters self.lora.nvram_save() time.sleep_ms(5) return responseData except Exception as e: self.log("ERROR", "Unable to send payload", e.args[0], e) return False
class LoRaManager: """ """ def __init__(self, manager, settings): self.manager = manager self.settings = settings # LoRa settings. self.otaa_settings = self.settings.get('networking.lora.otaa') #self.generated_device_eui = binascii.hexlify(LoRa().mac()) def start(self): """ """ self.start_lora_join() self.wait_for_lora_join(42) time.sleep(2.5) if self.lora_joined: self.create_lora_socket() else: log.error("[LoRa] Could not join network") def start_lora_join(self): """ """ from network import LoRa #pycom.rgbled(0x0f0000) # red #self.lora = LoRa(mode=LoRa.LORAWAN, region=self.otaa_settings['region']) self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) # restore LoRa state from NVRAM after waking up from DEEPSLEEP. Rejoin otherwise if machine.reset_cause() == machine.DEEPSLEEP_RESET: self.lora.nvram_restore() log.info( '[LoRA] LoRaWAN state restored from NVRAM after deep sleep') else: self.lora.nvram_erase() log.info( '[LoRA] LoRaWAN state erased from NVRAM to let the device join the network' ) # Create LoRaWAN OTAA connection to TTN. app_eui = binascii.unhexlify(self.otaa_settings['application_eui']) app_key = binascii.unhexlify(self.otaa_settings['application_key']) # Remark: For Pycom Nanogateway. # Set the 3 default channels to the same frequency (must be before sending the otaa join request) #self.lora.add_channel(0, frequency=self.otaa_settings['frequency'], dr_min=0, dr_max=5) #self.lora.add_channel(1, frequency=self.otaa_settings['frequency'], dr_min=0, dr_max=5) #self.lora.add_channel(2, frequency=self.otaa_settings['frequency'], dr_min=0, dr_max=5) if not self.lora.has_joined(): if self.otaa_settings.get('device_eui') is None: self.lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) else: dev_eui = binascii.unhexlify(self.otaa_settings['device_eui']) self.lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0) def wait_for_lora_join(self, attempts): """ :param attempts: """ self.lora_joined = None for i in range(0, attempts): while not self.lora.has_joined(): time.sleep(2.5) #pycom.rgbled(0x0f0f00) # yellow time.sleep(0.1) log.info('[LoRA] Not joined yet...') #pycom.rgbled(0x000000) # off self.lora_joined = self.lora.has_joined() if self.lora_joined: log.info('[LoRA] joined...') # TODO: move nvram_save() to after payload send call self.lora.nvram_save() else: log.info('[LoRa] did not join in %s attempts', attempts) #for i in range(3, 16): # self.lora.remove_channel(i) return self.lora_joined def create_lora_socket(self): """ """ # create a lora socket self.lora_socket = None self.socket = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate #self.socket.setsockopt(socket.SOL_LORA, socket.SO_DR, self.otaa_settings['datarate']) self.socket.setsockopt(socket.SOL_LORA, socket.SO_DR, self.otaa_settings['datarate']) # make the socket non-blocking self.socket.setblocking(False) self.lora_socket = True log.info('[LoRa] socket created') for i in range(0, 2): #pycom.rgbled(0x000f00) # green time.sleep(0.1) #pycom.rgbled(0x000000) # off time.sleep(4.0) return self.lora_socket def lora_send(self, payload): """ :param payload: """ success = self.socket.send(payload) for i in range(0, 2): #pycom.rgbled(0x00000f) # green time.sleep(0.1) #pycom.rgbled(0x000000) # off return success def lora_receive(self): """ """ rx, port = self.socket.recvfrom(256) if rx: #pycom.rgbled(0x000f00) # green log.info('[LoRa] Received: {}, on port: {}'.format(rx, port)) #pycom.rgbled(0x000f00) # green time.sleep(6) return rx, port
class Comunication: def __init__(self): self.key = b'encriptaincendis' pass # Initialize LoRa in LORAWAN mode. def JoinLoraWan(self): self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) # create an OTA authentication params app_eui = ubinascii.unhexlify('70B3D57ED001C55E') dev_eui = ubinascii.unhexlify( '006D2D7767E7BAFE') # these settings can be found from TTN #app_eui = ubinascii.unhexlify('70B3D57ED0019255') # these settings can be found from TTN app_key = ubinascii.unhexlify('0A05862CEA15FC56C047FC03FBDF34DB' ) # these settings can be found from TTN # set the 3 default channels to the same frequency (must be before sending the OTAA join request) self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) # join a network using OTAA self.lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0) # wait until the module has joined the network while not self.lora.has_joined(): time.sleep(5) print('Not joined yet...') # remove all the non-default channels for i in range(3, 16): self.lora.remove_channel(i) # create a LoRa socket self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) # make the socket non-blocking self.s.setblocking(False) time.sleep(5) """ Your own code can be written below! """ def start_LoraRaw(self): self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setblocking(False) #Aquesta instrucció igual sobra #time.sleep(5) lora = self.lora #return(lora) def savestate(self): self.lora.nvram_save() # def restorestate(self): # self.lora.nvram_restore() def Switch_to_LoraRaw(self): self.lora.nvram_save() self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setblocking(False) #Aquesta instrucció igual sobra time.sleep(5) def Switch_to_LoraWan(self): self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) self.lora.nvram_restore() time.sleep(5) #Si no es reinicia el socket el missatge 3 no s'envia self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) def EnviarGateway(self, data): self.s.send(data) time.sleep(5) def RebreGateway(self): data, port = self.s.recvfrom(256) print(data) def sendData(self, misg): self.s.setblocking(True) iv = crypto.getrandbits( 128) # hardware generated random IV (never reuse it) cipher = AES(self.key, AES.MODE_CFB, iv) msg = iv + cipher.encrypt(misg) self.s.send(msg) self.s.setblocking(False) #print(msg) #print(len(msg)) time.sleep(5) def reciveData(self): self.s.setblocking(False) msg = self.s.recv(128) #Get any data recieved #If there's any data, decrypt if len(msg) > 0: print("encriptat: ", msg) cipher = AES(self.key, AES.MODE_CFB, msg[:16]) # on the decryption side original = cipher.decrypt(msg[16:]) print("original ", original) return (original) else: return
class LoRaManager: """ """ def __init__(self, manager, settings): self.manager = manager self.settings = settings # LoRa settings. self.otaa_settings = self.settings.get('networking.lora.otaa') #self.generated_device_eui = binascii.hexlify(LoRa().mac()) def start(self): """ """ self.start_lora_join() def start_lora_join(self): """ """ from network import LoRa if self.otaa_settings['region'] == 'AS923': lora_region = LoRa.AS923 elif self.otaa_settings['region'] == 'AU915': lora_region = LoRa.AU915 elif self.otaa_settings['region'] == 'EU868': lora_region = LoRa.EU868 elif self.otaa_settings['region'] == 'US915': lora_region = LoRa.US915 lora_adr = self.otaa_settings['adr'] or False self.lora_socket = None self.lora = LoRa(mode=LoRa.LORAWAN, region=lora_region, adr=lora_adr) # restore LoRa state from NVRAM after waking up from DEEPSLEEP. Reset LoRa NVRAM and rejoin otherwise if machine.reset_cause() == machine.DEEPSLEEP_RESET: self.lora.nvram_restore() log.info( '[LoRa] LoRaWAN state restored from NVRAM after deep sleep') else: self.lora.nvram_erase() log.info('[LoRa] LoRaWAN state erased from NVRAM. Rejoin forced') # Create LoRaWAN OTAA connection to TTN. app_eui = binascii.unhexlify(self.otaa_settings['application_eui']) app_key = binascii.unhexlify(self.otaa_settings['application_key']) if not self.lora.has_joined(): log.info('[LoRa] joining the network...') if self.otaa_settings.get('device_eui') is None: self.lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) else: dev_eui = binascii.unhexlify(self.otaa_settings['device_eui']) self.lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0) def wait_for_lora_join(self, attempts): """ :param attempts: """ self.lora_joined = None for i in range(0, attempts): while not self.lora.has_joined(): log.info('[LoRa] Not joined yet...') time.sleep(2.5) self.lora_joined = self.lora.has_joined() if self.lora_joined: log.info('[LoRa] joined...') else: log.info('[LoRa] did not join in %s attempts', attempts) return self.lora_joined def create_lora_socket(self): """ """ # create a lora socket self.socket = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.socket.settimeout(6.0) self.lora_socket = True log.info('[LoRa] socket created') return self.lora_socket def lora_send(self, payload): """ :param payload: """ self.socket.setblocking(True) success = self.socket.send(payload) self.socket.setblocking(False) self.lora.nvram_save() return success def lora_receive(self): """ """ import binascii try: rx, port = self.socket.recvfrom(256) except socket.timeout: log.info('[LoRa] no packet received within receive window ') if rx: log.info('[LoRa] Received: {}, on port: {}'.format(rx, port)) return rx, port
# currently moving, wait between next GPS send time.sleep(30) send_data_lorawan() elif wakeup == WAKE_REASON_TIMER: # increment counter pulse = pycom.nvs_get('count') if pulse == None: pulse = 0 print("Wakeup Timer count: " + str(pulse)) pulse += 1 if pulse == config.COUNT_CYCLES: pulse = 0 print("--SEND TIMER") # Try to acquire GPS time.sleep(30) send_data_lorawan() pycom.nvs_set('count', pulse) # Save LoRaWAN states before deepsleep lora.nvram_save() # Enable activity and disable inactivity interrupts, using the default callback handler py.setup_int_wake_up(True, False) # enable the activity/inactivity interrupts # set the accelereation threshold to 200mG and the min duration to 100ms acc.enable_activity_interrupt(1000, 200) print("Go Deep Sleep") time.sleep(0.2) # go to sleep for 5 minutes maximum if no accelerometer interrupt happens py.setup_sleep(config.SLEEP_TIMER) py.go_to_sleep()
class Comunication: def __init__(self): self.key = b'encriptaincendis' pass def start_LoraRaw(self): self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setblocking(False)#Aquesta instrucció igual sobra time.sleep(5) lora=self.lora #return(lora) def change_txpower(self,power): self.lora.tx_power(power) def savestate(self): self.lora.nvram_save() def sendData(self,msg,rtc,f): if "Hay" not in msg: f=open('/sd/msg_sent_middle1.txt','a') f.write("{}/{}/{} {}:{}:{} msg {} stats {}\n".format(rtc.now()[2],rtc.now()[1],rtc.now()[0],rtc.now()[3],rtc.now()[4],rtc.now()[5],msg,self.lora.stats())) f.close() self.s.setblocking(True) iv = crypto.getrandbits(128) # hardware generated random IV (never reuse it) cipher = AES(self.key, AES.MODE_CFB, iv) misg_crc=msg+" "+str(self.calculate_crc(msg)) msg = iv + cipher.encrypt(misg_crc) self.s.send(msg) self.s.setblocking(False) #print(msg) #print(len(msg)) #time.sleep(5) def reciveData(self,rtc,f): self.s.setblocking(False) msg=self.s.recv(128)#Get any data recieved #If there's any data, decrypt if (len(msg)>0): try: #print("encriptat: ",msg) cipher = AES(self.key, AES.MODE_CFB, msg[:16]) # on the decryption side original = cipher.decrypt(msg[16:]) print("original ",original) if "Config" in original or "stop" in original or "Discover" in original or "Hello" in original or "Info" in original or "Token" in original or "Alarm" in original or "Hay" in original: crc_OK,msg=self.check_crc(original) if crc_OK: if "Hay" not in msg: f=open('/sd/msg_received_middle1.txt','a') f.write("{}/{}/{} {}:{}:{} msg {} stats {}\n".format(rtc.now()[2],rtc.now()[1],rtc.now()[0],rtc.now()[3],rtc.now()[4],rtc.now()[5],msg,self.lora.stats())) f.close() return(msg) else: print("CRC not OK") return("error") else: return("error") except Exception as e: print(e) return("error") else: return("error") def update_neighbours(self,pow,id_n,neighbours): if id_n in neighbours[0]: if pow < neighbours[1][neighbours[0].index(id_n)]: neighbours[1][neighbours[0].index(id_n)]=pow else: neighbours[0].append(id_n) neighbours[1].append(pow) #print("I have a friend ") print(neighbours) return neighbours def neighbours_min(self,neighbours,neighbours_aux): for id in neighbours[0]: if id in neighbours_aux[0]: neighbours[1][neighbours[0].index(id)]=min(neighbours[1][neighbours[0].index(id)],neighbours_aux[1][neighbours_aux[0].index(id)]) print(neighbours) return(neighbours) def calculate_crc(self,msg): """ Compute CRC """ if type(msg)==bytes: msg=bytes.decode(msg) crc = 0 data=bin(int(binascii.hexlify(msg),16)) data=str.encode(data) for i in range(len(data)): byte = data[i] for b in range(8): fb_bit = (crc ^ byte) & 0x01 if fb_bit == 0x01: crc = crc ^ 0x18 crc = (crc >> 1) & 0x7f if fb_bit == 0x01: crc = crc | 0x80 byte = byte >> 1 return crc def check_crc(self,msg): """ Check if CRC received is correct """ if type(msg)==bytes: msg=bytes.decode(msg) splitmsg=msg.split( ) crc_rcv=int(splitmsg[-1]) aux=" ".join(splitmsg[:-1]) #Not including the CRC received crc_new = self.calculate_crc(aux) return (crc_new==crc_rcv,aux)
class Comunication: def __init__(self): self.key = b'encriptaincendis' self.node_list = "" pass # Initialize LoRa in LORAWAN mode. def JoinLoraWan(self): self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) # create an OTA authentication params app_eui = ubinascii.unhexlify('70B3D57ED001C55E') dev_eui = ubinascii.unhexlify( '006D2D7767E7BAFE') # these settings can be found from TTN #app_eui = ubinascii.unhexlify('70B3D57ED0019255') # these settings can be found from TTN app_key = ubinascii.unhexlify('0A05862CEA15FC56C047FC03FBDF34DB' ) # these settings can be found from TTN # set the 3 default channels to the same frequency (must be before sending the OTAA join request) self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) # join a network using OTAA self.lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0) # wait until the module has joined the network while not self.lora.has_joined(): time.sleep(2.5) print('Not joined yet...') # remove all the non-default channels for i in range(3, 16): self.lora.remove_channel(i) # create a LoRa socket self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate. DR5 means 5470 bits/s ans max payload=230 self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) # make the socket non-blocking self.s.setblocking(False) time.sleep(5) def start_LoraRaw(self): self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setblocking(False) #Aquesta instrucció igual sobra time.sleep(5) lora = self.lora #return(lora) def change_txpower(self, power): self.lora.tx_power(power) def savestate(self): self.lora.nvram_save() def Switch_to_LoraRaw(self): self.lora.nvram_save() self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setblocking(False) #Aquesta instrucció igual sobra time.sleep(5) def Switch_to_LoraWan(self): self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) self.lora.nvram_restore() time.sleep(2.5) #Si no es reinicia el socket self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) self.s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, False) def EnviarGateway(self, data): self.s.bind(2) self.s.send(data) time.sleep(10) def sendData(self, msg, rtc, f): if "Hay" not in msg: f = open('msg_sent_final.txt', 'a') f.write("{}/{}/{} {}:{}:{} msg {} stats {}\n".format( rtc.now()[2], rtc.now()[1], rtc.now()[0], rtc.now()[3], rtc.now()[4], rtc.now()[5], msg, self.lora.stats())) f.close() self.s.setblocking(True) iv = crypto.getrandbits( 128) # hardware generated random IV (never reuse it) cipher = AES(self.key, AES.MODE_CFB, iv) misg_crc = msg + " " + str(self.calculate_crc(msg)) msg = iv + cipher.encrypt(misg_crc) self.s.send(msg) #print("missatge amb crc", msg) self.s.setblocking(False) #print(msg) #print(len(msg)) #time.sleep(5) def reciveData(self, rtc, f): self.s.setblocking(False) msg = self.s.recv(128) #Get any data recieved #If there's any data, decrypt if (len(msg) > 0): try: #print("encriptat: ",msg) cipher = AES(self.key, AES.MODE_CFB, msg[:16]) # on the decryption side original = cipher.decrypt(msg[16:]) print("original ", original) if "Config" in original or "stop" in original or "Discover" in original or "Hello" in original or "Info" in original or "Token" in original or "Alarm" in original or "Hay" in original: crc_OK, msg = self.check_crc(original) if crc_OK: if "Hay" not in msg: f = open('msg_received_final.txt', 'a') f.write( "{}/{}/{} {}:{}:{} msg {} stats {}\n".format( rtc.now()[2], rtc.now()[1], rtc.now()[0], rtc.now()[3], rtc.now()[4], rtc.now()[5], msg, self.lora.stats())) f.close() return (msg) else: print("CRC not OK") return ("error") else: return ("error") print("Keyword not in msg") except: return ("error") print("Exception") else: return ("error") print("Empty msg") def update_neighbours(self, pow, id_n, neighbours): if id_n in neighbours[0]: if pow < neighbours[1][neighbours[0].index(id_n)]: neighbours[1][neighbours[0].index(id_n)] = pow else: neighbours[0].append(id_n) neighbours[1].append(pow) #print("I have a friend ") print(neighbours) return neighbours def neighbours_min(self, neighbours, neighbours_aux, id): for id in neighbours[0]: if id in neighbours_aux[0]: neighbours[1][neighbours[0].index(id)] = min( neighbours[1][neighbours[0].index(id)], neighbours_aux[1][neighbours_aux[0].index(id)]) print(neighbours) return (neighbours) def ApplyFormat(self, splitmsg): packet_dust = ustruct.pack('H', int(splitmsg[3])) #Unsigned short 2 bytes packet_tempC = ustruct.pack('H', int(splitmsg[4])) packet_Tht = ustruct.pack('H', int(splitmsg[5])) packet_Hht = ustruct.pack( 'B', round(int(splitmsg[6]) * 100)) #Form 0 to 1 -> 0% to 100% #Unsigned char 1 byte packet_tbmp = ustruct.pack('H', int(splitmsg[7])) packet_val = ustruct.pack('H', int(splitmsg[8])) packet_dhi = ustruct.pack('B', int(splitmsg[9])) #+packet_TCam=ustruct.pack('f',int(splitmsg[10])) #id=splitmsg[1].encode('utf-8') id_aux = ustruct.pack('>Q', int(splitmsg[1], 16)) #long long: 8 bytes return (packet_dust + packet_tempC + packet_Tht + packet_Hht + packet_tbmp + packet_val + packet_dhi + id_aux) #+packet_TCam) def calculate_crc(self, msg): """ Compute CRC """ if type(msg) == bytes: msg = bytes.decode(msg) crc = 0 data = bin(int(binascii.hexlify(msg), 16)) data = str.encode(data) for i in range(len(data)): byte = data[i] for b in range(8): fb_bit = (crc ^ byte) & 0x01 if fb_bit == 0x01: crc = crc ^ 0x18 crc = (crc >> 1) & 0x7f if fb_bit == 0x01: crc = crc | 0x80 byte = byte >> 1 return crc def check_crc(self, msg): """ Check if CRC received is correct """ if type(msg) == bytes: msg = bytes.decode(msg) splitmsg = msg.split() crc_rcv = int(splitmsg[-1]) aux = " ".join(splitmsg[:-1]) #Not including the CRC received crc_new = self.calculate_crc(aux) return (crc_new == crc_rcv, aux) def get_node_list(self, list): self.node_list = list
class Node: def __init__(self, data_rate, py): self.lora = None # Instancia de Lora (sin inicializar) self.s = None # Instancia Socket (sin inicializar) self.dr = data_rate # Data Rate (defecto 5) self.py = py # Instancia de Pysense self.acc = LIS2HH12(self.py) # Instancia del Acelerometro self.last = [0, 0, 0] # Último valor leído de aceleracion self.raw = [0, 0, 0] # Valor leído actual de aceleracion self.busy = 0 # Value has passed limit self.interval = 10 # Intervalo de toma de datos self.battery = None # Valor de la tensión de batería self.s_lock = _thread.allocate_lock() # Semaforo para envío #------------------------------------------------------------------------------# def connect(self, dev_eui, app_eui, app_key): """ Connect device to LoRa. Set the socket and lora instances. """ # Initialize LoRa in LORAWAN mode self.lora = LoRa(mode=LoRa.LORAWAN, device_class=LoRa.CLASS_A) # Set the 3 default channels to the same frequency (must be before # sending the OTAA join request) self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) # Join a network using OTAA (Over the Air Activation) self.lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=5) #login for TheThingsNetwork see here: #https://www.thethingsnetwork.org/forum/t/lopy-otaa-example/4471 # Wait until the module has joined the network while not self.lora.has_joined(): print("Trying to join LoraWAN with OTAA") time.sleep(2.5) print("LoraWAN joined! ") #Handler de Recepción #self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT),handler=self.lora_cb) # save the LoRaWAN connection state self.lora.nvram_save() #------------------------------------------------------------------------------# def send(self, data): """ Send data over the network. """ self.s_lock.acquire( ) # Espera a que el semáforo esté disponible (tiempo indefinido) if py.get_wake_reason( ) == WAKE_REASON_ACCELEROMETER: #Si despierta tras deepsleep # Initialize LoRa in LORAWAN mode self.lora = LoRa(mode=LoRa.LORAWAN, adr=True, device_class=LoRa.CLASS_A) # restore the LoRaWAN connection state try: self.lora.nvram_restore() except OSError: print("Error: LoRa Configuration could not be restored") self.connect( binascii.unhexlify('006A76B0778AEDA7'), binascii.unhexlify('70B3D57ED0009ABB'), binascii.unhexlify('08D62712D816F1C28B7E6EA39E711209')) print("LoRa Connection Parameters Recovered") for i in range(3, 16): self.lora.remove_channel(i) # Set the 3 default channels to the same frequency # (must be before sending the OTAA join request) self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) # Create a LoRa socket self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) print("Created LoRaWAN socket") # Make the socket non-blocking self.s.setblocking(True) try: self.s.send(data) self.s.setblocking(False) #Espera para posible recepción rx = bytes(self.s.recv(128)) #Recepción de datos self.receive(rx=rx) self.lora.nvram_save() except OSError as e: if e.errno == 11: print("Caught exception while sending") print("errno: ", e.errno) self.s_lock.release() #Libera el semáforo _thread.exit() #Cierra el hilo #------------------------------------------------------------------------------# #Función de recpeción de datos.Es activada tras la ventana de recepción #posterior al envío. def receive(self, rx=None): if len(rx) == 0: #No hay mensaje de recepción pass else: if rx[0] == 82: #Orden de Cambio Data Rate (ASCII hex R=0x52 dec 87) print("Cambiando Data Rate %d" % (int.from_bytes(rx[1:], 'big'))) self.dr = int.from_bytes( rx[1:], 'big') #Decodifica el valor del nuevo data Rate pycom.nvs_set('data_rate', self.data_rate) #Lo guarda en NVRAM else: pass #------------------------------------------------------------------------------# #Función de lectura de medidas. Los sensores ya han sido inicializados al #crear la instancia de la clase Node def readsens(self): self.raw = self.acc.acceleration( ) # Devuelve tuple con aceleracion en tres ejes (G) print("Aceleracion-> X:%fG Y:%fG Z:%fG" % (self.raw[0], self.raw[1], self.raw[2])) #Cálculos #if (self.raw[0] > 2.1) or (self.raw[1] > 2.1) or (self.raw[2] > 2.1): # print("Enviando datos") # XR=int(self.raw[0]*10000).to_bytes(2,'little') # YR=int(self.raw[1]*10000).to_bytes(2,'little') # ZR=int(self.raw[2]*10000).to_bytes(2,'little') # XL=int(self.last[0]*10000).to_bytes(2,'little') # YL=int(self.last[1]*10000).to_bytes(2,'little') # ZL=int(self.last[2]*10000).to_bytes(2,'little') # data = XR+YR+ZR+XL+YL+ZL # _thread.start_new_thread(self.send,data) # Se crea un hilo para el envío de valores self._compare_update() alarmaPub = Timer.Alarm(self.readsens(), 10, periodic=False) #if (self.raw[0] < 1.5) and (self.raw[1] < 1.5) and (self.raw[2] < 1.5): # alarmaPub.cancel(); # n.py.setup_int_wake_up(rising=True,falling=False) #Activa la interrupcion para el boton DEBUG # print('Activada Interrupccion de Actividad') # n.acc.enable_activity_interrupt(1500,100) #Threshold= 1,5G, Min Time = 100ms # print("Going to Sleep") # n.py.setup_sleep(300) # n.py.go_to_sleep() #self.battery = round(self.py.read_battery_voltage(),2) #print("Battery: %f",%(self.battery)) #if (self.battery < 3.4): # print("Batería Crítica") # _thread.start_new_thread(self.send,("Batería"," Crítica")) # Se crea un hilo para el envío de alarma de batería #------------------------------------------------------------------------------# def _compare_update(self): if self.raw is not self.last: self.last = self.raw else: pass