class Lora(Connection): """Putting sensor data onto the Enabling platform. USING LoRa""" def __init__(self, deviceAddress, applicationKey, networkKey): from network import LoRa import socket import binascii import struct self.deviceAddress = deviceAddress self.applicationKey = applicationKey self.networkKey = networkKey self.lora = LoRa(mode=LoRa.LORAWAN) dev_addr = struct.unpack(">l", binascii.unhexlify(deviceAddress.replace(' ','')))[0] nwk_swkey = binascii.unhexlify(networkKey.replace(' ','')) app_swkey = binascii.unhexlify(applicationKey.replace(' ','')) self.lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey)) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) self.s.setblocking(False) def pushSensorData(self, enCoSensor, debug = False, forceCreateChannel = False): try: self.s.send(bytes(enCoSensor.getLoRaPacket())) data = self.s.recv(64) if data: print(data) except AttributeError as err: print("Unable to send sensor over the loar network. Unable to convert to binary stream!") print (err)
def start(self): # Change WiFi to STA mode and connect self.wlan = WLAN(mode=WLAN.STA) self._connect_to_wifi() # Get a time Sync self.rtc = machine.RTC() self.rtc.ntp_sync(self.ntp, update_period=self.ntp_period) # Get the server IP and create an UDP socket self.server_ip = socket.getaddrinfo(self.server, self.port)[0][-1] self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.setblocking(False) # Push the first time immediatelly self._push_data(self._make_stat_packet()) # Create the alarms self.stat_alarm = Timer.Alarm(handler=lambda t: self._push_data(self._make_stat_packet()), s=60, periodic=True) self.pull_alarm = Timer.Alarm(handler=lambda u: self._pull_data(), s=25, periodic=True) # Start the UDP receive thread _thread.start_new_thread(self._udp_thread, ()) # Initialize LoRa in LORA mode self.lora = LoRa(mode=LoRa.LORA, frequency=self.frequency, bandwidth=LoRa.BW_125KHZ, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True) # Create a raw LoRa socket self.lora_sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.lora_sock.setblocking(False) self.lora_tx_done = False self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=self._lora_cb)
def __init__(self): self.sock = None self.connected = False self.wlan = WLAN(mode=WLAN.STA) self.riders = {} # dictionary of riders # initialize LoRa as a Gateway (with Tx IQ inversion) self.lora = LoRa(tx_iq=True, rx_iq=False)
class Startiot: def __init__(self): self.dev_eui = binascii.unhexlify("**REMOVED**") self.app_eui = binascii.unhexlify("**REMOVED**") self.app_key = binascii.unhexlify("**REMOVED**") self.lora = LoRa(mode=LoRa.LORAWAN) def connect(self, blocking = False, timeout = 0, function = None): 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: time.sleep(2.5) else: function() else: for x in range(timeout): if self.lora.has_joined(): break if function == None: time.sleep(2.5) else: function() if not self.lora.has_joined(): return False 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) return True def send(self, data): self.s.send(data) def recv(self, length): return self.s.recv(length)
def start(self): """ Starts the LoRaWAN nano gateway. """ self._log('Starting LoRaWAN nano gateway with id: {}', self.id) # setup WiFi as a station and connect self.wlan = WLAN(mode=WLAN.STA) self._connect_to_wifi() # get a time sync self._log('Syncing time with {} ...', self.ntp_server) self.rtc.ntp_sync(self.ntp_server, update_period=self.ntp_period) while not self.rtc.synced(): utime.sleep_ms(50) self._log("RTC NTP sync complete") # get the server IP and create an UDP socket self.server_ip = usocket.getaddrinfo(self.server, self.port)[0][-1] self._log('Opening UDP socket to {} ({}) port {}...', self.server, self.server_ip[0], self.server_ip[1]) self.sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM, usocket.IPPROTO_UDP) self.sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1) self.sock.setblocking(False) # push the first time immediatelly self._push_data(self._make_stat_packet()) # create the alarms self.stat_alarm = Timer.Alarm(handler=lambda t: self._push_data(self._make_stat_packet()), s=60, periodic=True) self.pull_alarm = Timer.Alarm(handler=lambda u: self._pull_data(), s=25, periodic=True) # start the UDP receive thread self.udp_stop = False _thread.start_new_thread(self._udp_thread, ()) # initialize the LoRa radio in LORA mode self._log('Setting up the LoRa radio at {:.1f} Mhz using {}', self._freq_to_float(self.frequency), self.datarate) self.lora = LoRa( mode=LoRa.LORA, frequency=self.frequency, bandwidth=self.bw, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True ) # create a raw LoRa socket self.lora_sock = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW) self.lora_sock.setblocking(False) self.lora_tx_done = False self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=self._lora_cb) self._log('LoRaWAN nano gateway online')
def start(self): # Initialize a LoRa sockect self.lora = LoRa(mode=LoRa.LORA) self.lora_sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.lora_sock.setblocking(False) #self.tcp_alarm = Timer.Alarm(handler=lambda u: self._tcp_gps(), s=1, periodic=True) self.lora.callback(trigger=LoRa.RX_PACKET_EVENT, handler=self._lora_cb) # Start the TCP thread receiving GPS coordinates _thread.start_new_thread(self._tcp_thread, ())
def __init__(self, deviceAddress, applicationKey, networkKey): from network import LoRa import socket import binascii import struct self.deviceAddress = deviceAddress self.applicationKey = applicationKey self.networkKey = networkKey self.lora = LoRa(mode=LoRa.LORAWAN) dev_addr = struct.unpack(">l", binascii.unhexlify(deviceAddress.replace(' ','')))[0] nwk_swkey = binascii.unhexlify(networkKey.replace(' ','')) app_swkey = binascii.unhexlify(applicationKey.replace(' ','')) self.lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey)) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) self.s.setblocking(False)
""" OTAA Node example compatible with the LoPy Nano Gateway """ from network import LoRa import socket import binascii import struct import time import config # initialize LoRa in LORAWAN mode. lora = LoRa(mode=LoRa.LORAWAN) # create an OTA authentication params dev_eui = binascii.unhexlify('AA BB CC DD EE FF 77 78'.replace(' ','')) app_eui = binascii.unhexlify('70 B3 D5 7E F0 00 3B FD'.replace(' ','')) app_key = binascii.unhexlify('36 AB 76 25 FE 77 0B 68 81 68 3B 49 53 00 FF D6'.replace(' ','')) # remove all the channels for channel in range(0, 72): lora.remove_channel(channel) # set all channels to the same frequency (must be before sending the OTAA join request) for channel in range(0, 72): lora.add_channel(channel, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=3) # join a network using OTAA lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=config.LORA_NODE_DR) # wait until the module has joined the network join_wait = 0 while True:
class NanoGateway: """ Nano gateway class, set up by default for use with TTN, but can be configured for any other network supporting the Semtech Packet Forwarder. Only required configuration is wifi_ssid and wifi_password which are used for connecting to the Internet. """ def __init__(self, id, frequency, datarate, ssid, password, server, port, ntp_server='pool.ntp.org', ntp_period=3600): self.id = id self.server = server self.port = port self.frequency = frequency self.datarate = datarate self.ssid = ssid self.password = password self.ntp_server = ntp_server self.ntp_period = ntp_period self.server_ip = None self.rxnb = 0 self.rxok = 0 self.rxfw = 0 self.dwnb = 0 self.txnb = 0 self.sf = self._dr_to_sf(self.datarate) self.bw = self._dr_to_bw(self.datarate) self.stat_alarm = None self.pull_alarm = None self.uplink_alarm = None self.wlan = None self.sock = None self.udp_stop = False self.udp_lock = _thread.allocate_lock() self.lora = None self.lora_sock = None self.rtc = machine.RTC() def start(self): """ Starts the LoRaWAN nano gateway. """ self._log('Starting LoRaWAN nano gateway with id: {}', self.id) # setup WiFi as a station and connect self.wlan = WLAN(mode=WLAN.STA) self._connect_to_wifi() # get a time sync self._log('Syncing time with {} ...', self.ntp_server) self.rtc.ntp_sync(self.ntp_server, update_period=self.ntp_period) while not self.rtc.synced(): utime.sleep_ms(50) self._log("RTC NTP sync complete") # get the server IP and create an UDP socket self.server_ip = usocket.getaddrinfo(self.server, self.port)[0][-1] self._log('Opening UDP socket to {} ({}) port {}...', self.server, self.server_ip[0], self.server_ip[1]) self.sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM, usocket.IPPROTO_UDP) self.sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1) self.sock.setblocking(False) # push the first time immediatelly self._push_data(self._make_stat_packet()) # create the alarms self.stat_alarm = Timer.Alarm(handler=lambda t: self._push_data(self._make_stat_packet()), s=60, periodic=True) self.pull_alarm = Timer.Alarm(handler=lambda u: self._pull_data(), s=25, periodic=True) # start the UDP receive thread self.udp_stop = False _thread.start_new_thread(self._udp_thread, ()) # initialize the LoRa radio in LORA mode self._log('Setting up the LoRa radio at {:.1f} Mhz using {}', self._freq_to_float(self.frequency), self.datarate) self.lora = LoRa( mode=LoRa.LORA, frequency=self.frequency, bandwidth=self.bw, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True ) # create a raw LoRa socket self.lora_sock = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW) self.lora_sock.setblocking(False) self.lora_tx_done = False self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=self._lora_cb) self._log('LoRaWAN nano gateway online') def stop(self): """ Stops the LoRaWAN nano gateway. """ self._log('Stopping...') # send the LoRa radio to sleep self.lora.callback(trigger=None, handler=None) self.lora.power_mode(LoRa.SLEEP) # stop the NTP sync self.rtc.ntp_sync(None) # cancel all the alarms self.stat_alarm.cancel() self.pull_alarm.cancel() # signal the UDP thread to stop self.udp_stop = True while self.udp_stop: utime.sleep_ms(50) # disable WLAN self.wlan.disconnect() self.wlan.deinit() def _connect_to_wifi(self): self.wlan.connect(self.ssid, auth=(None, self.password)) while not self.wlan.isconnected(): utime.sleep_ms(50) self._log('WiFi connected to: {}', self.ssid) def _dr_to_sf(self, dr): sf = dr[2:4] if sf[1] not in '0123456789': sf = sf[:1] return int(sf) def _dr_to_bw(self, dr): bw = dr[-5:] if bw == 'BW125': return LoRa.BW_125KHZ elif bw == 'BW250': return LoRa.BW_250KHZ else: return LoRa.BW_500KHZ def _sf_bw_to_dr(self, sf, bw): dr = 'SF' + str(sf) if bw == LoRa.BW_125KHZ: return dr + 'BW125' elif bw == LoRa.BW_250KHZ: return dr + 'BW250' else: return dr + 'BW500' def _lora_cb(self, lora): """ LoRa radio events callback handler. """ events = lora.events() if events & LoRa.RX_PACKET_EVENT: self.rxnb += 1 self.rxok += 1 rx_data = self.lora_sock.recv(256) stats = lora.stats() packet = self._make_node_packet(rx_data, self.rtc.now(), stats.rx_timestamp, stats.sfrx, self.bw, stats.rssi, stats.snr) self._push_data(packet) self._log('Received packet: {}', packet) self.rxfw += 1 if events & LoRa.TX_PACKET_EVENT: self.txnb += 1 lora.init( mode=LoRa.LORA, frequency=self.frequency, bandwidth=self.bw, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True ) def _freq_to_float(self, frequency): """ MicroPython has some inprecision when doing large float division. To counter this, this method first does integer division until we reach the decimal breaking point. This doesn't completely elimate the issue in all cases, but it does help for a number of commonly used frequencies. """ divider = 6 while divider > 0 and frequency % 10 == 0: frequency = frequency // 10 divider -= 1 if divider > 0: frequency = frequency / (10 ** divider) return frequency def _make_stat_packet(self): now = self.rtc.now() STAT_PK["stat"]["time"] = "%d-%02d-%02d %02d:%02d:%02d GMT" % (now[0], now[1], now[2], now[3], now[4], now[5]) STAT_PK["stat"]["rxnb"] = self.rxnb STAT_PK["stat"]["rxok"] = self.rxok STAT_PK["stat"]["rxfw"] = self.rxfw STAT_PK["stat"]["dwnb"] = self.dwnb STAT_PK["stat"]["txnb"] = self.txnb return ujson.dumps(STAT_PK) def _make_node_packet(self, rx_data, rx_time, tmst, sf, bw, rssi, snr): RX_PK["rxpk"][0]["time"] = "%d-%02d-%02dT%02d:%02d:%02d.%dZ" % (rx_time[0], rx_time[1], rx_time[2], rx_time[3], rx_time[4], rx_time[5], rx_time[6]) RX_PK["rxpk"][0]["tmst"] = tmst RX_PK["rxpk"][0]["freq"] = self._freq_to_float(self.frequency) RX_PK["rxpk"][0]["datr"] = self._sf_bw_to_dr(sf, bw) RX_PK["rxpk"][0]["rssi"] = rssi RX_PK["rxpk"][0]["lsnr"] = snr RX_PK["rxpk"][0]["data"] = ubinascii.b2a_base64(rx_data)[:-1] RX_PK["rxpk"][0]["size"] = len(rx_data) return ujson.dumps(RX_PK) def _push_data(self, data): token = uos.urandom(2) packet = bytes([PROTOCOL_VERSION]) + token + bytes([PUSH_DATA]) + ubinascii.unhexlify(self.id) + data with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception as ex: self._log('Failed to push uplink packet to server: {}', ex) def _pull_data(self): token = uos.urandom(2) packet = bytes([PROTOCOL_VERSION]) + token + bytes([PULL_DATA]) + ubinascii.unhexlify(self.id) with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception as ex: self._log('Failed to pull downlink packets from server: {}', ex) def _ack_pull_rsp(self, token, error): TX_ACK_PK["txpk_ack"]["error"] = error resp = ujson.dumps(TX_ACK_PK) packet = bytes([PROTOCOL_VERSION]) + token + bytes([PULL_ACK]) + ubinascii.unhexlify(self.id) + resp with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception as ex: self._log('PULL RSP ACK exception: {}', ex) def _send_down_link(self, data, tmst, datarate, frequency): """ Transmits a downlink message over LoRa. """ self.lora.init( mode=LoRa.LORA, frequency=frequency, bandwidth=self._dr_to_bw(datarate), sf=self._dr_to_sf(datarate), preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True ) while utime.ticks_us() < tmst: pass self.lora_sock.send(data) self._log( 'Sent downlink packet scheduled on {:.3f}, at {:.1f} Mhz using {}: {}', tmst / 1000000, self._freq_to_float(frequency), datarate, data ) def _udp_thread(self): """ UDP thread, reads data from the server and handles it. """ while not self.udp_stop: try: data, src = self.sock.recvfrom(1024) _token = data[1:3] _type = data[3] if _type == PUSH_ACK: self._log("Push ack") elif _type == PULL_ACK: self._log("Pull ack") elif _type == PULL_RESP: self.dwnb += 1 ack_error = TX_ERR_NONE tx_pk = ujson.loads(data[4:]) tmst = tx_pk["txpk"]["tmst"] t_us = tmst - utime.ticks_us() - 12500 if t_us < 0: t_us += 0xFFFFFFFF if t_us < 20000000: self.uplink_alarm = Timer.Alarm( handler=lambda x: self._send_down_link( ubinascii.a2b_base64(tx_pk["txpk"]["data"]), tx_pk["txpk"]["tmst"] - 50, tx_pk["txpk"]["datr"], int(tx_pk["txpk"]["freq"] * 1000000) ), us=t_us ) else: ack_error = TX_ERR_TOO_LATE self._log('Downlink timestamp error!, t_us: {}', t_us) self._ack_pull_rsp(_token, ack_error) self._log("Pull rsp") except usocket.timeout: pass except OSError as ex: if ex.errno != errno.EAGAIN: self._log('UDP recv OSError Exception: {}', ex) except Exception as ex: self._log('UDP recv Exception: {}', ex) # wait before trying to receive again utime.sleep_ms(UDP_THREAD_CYCLE_MS) # we are to close the socket self.sock.close() self.udp_stop = False self._log('UDP thread stopped') def _log(self, message, *args): """ Outputs a log message to stdout. """ print('[{:>10.3f}] {}'.format( utime.ticks_ms() / 1000, str(message).format(*args) ))
class LGW: lora = None sock = None app_eui = None app_key = None dev_eui = None id = -1 timer = 0 NbIN = 0 idRegistered = [] isRegistered = [] frequency = 1 discovered = False slot = 10 MyLW = 0 nb_harvest = 0 listeningTime = 10.0 data = 666 def __init__(self,app_eui,app_key,dev_eui,id,frequency,slot): # create an OTAA authentication parameters self.app_eui=binascii.unhexlify(app_eui) self.app_key=binascii.unhexlify(app_key) self.dev_eui=binascii.unhexlify(dev_eui) self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) self.id=id self.frequency=frequency self.slot=slot #self.isListening=True pycom.heartbeat(False) pycom.rgbled(0xff00) def start(self): global isListening # join a network using OTAA (Over the Air Activation) self.lora.join(activation=LoRa.OTAA, auth=(self.dev_eui,self.app_eui,self.app_key), timeout=0) # wait until the module has joined the network while not self.lora.has_joined(): time.sleep(2.5) print('Not yet joined...') print('Connected to Objenious LoRaWAN!') self.sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) self.sock.setblocking(True) # send some data self.sock.send(bytes([0x01, 0x02, 0x03])) # make the socket non-blocking # (because if there's no data received it will block forever...) self.sock.setblocking(False) self.changetoLoRa() time.sleep(2.5) clock = TimerL(self.slot,2) while True: if isListening: try: pycom.rgbled(0x007f00) # green data = self.sock.recv(128) self.handle_message(data) time.sleep(1.500) self.handle_message(data) time.sleep(1.500) recolte=self.standard() time.sleep(1.500) if recolte !="" : #[BEGIN] sending data from IN attached to me deveui_custom=[] data_custom=[] print("first split") devices=recolte.split(":") for deviceIN in devices: print(deviceIN) print("second split") device_custom,data_custom=deviceIN.split(",") print(device_custom) print(data_custom) self.change_AND_send_toLW(device_custom, data_custom) #[END] sending data from IN attached to me time.sleep(1.500) self.changetoLW() time.sleep(1.500) self.sock.setblocking(True) #print(recolte) time.sleep(2) self.send_datatoLWGW(str(self.data)) self.changetoLoRa() self.sock.setblocking(False) except OSError as err: print("OS error: {0}".format(err)) #except EAGAIN as err: # print("EAGAIN error: {0}".format(err)) else: pycom.rgbled(0x7f0000) #red try: print("I am sleeping") time.sleep(self.slot) del clock clock = TimerL(self.listeningTime,2) isListening=True except OSError as err: print("OS error: {0}".format(err)) #except EAGAIN as err: # print("EAGAIN error: {0}".format(err)) def Random(self): result = ((uos.urandom(1)[0] / 256 )*3)+2 return result def change_frequency(self,frequency_d): current_frequency=self.lora.frequency() if current_frequency != frequency_d: print("FREQUENCY WAS CHANGED FROM :"+str(current_frequency)+" TO= ") if frequency_d == 1: self.lora.frequency(868000000) print("868000000") if frequency_d == 2: self.lora.frequency(868100000) print("868100000") if frequency_d == 3: self.lora.frequency(868300000) print("868300000") if frequency_d == 4: self.lora.frequency(868500000) print("868500000") if frequency_d == 5: self.lora.frequency(864100000) print("864100000") if frequency_d == 6: self.lora.frequency(864300000) print("864300000") if frequency_d == 7: self.lora.frequency(864500000) print("864500000") else: print("FREQUENCY ALREADY CHANGED") def change_AND_send_toLW(self, devEUI_custom, data_custom): #print("FONCTION CHANGE TO LW 1") self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) #print("FONCTION CHANGE TO LW 2 "+str(app_eui)+str(app_key)+str(dev_eui)) self.lora.join(activation=LoRa.OTAA, auth=(binascii.unhexlify(devEUI_custom), self.app_eui, self.app_key), timeout=0) #print("FONCTION CHANGE TO LW 3") while not self.lora.has_joined(): print('CtLW : Not yet joined... as '+str(devEUI_custom)) time.sleep(2.5) print('Connected to Objenious LoRaWAN again ! as '+str(devEUI_custom)) self.sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) data=data_custom taille=str(len(data))+'s' databytes = struct.pack(taille, data) self.sock.setblocking(True) self.sock.send(databytes) self.sock.setblocking(False) data="" time.sleep(1.5) def changetoLW(self): #print("FONCTION CHANGE TO LW 1") self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) #print("FONCTION CHANGE TO LW 2 "+str(app_eui)+str(app_key)+str(dev_eui)) self.lora.join(activation=LoRa.OTAA, auth=(self.dev_eui, self.app_eui, self.app_key), timeout=0) #print("FONCTION CHANGE TO LW 3") while not self.lora.has_joined(): print('LGW : Not yet joined...') time.sleep(2.5) print('Connected to Objenious LoRaWAN again !') self.sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) def changetoLoRa(self): self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) print('Radio mode is LoRa now !') time.sleep(5) def send_datatoLWGW(self,dataString): data=dataString taille=str(len(data))+'s' databytes = struct.pack(taille, data) self.sock.send(databytes) data="" time.sleep(1.500) def pairing_phase(self,msg): #print("PAIRING PHASE WITH "+str(msg.id_src)+" STARTED") self.sock.send('Accept,'+str(2)+','+str(self.frequency)+','+str(self.slot)+','+str(self.id)+','+str(msg.id_src)+','+str(-1)+','+str(self.slot*3)) if msg.id_src in self.idRegistered: print("Added before") else: self.idRegistered.append(msg.id_src) #print("PAIRING PHASE WITH "+str(msg.id_src)+" ENDED") def registering_phase(self,msg): #print("REGISTERING PHASE WITH "+str(msg.id_src)+" STARTED") if msg.id_src in self.idRegistered: self.sock.send('DataReq,'+str(4)+','+str(self.frequency)+','+str(self.slot)+','+str(self.id)+','+str(msg.id_src)+','+str(-1)+','+str(self.slot*3)) if msg.id_src in self.isRegistered: print("Added before") else: self.isRegistered.append(msg.id_src) #print("REGISTERING PHASE WITH "+str(msg.id_src)+" ENDED") def ack_data(self,msg): #print("STANDARD PHASE STARTED") #global slot print("I received data : "+str(msg.data)) self.sock.send('ack,'+str(4)+','+str(self.frequency)+','+str(self.slot)+','+str(id)+','+str(self.msg.id_src)+','+str(-1)+','+str(self.slot*3)) #print("STANDARD PHASE ENDED") def standard(self): print("STANDARD PHASE STARTED") data_sum="" for idDest in self.isRegistered: print(idDest) print('DataReq,'+str(4)+','+str(self.frequency)+','+str(self.slot)+','+str(self.id)+','+str(idDest)+','+str(-1)+','+str(self.slot*3)) self.sock.send('DataReq,'+str(4)+','+str(self.frequency)+','+str(self.slot)+','+str(self.id)+','+str(idDest)+','+str(-1)+','+str(self.slot*3)) dataHarvested = self.sock.recv(128) msgH =messageLoRa() msgH.fillMessage(dataHarvested) rnd=self.Random() print("[FIRST Send] for "+str(idDest)+" Request data in "+str(rnd)) print(dataHarvested) time.sleep(rnd) while msgH.id_src != str(idDest) or msgH.id_dest != str(self.id) or msgH.kind != "5" or msgH.messageName != "DataRes": rnd=self.Random() print("[Try] for "+str(idDest)+" send Request data in "+str(rnd)) time.sleep(rnd) self.sock.send('DataReq,'+str(4)+','+str(self.frequency)+','+str(self.slot)+','+str(self.id)+','+str(idDest)+','+str(-1)+','+str(self.slot*3)) dataHarvested = self.sock.recv(128) msgH =messageLoRa() msgH.fillMessage(dataHarvested) print("msg data =========>"+dataHarvested.decode()) data_sum=data_sum+str(idDest)+","+str(msgH.data)+":" data_sum=data_sum[:-1] print("STANDARD PHASE ENDED") return data_sum def handle_message(self,data): msg =messageLoRa() msg.fillMessage(data) print(data) #time.sleep(5) if msg.kind == "1": self.pairing_phase(msg) else: print(msg.kind ) if msg.kind == "3" and msg.id_dest == str(self.id): self.registering_phase(msg) if msg.kind == "3" and msg.id_dest != str(self.id): if msg.id_src in idRegistered: self.idRegistered.remove(msg.id_src) print("Delete ID:"+str(msg.id_src)+"from the table idRegistered")
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()
Run the code below on the 2 LoPy modules and you will see the word 'Hello' being received on both sides. """ from network import LoRa import socket import machine import time # initialise LoRa in LORA mode # Please pick the region that matches where you are using the device: # Asia = LoRa.AS923 # Australia = LoRa.AU915 # Europe = LoRa.EU868 # United States = LoRa.US915 # more params can also be given, like frequency, tx power and spreading factor lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) # create a raw LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) while True: # send some data s.setblocking(True) s.send('Hello') # get any data received... s.setblocking(False) data = s.recv(64) print(data) # wait a random amount of time
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 get_device_eui(): lora = LoRa(mode=LoRa.LORAWAN) print(ubinascii.hexlify(lora.mac()).upper().decode("utf-8"))
from network import LoRa import binascii lora = LoRa(mode=LoRa.LORAWAN) print(binascii.hexlify(lora.mac()).upper().decode('utf-8'))
if pybytes is not None and pybytes.isconnected(): # try to find Pybytes Token if include in rcv_data token = "" if rcv_data.startswith(PACK_TOCKEN_PREFIX): x = rcv_data.split(PACK_TOCKEN_SEP.encode()) if len(x)>2: token = x[1] rcv_data = rcv_data[len(PACK_TOCKEN_PREFIX) + len(token) + len(PACK_TOCKEN_SEP):] pkt = 'BR %d B from %s (%s), to %s ( %d): %s'%(len(rcv_data), token, rcv_ip, dest_ip, dest_port, str(rcv_data)) pybytes.send_signal(1, pkt) return pycom.heartbeat(False) lora = LoRa(mode=LoRa.LORA, region= LoRa.EU868) lora_mac = int(str(ubinascii.hexlify(lora.mac()))[2:-1], 16) # read config file, or set default values pymesh_config = PymeshConfig.read_config(lora_mac) #initialize Pymesh pymesh = Pymesh(pymesh_config, new_message_cb) # mac = pymesh.mac() # if mac > 10: # pymesh.end_device(True) # elif mac == 5: # pymesh.leader_priority(255) while not pymesh.is_connected():
class LoraCoverage: def __init__(self, host, port, ssid, wpa, log_path): self.host = host self.port = port self.ssid = ssid self.wpa = wpa self.path = log_path self.gps_buffer = None self.log_time = None self.log_file = None self.rxnb = 0 self.loramac = binascii.hexlify(network.LoRa().mac()) # to be refactored self.end = False # Create proper directory for log file self._init_log() # Setup wypy/lopy as a station self.wlan = network.WLAN(mode=network.WLAN.STA) self.wlan.connect(self.ssid, auth=(network.WLAN.WPA2, self.wpa)) while not self.wlan.isconnected(): time.sleep_ms(50) print('Connected to Android WIFI HOTPOST') # Lora socket self.lora = None self.lora_sock = None # TCP socket self.tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.tcp_sock.connect((self.host, self.port)) # Start the TCP thread receiving GPS coordinates #self.id = _thread.start_new_thread(self._tcp_thread, ()) def _init_log(self): # create directory log if not exist try: os.mkdir(self.path) except OSError: pass # Check if string is empty def _isNotBlank(self, myString): return bool(myString and myString.strip()) def _get_log_name(self): #print(self.log_time[:19]) #print(type(ts)) # ts = ts.replace('-', '') # ts = ts.replace('T', '') # ts = ts.replace(':', '') #ts = '1974' #base = self.path + '/acq/' #return base + ts + 'list.csv' return self.path + '/acq.list.csv' def _lora_cb(self, lora): events = lora.events() if (events & LoRa.RX_PACKET_EVENT) and (self.gps_buffer is not None): print(self.log_time) if self.log_file is None: self.log_file = open(self._get_log_name(), 'w') data_rx = self.lora_sock.recv(256) stats = self.lora.stats() # get lora stats (data is tuple) if self._isNotBlank(data_rx): print(self.gps_buffer['time']) # time_stamp = stats[0] # get timestamp value # rssi = stats[1] # snr = stats[2] # sf = stats[3] # # msgData = '' # msgCrc = '' # if len(data_rx) >= 5: # msg_data = data_rx[:-5] # remove the last 5 char data crc # msg_crc = data_rx[-4:] # get the last 4 char # # # Calculate CRC # crc8 = utils.crc(msg_data) # # # Check CRC # crc_ok = True if crc8 == msg_crc.decode('utf-8') else False # # crc_ok = False # # if crc8 == msg_crc.decode('utf-8'): # # crc_ok = True # # # fields_lorastats(LoraStats) # # # form csv row # msg = str(self.rxnb) # msg = msg + ',' + self.loramac.decode('utf8') # msg = msg + ',' + self.gps_buffer['time'] # msg = msg + ',' + str(self.gps_buffer.lat) # msg = msg + ',' + str(self.gps_buffer.lon) # msg = msg + ',' + str(self.gps_buffer.alt) # # msg = msg + ',' + msg_data.decode('utf-8') # msg = msg + ',' + msg_crc.decode('utf-8') # msg = msg + ',' + str(crc8) # msg = msg + ',' + str(crc_ok) # msg = msg + ',' + str(time_stamp) # msg = msg + ',' + str(rssi) # msg = msg + ',' + str(snr) # msg = msg + ',' + str(sf) # # # # calc crc8 row # #crc8row = calc(msg.encode('utf-8')) # crc8row = utils.crc(msg.encode('utf-8')) # # # # add crc8row as last item # msg = msg + ',' + str(crc8row) # # # write csv and terminal # self.log_file.write(msg) # self.log_file.write('\n') # self.log_file.flush() # # print(msg) # show in repl # self.rxnb += 1 def start(self): # Initialize a LoRa sockect self.lora = LoRa(mode=LoRa.LORA) self.lora_sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.lora_sock.setblocking(False) self.tcp_alarm = Timer.Alarm(handler=lambda u: self._tcp_gps(), s=1, periodic=True) self.lora.callback(trigger=LoRa.RX_PACKET_EVENT, handler=self._lora_cb) def stop(self): self.wlan.mode(network.WLAN.AP) self.tcp_sock.close() self.lora.callback(trigger=LoRa.RX_PACKET_EVENT, handler=None) self.lora_sock.close() self.log_file.close() # Need to find a better way to terminate thread self.end = True def _tcp_gps(self): try: # Send request self.tcp_sock.send(b'?SHGPS.LOCATION;\r\n') # Get response rx_data = self.tcp_sock.recv(4096) # Save last gps received self.gps_buffer = json.loads(rx_data.decode('ascii')) if self.log_time is None: #self.log_time = self.gps_buffer['time'] self.log_time = self.gps_buffer['time'] except socket.timeout: pass except OSError as e: if e.errno == errno.EAGAIN: pass else: print( "Error: Android 'ShareGPS' connection status should be 'Listening'" ) except Exception: print("TCP recv Exception")
i2c = I2C(0, I2C.MASTER, baudrate=100000) # Inicia bme280 bme = bme280.BME280(i2c=i2c, address=0x76) # Inicia ssd1306 oled = ssd1306.SSD1306_I2C(128, 64, i2c) # Inicia GPS com = UART(1, pins=(config.TX, config.RX), baudrate=config.BAUDRATE) my_gps = MicropyGPS() DEBUG = config.DEBUG # Initialize LoRa in LORAWAN mode. lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) # create an OTA authentication params dev_eui = config.DEV_EUI app_eui = config.APP_EUI app_key = config.APP_KEY # set the 3 default channels to the same frequency lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) # join a network using OTAA lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0) # create a LoRa socket
class NanoGateway: """ Nano gateway class, set up by default for use with TTN, but can be configured for any other network supporting the Semtech Packet Forwarder. Only required configuration is wifi_ssid and wifi_password which are used for connecting to the Internet. """ def __init__(self, id, frequency, datarate, ssid, password, server, port, ntp_server='pool.ntp.org', ntp_period=3600): self.id = id self.server = server self.port = port self.frequency = frequency self.datarate = datarate self.ssid = ssid self.password = password self.ntp_server = ntp_server self.ntp_period = ntp_period self.server_ip = None self.rxnb = 0 self.rxok = 0 self.rxfw = 0 self.dwnb = 0 self.txnb = 0 self.sf = self._dr_to_sf(self.datarate) self.bw = self._dr_to_bw(self.datarate) self.stat_alarm = None self.pull_alarm = None self.uplink_alarm = None self.wlan = None self.sock = None self.udp_stop = False self.udp_lock = _thread.allocate_lock() self.lora = None self.lora_sock = None self.rtc = machine.RTC() def start(self): """ Starts the LoRaWAN nano gateway. """ self._log('Starting LoRaWAN nano gateway with id: {}', self.id) # setup WiFi as a station and connect self.wlan = WLAN(mode=WLAN.STA) self._connect_to_wifi() # get a time sync self._log('Syncing time with {} ...', self.ntp_server) self.rtc.ntp_sync(self.ntp_server, update_period=self.ntp_period) while not self.rtc.synced(): utime.sleep_ms(50) self._log("RTC NTP sync complete") # get the server IP and create an UDP socket self.server_ip = usocket.getaddrinfo(self.server, self.port)[0][-1] self._log('Opening UDP socket to {} ({}) port {}...', self.server, self.server_ip[0], self.server_ip[1]) self.sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM, usocket.IPPROTO_UDP) self.sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1) self.sock.setblocking(False) # push the first time immediatelly self._push_data(self._make_stat_packet()) # create the alarms self.stat_alarm = Timer.Alarm(handler=lambda t: self._push_data(self._make_stat_packet()), s=60, periodic=True) self.pull_alarm = Timer.Alarm(handler=lambda u: self._pull_data(), s=25, periodic=True) # start the UDP receive thread self.udp_stop = False _thread.start_new_thread(self._udp_thread, ()) # initialize the LoRa radio in LORA mode self._log('Setting up the LoRa radio at {} Mhz using {}', self._freq_to_float(self.frequency), self.datarate) self.lora = LoRa( mode=LoRa.LORA, frequency=self.frequency, bandwidth=self.bw, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True ) # create a raw LoRa socket self.lora_sock = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW) self.lora_sock.setblocking(False) self.lora_tx_done = False self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=self._lora_cb) self._log('LoRaWAN nano gateway online') def stop(self): """ Stops the LoRaWAN nano gateway. """ self._log('Stopping...') # send the LoRa radio to sleep self.lora.callback(trigger=None, handler=None) self.lora.power_mode(LoRa.SLEEP) # stop the NTP sync self.rtc.ntp_sync(None) # cancel all the alarms self.stat_alarm.cancel() self.pull_alarm.cancel() # signal the UDP thread to stop self.udp_stop = True while self.udp_stop: utime.sleep_ms(50) # disable WLAN self.wlan.disconnect() self.wlan.deinit() def _connect_to_wifi(self): self.wlan.connect(self.ssid, auth=(None, self.password)) while not self.wlan.isconnected(): utime.sleep_ms(50) self._log('WiFi connected to: {}', self.ssid) def _dr_to_sf(self, dr): sf = dr[2:4] if sf[1] not in '0123456789': sf = sf[:1] return int(sf) def _dr_to_bw(self, dr): bw = dr[-5:] if bw == 'BW125': return LoRa.BW_125KHZ elif bw == 'BW250': return LoRa.BW_250KHZ else: return LoRa.BW_500KHZ def _sf_bw_to_dr(self, sf, bw): dr = 'SF' + str(sf) if bw == LoRa.BW_125KHZ: return dr + 'BW125' elif bw == LoRa.BW_250KHZ: return dr + 'BW250' else: return dr + 'BW500' def _lora_cb(self, lora): """ LoRa radio events callback handler. """ events = lora.events() if events & LoRa.RX_PACKET_EVENT: self.rxnb += 1 self.rxok += 1 rx_data = self.lora_sock.recv(256) stats = lora.stats() packet = self._make_node_packet(rx_data, self.rtc.now(), stats.rx_timestamp, stats.sfrx, self.bw, stats.rssi, stats.snr) self._push_data(packet) self._log('Received packet: {}', packet) self.rxfw += 1 if events & LoRa.TX_PACKET_EVENT: self.txnb += 1 lora.init( mode=LoRa.LORA, frequency=self.frequency, bandwidth=self.bw, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True ) def _freq_to_float(self, frequency): """ MicroPython has some inprecision when doing large float division. To counter this, this method first does integer division until we reach the decimal breaking point. This doesn't completely elimate the issue in all cases, but it does help for a number of commonly used frequencies. """ divider = 6 while divider > 0 and frequency % 10 == 0: frequency = frequency // 10 divider -= 1 if divider > 0: frequency = frequency / (10 ** divider) return frequency def _make_stat_packet(self): now = self.rtc.now() STAT_PK["stat"]["time"] = "%d-%02d-%02d %02d:%02d:%02d GMT" % (now[0], now[1], now[2], now[3], now[4], now[5]) STAT_PK["stat"]["rxnb"] = self.rxnb STAT_PK["stat"]["rxok"] = self.rxok STAT_PK["stat"]["rxfw"] = self.rxfw STAT_PK["stat"]["dwnb"] = self.dwnb STAT_PK["stat"]["txnb"] = self.txnb return ujson.dumps(STAT_PK) def _make_node_packet(self, rx_data, rx_time, tmst, sf, bw, rssi, snr): RX_PK["rxpk"][0]["time"] = "%d-%02d-%02dT%02d:%02d:%02d.%dZ" % (rx_time[0], rx_time[1], rx_time[2], rx_time[3], rx_time[4], rx_time[5], rx_time[6]) RX_PK["rxpk"][0]["tmst"] = tmst RX_PK["rxpk"][0]["freq"] = self._freq_to_float(self.frequency) RX_PK["rxpk"][0]["datr"] = self._sf_bw_to_dr(sf, bw) RX_PK["rxpk"][0]["rssi"] = rssi RX_PK["rxpk"][0]["lsnr"] = snr RX_PK["rxpk"][0]["data"] = ubinascii.b2a_base64(rx_data)[:-1] RX_PK["rxpk"][0]["size"] = len(rx_data) return ujson.dumps(RX_PK) def _push_data(self, data): token = uos.urandom(2) packet = bytes([PROTOCOL_VERSION]) + token + bytes([PUSH_DATA]) + ubinascii.unhexlify(self.id) + data with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception as ex: self._log('Failed to push uplink packet to server: {}', ex) def _pull_data(self): token = uos.urandom(2) packet = bytes([PROTOCOL_VERSION]) + token + bytes([PULL_DATA]) + ubinascii.unhexlify(self.id) with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception as ex: self._log('Failed to pull downlink packets from server: {}', ex) def _ack_pull_rsp(self, token, error): TX_ACK_PK["txpk_ack"]["error"] = error resp = ujson.dumps(TX_ACK_PK) packet = bytes([PROTOCOL_VERSION]) + token + bytes([PULL_ACK]) + ubinascii.unhexlify(self.id) + resp with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception as ex: self._log('PULL RSP ACK exception: {}', ex) def _send_down_link(self, data, tmst, datarate, frequency): """ Transmits a downlink message over LoRa. """ self.lora.init( mode=LoRa.LORA, frequency=frequency, bandwidth=self._dr_to_bw(datarate), sf=self._dr_to_sf(datarate), preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True ) while utime.ticks_cpu() < tmst: pass self.lora_sock.send(data) self._log( 'Sent downlink packet scheduled on {:.3f}, at {:.3f} Mhz using {}: {}', tmst / 1000000, self._freq_to_float(frequency), datarate, data ) def _udp_thread(self): """ UDP thread, reads data from the server and handles it. """ while not self.udp_stop: try: data, src = self.sock.recvfrom(1024) _token = data[1:3] _type = data[3] if _type == PUSH_ACK: self._log("Push ack") elif _type == PULL_ACK: self._log("Pull ack") elif _type == PULL_RESP: self.dwnb += 1 ack_error = TX_ERR_NONE tx_pk = ujson.loads(data[4:]) tmst = tx_pk["txpk"]["tmst"] t_us = tmst - utime.ticks_cpu() - 15000 if t_us < 0: t_us += 0xFFFFFFFF if t_us < 20000000: self.uplink_alarm = Timer.Alarm( handler=lambda x: self._send_down_link( ubinascii.a2b_base64(tx_pk["txpk"]["data"]), tx_pk["txpk"]["tmst"] - 50, tx_pk["txpk"]["datr"], int(tx_pk["txpk"]["freq"] * 1000) * 1000 ), us=t_us ) else: ack_error = TX_ERR_TOO_LATE self._log('Downlink timestamp error!, t_us: {}', t_us) self._ack_pull_rsp(_token, ack_error) self._log("Pull rsp") except usocket.timeout: pass except OSError as ex: if ex.errno != errno.EAGAIN: self._log('UDP recv OSError Exception: {}', ex) except Exception as ex: self._log('UDP recv Exception: {}', ex) # wait before trying to receive again utime.sleep_ms(UDP_THREAD_CYCLE_MS) # we are to close the socket self.sock.close() self.udp_stop = False self._log('UDP thread stopped') def _log(self, message, *args): """ Outputs a log message to stdout. """ print('[{:>10.3f}] {}'.format( utime.ticks_ms() / 1000, str(message).format(*args) ))
pow_mode = LoRa.ALWAYS_ON # def.: power_mode=LoRa.ALWAYS_ON tx_iq_inv = False # def.: tx_iq=false rx_iq_inv = False # def.: rx_iq=false ada_dr = False # def.: adr=false pub = False # def.: public=true tx_retr = 1 # def.: tx_retries=1 dev_class = LoRa.CLASS_A # def.: device_class=LoRa.CLASS_A ANY_ADDR = b'FFFFFFFFFFFFFFFF' lora = LoRa(mode=LoRa.LORA, frequency=freq, tx_power=tx_pow, bandwidth=band, sf=spreadf, preamble=prea, coding_rate=cod_rate, power_mode=pow_mode, tx_iq=tx_iq_inv, rx_iq=rx_iq_inv, adr=ada_dr, public=pub, tx_retries=tx_retr, device_class=dev_class) # get LoRa MAC address lora_mac = binascii.hexlify(network.LoRa().mac()).decode('utf8') print(lora_mac) # create a raw LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # mr add 27/07
def __process_sigfox_registration(self, activation_token): try: import urequest except: import _urequest as urequest if hasattr(pycom, 'sigfox_info'): if not pycom.sigfox_info(): try: jsigfox = None from network import LoRa data = { "activationToken": activation_token['a'], "wmac": binascii.hexlify(machine.unique_id()).upper(), "smac": binascii.hexlify(LoRa(region=LoRa.EU868).mac()) } print_debug(99, 'sigfox_registration: {}'.format(data)) try: self.__pybytes_sigfox_registration = urequest.post( 'https://api.{}/v2/register-sigfox'.format( constants.__DEFAULT_DOMAIN), json=data, headers={'content-type': 'application/json'}) jsigfox = self.__pybytes_sigfox_registration.json() except: jsigfox = None start_time = time.time() while jsigfox is None and time.time() - start_time < 300: time.sleep(15) try: self.__pybytes_sigfox_registration = urequest.post( 'https://api.{}/v2/register-sigfox'.format( constants.__DEFAULT_DOMAIN), json=data, headers={'content-type': 'application/json'}) print_debug( 2, '/v2/register-sigfox returned response: {}'. format( self.__pybytes_sigfox_registration.text)) jsigfox = self.__pybytes_sigfox_registration.json() except: jsigfox = None if jsigfox is not None: try: self.__pybytes_sigfox_registration.close() except: pass print_debug( 99, 'Sigfox regisgtration response:\n{}'.format( jsigfox)) return pycom.sigfox_info( id=jsigfox.get('sigfoxId'), pac=jsigfox.get('sigfoxPac'), public_key=jsigfox.get('sigfoxPubKey'), private_key=jsigfox.get('sigfoxPrivKey'), force=True) else: try: self.__pybytes_sigfox_registration.close() except: pass return False except Exception as ex: print('Failed to retrieve/program Sigfox credentials!') print_debug(2, ex) return False return True
def __init__(self): self.dev_eui = binascii.unhexlify("**REMOVED**") self.app_eui = binascii.unhexlify("**REMOVED**") self.app_key = binascii.unhexlify("**REMOVED**") self.lora = LoRa(mode=LoRa.LORAWAN)
def _wait_for_connections(self): """ Main loop awaiting connections """ lora = LoRa(mode=LoRa.LORA) s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setblocking(False) _thread.start_new_thread(self.listen_at_all_times, (s,)) while True: gc.collect() print("\n -- Awaiting new connection/request from clients -- ") self.socket.listen(3) conn, addr = self.socket.accept() print('\n -- Recieved connection from ', addr[0], ' with port ', addr[1]) data = conn.recv(1024) string = bytes.decode(data) options = {} split_string = string.split(' ') request_method = split_string[0] print("Method: ", request_method) print("Request body: ", string) for option in string.split('\n'): options[option[:option.find(':')] ] = option[option.find(':')+2:] print('+'*100 + '\n', string) if request_method == 'GET': # Code for when user connects to the WiFi for the first time. i.e. Introductory page. if (options['User-Agent'] not in client_username.keys()) or client_username[options['User-Agent']] == '': client_username[options['User-Agent']] = '' self.send_to_frontend(conn, introductory_text) continue routes = split_string[1].split('/') # Code for when user wants the page for the list of users. i.e. Users page. if routes[1] == 'users': if split_string[1][6:7] == '/': to_user = routes[2] from_user = client_username[options['User-Agent']] if ((from_user + '-' + to_user) not in message_list) or ((to_user + '-' + from_user) not in message_list): message_list[from_user + '-' + to_user] = [] self.send_to_frontend( conn, get_user_message_page(client_username[options['User-Agent']], to_user, {'string': '', 'length': 0})) continue self.send_to_frontend( conn, get_user_message_page(client_username[options['User-Agent']], to_user, generate_from_to_user_message_list( from_user, to_user) )) continue self.send_to_frontend(conn, header + """ <h2>This is users page</h2> <a href="/users"><h3>View of online users</h3></a> %s </center> </body> </html> """ % generate_dynamic_user_list()) continue # Code for when user sees the page. i.e. Message page. if request_method == 'POST': if 'username' in split_string[-1][8:]: client_username[options['User-Agent'] ] = split_string[-1][51:] self.send_to_frontend(conn, user_page_response_content) continue if 'message' in split_string[-1]: from_user = client_username[options['User-Agent']] to_user = split_string[1].split('/')[2] if (from_user + '-' + to_user) in message_list.keys(): s.send(from_user + '-' + to_user + '*' + from_user + ': ' + split_string[-1][50:]) message_list[from_user + '-' + to_user].append(split_string[-1][50:]) else: s.send(to_user + '-' + from_user + '*' + from_user + ': ' + split_string[-1][50:]) message_list[to_user + '-' + from_user].append(split_string[-1][50:]) self.send_to_frontend( conn, get_user_message_page(client_username[options['User-Agent']], to_user, generate_from_to_user_message_list( from_user, to_user) )) continue conn.close()
class NanoGateWay: def __init__(self): self.sock = None self.connected = False self.wlan = WLAN(mode=WLAN.STA) self.riders = {} # dictionary of riders # initialize LoRa as a Gateway (with Tx IQ inversion) self.lora = LoRa(tx_iq=True, rx_iq=False) def connect_to_wlan(self): if not self.wlan.isconnected(): # TODO: change for the correct credentials here (ssid and password) self.wlan.connect(ssid='KCOMIoT', auth=(None, '10noCHOSun'), timeout=7000) while not self.wlan.isconnected(): time.sleep_ms(50) def connect_to_server(self): if self.sock: self.sock.close() self.sock = socket.socket() # TCP try: self.sock.connect((TCP_IP, TCP_PORT)) # TODO self.sock.settimeout(1) self.connected = True except Exception: self.sock.close() # just close the socket and try again later print('Socket connect failed, retrying...') time.sleep_ms(500) def send(self, msg): if self.connected and self.sock: try: self.sock.send(msg) except Exception: self.connected = False self.sock.close() self.sock = None def new_rider(self, name, company, badge, bike, eventid, ridetimestamp): rider = Rider(name, company, badge, bike, eventid, ridetimestamp) self.riders[bike] = rider def recv(self): if self.connected and self.sock: try: data = self.sock.recv(1024) except socket.timeout: return None except socket.error as e: if e.args[0] != EAGAIN: self.connected = False return None return data def run(self): data = self.recv() if data: print(data) parsed_json = json.loads(data.decode('ascii')) print(parsed_json) if parsed_json['RideStatus'] == "started": self.new_rider(parsed_json['RiderName'], parsed_json['Company'], parsed_json['BadgeNumber'], parsed_json['BikeID'],parsed_json['EventID'],parsed_json['RideTimestamp']) # start the race print(str({'id':parsed_json['BikeID'], 'cm': 's'})) packet_tx = json.dumps({'id':parsed_json['BikeID'], 'cm': 's'}) print ("packet_tx = " + packet_tx) self.lora.send(packet_tx, True) lora_d = self.lora.recv() if lora_d: parsed_json = json.loads(lora_d.decode('ascii')) print(parsed_json) # update the rider info (if the rider already exists) bike_id = parsed_json['id'] if bike_id in self.riders: self.riders[bike_id].speed = parsed_json['sp'] self.riders[bike_id].distance = parsed_json['ds'] self.riders[bike_id].crank = parsed_json['cr'] if parsed_json['st'] == 'i' or parsed_json['st'] == 'f': self.riders[bike_id].status = 'finished' elif parsed_json['st'] == 'r': self.riders[bike_id].status = 'counting' else: self.riders[bike_id].status = 'started' # Assemble the TCP packet wheel_count=self.riders[bike_id].crank * 7 json_d = {"RiderName":self.riders[bike_id].name, "Company":self.riders[bike_id].company, "BadgeNumber":self.riders[bike_id].badge, \ "EventID":self.riders[bike_id].eventid, "RideTimestamp":'{:f}'.format(self.riders[bike_id].ridetimestamp), "BikeID":bike_id, \ "RideStatus":self.riders[bike_id].status, "RideInfo":[{"CounterTimestamp": float(time.ticks_ms()), \ "CrankCounter":self.riders[bike_id].crank, "WheelCounter":wheel_count}]} json_str = json.dumps(json_d) print("Outgoing from Gateway: " + str(json_str)) self.send(json_str+"\n") if not self.connected: self.connect_to_wlan() self.connect_to_server()
import socket import ubinascii import binascii import struct import machine import time import uos # Initialise LoRa in LORAWAN mode. # Please pick the region that matches where you are using the device: # Asia = LoRa.AS923 # Australia = LoRa.AU915 # Europe = LoRa.EU868 # United States = LoRa.US915 #lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AU915) lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AU915, adr=True, tx_retries=0, device_class=LoRa.CLASS_A) APP_EUI = '406d23713c2de17a' APP_KEY = 'dae41ee5789b7cc4bdd10a0799df6a7d' # remove default channels for i in range(0, 72): lora.remove_channel(i) # adding the Australian channels print("add channels") for i in range(0, 7): lora.add_channel(i, frequency=915200000 + i * 200000, dr_min=0, dr_max=3) lora.add_channel(65, frequency=917500000, dr_min=4, dr_max=4) # create an OTA authentication params app_eui = binascii.unhexlify(APP_EUI.replace(' ',''))
import urequests gc.collect() from machine import I2C gc.collect() from bh1750 import BH1750 gc.collect() # Enable automatic garbage collection: gc.enable() """ SETUP FOR WIFI: """ """ SETUP FOR LORA: """ lora = LoRa(mode=LoRa.LORAWAN) # create ABP authentication parameters dev_addr = struct.unpack(">l", binascii.unhexlify(config.DEV_ADDR_kpn))[0] nwk_swkey = binascii.unhexlify(config.NWKS_KEY_kpn) app_swkey = binascii.unhexlify(config.APPS_KEY_kpn) # join a network using ABP (Activation By Personalization) lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey)) print("LoRa active: ", lora.has_joined()) # 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_CONFIRMED, False) """ SETUP FOR SENSORS: """
#sd = SD() #os.mount(sd, '/sd') # start new log file with headers #with open("/sd/log.csv", 'w') as Log_file: # Log_file.write('remote_ID,GPSFix,latitude,longitude,voltage,rssi\n') print("Starting Webserver") routes = WWW_routes() mws = MicroWebSrv(routeHandlers=routes, webPath="/sd") # TCP port 80 and files in /sd gc.collect() mws.Start() # Starts server in a new thread gc.collect() print("Starting Lora") lora = LoRa(mode=LoRa.LORA, region=LoRa.AU915) s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setblocking(False) print('Starting MQTT') mqtt = MQTTClient(my_ID, "io.adafruit.com", user="******", password="******", port=1883) mqtt.set_callback(mqtt_callback) mqtt.connect() mqtt.subscribe(topic="agmatthews/feeds/LORAtest") print("Waiting for data")
def nvram_erase(): lora = LoRa(mode=LoRa.LORAWAN) lora.nvram_erase()
events = lora.events() if events & LoRa.RX_PACKET_EVENT: if lora_socket is not None: frame, port = lora_socket.recvfrom(512) # longuest frame is +-220 print(port, frame) if events & LoRa.TX_PACKET_EVENT: print("tx_time_on_air: {} ms @dr {}", lora.stats().tx_time_on_air, lora.stats().sftx) ''' Main operations: this is sample code for LoRaWAN on EU868 ''' lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868, device_class=LoRa.CLASS_C) # create an OTA authentication params dev_eui = config.app_eui app_key = config.app_key # not used leave empty loraserver.io #nwk_key = binascii.unhexlify('a926e5bb85271f2da0440f2f4200afe3') prepare_channels(lora, 1, LORA_NODE_DR) # join a network using OTAA lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_key), timeout=0, dr=LORA_NODE_DR) # DR is 2 in v1.1rb but 0 worked for ne # wait until the module has joined the network
from network import LoRa import socket import time import pycom lora = LoRa(mode=LoRa.LORAWAN) # create an OTAA authentication parameters app_eui = binascii.unhexlify('00 00 00 00 00 00 00 00'.replace(' ','')) app_key = binascii.unhexlify('11 22 33 44 55 66 77 88 11 22 33 44 55 66 77 88'.replace(' ','')) pycom.heartbeat(False) pycom.rgbled(0xFFFFFF) # 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 while not lora.has_joined(): time.sleep(2.5) print('Not yet joined...') pycom.rgbled(0x000000)
from pysense import Pysense from LIS2HH12 import LIS2HH12 from SI7006A20 import SI7006A20 from LTR329ALS01 import LTR329ALS01 from MPL3115A2 import MPL3115A2, ALTITUDE, PRESSURE import time import pycom from network import LoRa import socket import struct execfile('/flash/homewifi/homewifi.py') # connect to wifi lora = LoRa(mode=LoRa.LORA, frequency=925000000) s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setblocking(False) s.send(b'pysense hello') py = Pysense() mp = MPL3115A2( py, mode=ALTITUDE ) # Returns height in meters. Mode may also be set to PRESSURE, returning a value in Pascals si = SI7006A20(py) lt = LTR329ALS01(py) li = LIS2HH12(py) print('pysense') while True: pycom.rgbled(0x00007f) # blue
def changetoLoRa(self): self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) print('Radio mode is LoRa now !') time.sleep(5)
def __init__(self,bandwidth=0, sf=7, buffersize=64, preamble=8, fichier='img.py',power=14,coding=1,timeout=0.5,maxretry=10): #super(Send, self).__init__() #self.arg = arg #buffersize=64 #taille du buffer de récéption # lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868, bandwidth=LoRa.BW_500KHZ,preamble=5, sf=7)#définition dun truc lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868, bandwidth=bandwidth,preamble=preamble, sf=sf,tx_power=power,coding_rate=coding)#définition dun truc print(lora.stats()) print("bandwidth="+str(bandwidth)+"preamble="+str(preamble)+"sf="+str(sf)+"tx_power="+str(power)+"coding_rate="+str(coding)) print("bandtith"+str(lora.bandwidth())+"preamble"+str(lora.preamble())+"sf"+str(lora.sf())+"tx_power"+str(lora.tx_power())+"coding_rate"+str(lora.coding_rate())) s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)#définition d'un socket réseaux de type lora f = open(fichier, 'rb')#on va ouvrire l'image qui port l'extention .py (pycom n'axepte pas des fichier de format image) s.setblocking(True)#on dit que l'écoute ou l'envoit bloque le socket s.settimeout(timeout) #temps a attendre avant de considérer une trame comme perdu ==> DOIT ETRE BC PLUS COURT ! ! ! ! ! quelque MS #purger les sockete def purge(): s.setblocking(False) purgetemp=s.recv(buffersize) while purgetemp!=b'': purgetemp=s.recv(buffersize) s.setblocking(True) #définition d'une fonction d'aquitement def sendACK(vara): s.settimeout(timeout) i=0 while True: i+=1 s.send(vara) print("ACK Envoit: "+str(vara)) try: retour=s.recv(buffersize) #print("ack Reçus") break except OSError as socket : print("ACK timeout n° ",i) if(i==maxretry): exit("connexion perdu") return retour def sendACKvrf(data, match): while True: mydata=sendACK(data) if(type(match)==bytes): #print("ACKvfr type = bytes") if mydata == match: #print("ACKvfr break") break else: print("ACKvfr attendue : ", match, " type byte reçus", mydata) if(type(match)==str): #print("ACKvfr type = str") if mydata == match.encode() : #print("ACKvfr break") break else: print("ACKvfr attendue : ", match.encode(), " type str reçus", mydata) return True #on va utiliser la trame rentrée est la décomposer est ajouter les numero def AddToIndexToSend(temp): #on va déduire le nombre de valeur a insere dans le tableaux par la longeur /2 car coder sur 2 bite nbcase=int(len(temp)/2) #on parse toute les valeur reçus de la trame for i in range(nbcase):##on déduit le nombre de numero en fonction de la size de trame attention si malformer ! #on verrifie si la valeur existe bien... pointeur=struct.unpack(str(nbcase)+'H',temp)[i] if(len(dataMap) >= pointeur): #on ajoute la case parser a un tableaux principale indexToSend.append(pointeur)# I n'a pas a être la et on e st sensermodifier les h #on affiche la geule de la trame entierre print("trame a renvoiller récéptioner :",indexToSend) #return True #initialisation de la map de donnée dataMap=[] f = open(fichier, 'rb') stringToHash=var=b'' sizefile=os.stat(fichier)[6] #on déduit le type de variable a utiliser en fonction du nombre de trame total if sizefile/(buffersize-1)<256: tVarIndex="B" #a enlever qqd ça marhce stVarIndex="B"+str(buffersize-1) sVarIndex=1 elif sizefile/(buffersize-2) < 65536: tVarIndex="H" stVarIndex="H"+str(buffersize-2) sVarIndex=2 else: tVarIndex="L" stVarIndex="L"+str(buffersize-4) sVarIndex=4 lenDatamap=os.stat(fichier)[6]//(buffersize-sVarIndex)+1 #on génère notre dataMap while True: var=f.read(buffersize-sVarIndex) if (var==b''): break #pour que la fin du fichier soit fill avec des 0 pour un checksum correct ajouter=(buffersize-sVarIndex)-len(var) if ajouter!=0: var+=ajouter*b'\x00' dataMap.append(var) stringToHash+=var if (len(dataMap)!=lenDatamap): print("Erreur taille datamap") print("len(dataMap)",str(len(dataMap))) print("lenDatamap",str(lenDatamap)) #on va hasher datamap m = hashlib.sha256() m.update(stringToHash) # print("array contenant les data maper:") ###initialisation d'un tableaux qui va lister tout les chunk de data #indexToSend[0,1,2,3,4,5,6,7,8,9] indexToSend=[] for number in range(lenDatamap): indexToSend.append(number) #send du nombre de trame print("send demande de communiquation et annonce de ",str(lenDatamap)," trame a envoiller") #on va utiliser le smiller OwO pour taguer qu'on est bien sur une trame qui annonce la longeur #on verrifie que la valeur envoilkler est bien la valleur recus purge() ##verifier si utile ? ##pack('H3s32s' #utiliser un sendACKvrf ?? # sendACK(pack('L3s32s',lenDatamap,b'OwO',m.digest()),str(lenDatamap)) if (str(sendACK(pack('L3s32s',lenDatamap,b'OwO',m.digest())))==str(lenDatamap)): print("Nombre de trame OK") else: print("erreur de trame") print("sucès début de transmition") while len(indexToSend)!=0: chargement=len(indexToSend) for notrame in range(len(indexToSend)): #on map la trame en utilisant un octée pour anoncer le nombre de tram est ensuite 63 suivant pour les data trame=pack(stVarIndex+"s",indexToSend[notrame], dataMap[indexToSend[notrame]])#buffersize = tl ? #j'envoit ma trame s.send(trame) print("envoit trame num: "+str(notrame)+"/"+str(chargement)+" index data: "+ str(indexToSend[notrame]))#,"string pur",dataMap[indexToSend[notrame]]) #on flush la variable qui stoque la précédante session d'index a send indexToSend=[] #on verifi qu'il y a encore des data indextrame=sendACK("STOP") if (indextrame == b'FinTransmition'): break #reception des trame manquante print("detection des trame manquante") while True: #on va décomposer la trame est l'ajouter a la bd AddToIndexToSend(indextrame) indextrame = sendACK("indexOKforNext") #avec un prochaine opti doit plus exister if (indextrame == b'FinTransmition'): break #indextrame=s.recv(buffersize) # s.settimeout(timeout)########### Besoin de désincroniser pour que A ecoute et B parle print("INFO TrameListe reçus",indextrame)# # DEBUGage if (indextrame == b'STOPliste'): print("Attente confirmation du de stop d'envoit trame") sendACKvrf("indexFIN","GO") print("SINKRO") break print("toute numero de chunck a renvoiller recus:") print(indexToSend) print("sortie!")
class NanoGateway: def __init__(self, id, frequency, datarate, ssid, password, server, port, ntp='pool.ntp.org', ntp_period=3600): self.id = id self.frequency = frequency self.datarate = datarate self.sf = self._dr_to_sf(datarate) self.ssid = ssid self.password = password self.server = server self.port = port self.ntp = ntp self.ntp_period = ntp_period self.rxnb = 0 self.rxok = 0 self.rxfw = 0 self.dwnb = 0 self.txnb = 0 self.stat_alarm = None self.pull_alarm = None self.uplink_alarm = None self.udp_lock = _thread.allocate_lock() self.lora = None self.lora_sock = None def start(self): # Change WiFi to STA mode and connect self.wlan = WLAN(mode=WLAN.STA) self._connect_to_wifi() # Get a time Sync self.rtc = machine.RTC() self.rtc.ntp_sync(self.ntp, update_period=self.ntp_period) # Get the server IP and create an UDP socket self.server_ip = socket.getaddrinfo(self.server, self.port)[0][-1] self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.setblocking(False) # Push the first time immediatelly self._push_data(self._make_stat_packet()) # Create the alarms self.stat_alarm = Timer.Alarm(handler=lambda t: self._push_data(self._make_stat_packet()), s=60, periodic=True) self.pull_alarm = Timer.Alarm(handler=lambda u: self._pull_data(), s=25, periodic=True) # Start the UDP receive thread _thread.start_new_thread(self._udp_thread, ()) # Initialize LoRa in LORA mode self.lora = LoRa(mode=LoRa.LORA, frequency=self.frequency, bandwidth=LoRa.BW_125KHZ, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True) # Create a raw LoRa socket self.lora_sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.lora_sock.setblocking(False) self.lora_tx_done = False self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=self._lora_cb) def stop(self): # TODO: Check how to stop the NTP sync # TODO: Create a cancel method for the alarm # TODO: kill the UDP thread self.sock.close() def _connect_to_wifi(self): self.wlan.connect(self.ssid, auth=(None, self.password)) while not self.wlan.isconnected(): time.sleep(0.5) print("WiFi connected!") def _dr_to_sf(self, dr): sf = dr[2:4] if sf[1] not in '0123456789': sf = sf[:1] return int(sf) def _sf_to_dr(self, sf): return self.datarate def _make_stat_packet(self): now = self.rtc.now() STAT_PK["stat"]["time"] = "%d-%02d-%02d %02d:%02d:%02d GMT" % (now[0], now[1], now[2], now[3], now[4], now[5]) STAT_PK["stat"]["rxnb"] = self.rxnb STAT_PK["stat"]["rxok"] = self.rxok STAT_PK["stat"]["rxfw"] = self.rxfw STAT_PK["stat"]["dwnb"] = self.dwnb STAT_PK["stat"]["txnb"] = self.txnb return json.dumps(STAT_PK) def _make_node_packet(self, rx_data, rx_time, tmst, sf, rssi, snr): RX_PK["rxpk"][0]["time"] = "%d-%02d-%02dT%02d:%02d:%02d.%dZ" % (rx_time[0], rx_time[1], rx_time[2], rx_time[3], rx_time[4], rx_time[5], rx_time[6]) RX_PK["rxpk"][0]["tmst"] = tmst RX_PK["rxpk"][0]["datr"] = self._sf_to_dr(sf) RX_PK["rxpk"][0]["rssi"] = rssi RX_PK["rxpk"][0]["lsnr"] = float(snr) RX_PK["rxpk"][0]["data"] = binascii.b2a_base64(rx_data)[:-1] RX_PK["rxpk"][0]["size"] = len(rx_data) return json.dumps(RX_PK) def _push_data(self, data): token = os.urandom(2) packet = bytes([PROTOCOL_VERSION]) + token + bytes([PUSH_DATA]) + binascii.unhexlify(self.id) + data with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception: print("PUSH exception") def _pull_data(self): token = os.urandom(2) packet = bytes([PROTOCOL_VERSION]) + token + bytes([PULL_DATA]) + binascii.unhexlify(self.id) with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception: print("PULL exception") def _ack_pull_rsp(self, token, error): TX_ACK_PK["txpk_ack"]["error"] = error resp = json.dumps(TX_ACK_PK) packet = bytes([PROTOCOL_VERSION]) + token + bytes([PULL_ACK]) + binascii.unhexlify(self.id) + resp with self.udp_lock: try: self.sock.sendto(packet, self.server_ip) except Exception: print("PULL RSP ACK exception") def _lora_cb(self, lora): events = lora.events() if events & LoRa.RX_PACKET_EVENT: self.rxnb += 1 self.rxok += 1 rx_data = self.lora_sock.recv(256) stats = lora.stats() #self._push_data(self._make_node_packet(rx_data, self.rtc.now(), stats.rx_timestamp, stats.sfrx, stats.rssi, stats.snr)) # Fix the "not joined yet" issue: https://forum.pycom.io/topic/1330/lopy-lorawan-gateway-with-an-st-lorawan-device/2 self._push_data(self._make_node_packet(rx_data, self.rtc.now(), time.ticks_us(), stats.sfrx, stats.rssi, stats.snr)) self.rxfw += 1 if events & LoRa.TX_PACKET_EVENT: self.txnb += 1 lora.init(mode=LoRa.LORA, frequency=self.frequency, bandwidth=LoRa.BW_125KHZ, sf=self.sf, preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True) def _send_down_link(self, data, tmst, datarate, frequency): self.lora.init(mode=LoRa.LORA, frequency=frequency, bandwidth=LoRa.BW_125KHZ, sf=self._dr_to_sf(datarate), preamble=8, coding_rate=LoRa.CODING_4_5, tx_iq=True) while time.ticks_us() < tmst: pass self.lora_sock.send(data) def _udp_thread(self): while True: try: data, src = self.sock.recvfrom(1024) _token = data[1:3] _type = data[3] if _type == PUSH_ACK: print("Push ack") elif _type == PULL_ACK: print("Pull ack") elif _type == PULL_RESP: self.dwnb += 1 ack_error = TX_ERR_NONE tx_pk = json.loads(data[4:]) tmst = tx_pk["txpk"]["tmst"] t_us = tmst - time.ticks_us() - 5000 if t_us < 0: t_us += 0xFFFFFFFF if t_us < 20000000: self.uplink_alarm = Timer.Alarm(handler=lambda x: self._send_down_link(binascii.a2b_base64(tx_pk["txpk"]["data"]), tx_pk["txpk"]["tmst"] - 10, tx_pk["txpk"]["datr"], int(tx_pk["txpk"]["freq"] * 1000000)), us=t_us) else: ack_error = TX_ERR_TOO_LATE print("Downlink timestamp error!, t_us:", t_us) self._ack_pull_rsp(_token, ack_error) print("Pull rsp") except socket.timeout: pass except OSError as e: if e.errno == errno.EAGAIN: pass else: print("UDP recv OSError Exception") except Exception: print("UDP recv Exception") # Wait before trying to receive again time.sleep(0.025)
from network import LoRa import socket import machine import time lora = LoRa(mode=LORA, frequency=863000000) s.socket
def main(): start_delay_ms = 0 time_ms = time.ticks_ms() last_sent_ms = time_ms state = 'IDLE' # States are: 'IDLE', 'RUNNING', 'FINISHED' Pin('G4', mode=Pin.IN, pull=Pin.PULL_DOWN) crank = PulseCounter('G5', Pin.PULL_DOWN, Pin.IRQ_RISING, 250) # initialize LoRa as a node (with Rx IQ inversion) lora = LoRa(tx_iq=False, rx_iq=True) # LCD pin configuration: lcd_rs = 'G11' lcd_en = 'G12' lcd_d4 = 'G15' lcd_d5 = 'G16' lcd_d6 = 'G13' lcd_d7 = 'G28' lcd_columns = 16 lcd_rows = 1 lcd = LCD.CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, lcd_rows) rider = Rider(lcd) print("Ready for first rider.") lcd.clear() lcd.message("Ready fo\nr first rider.") while True: if state == 'IDLE': packet_rx = lora.recv() if packet_rx: try: parsed_json = json.loads(packet_rx.decode('ascii')) cmd = parsed_json['cm'] id = parsed_json['id'] if cmd == 's' and id == config.id: print('Going to running state') start_delay_ms = ((machine.rng() % 30) * 100) + time.ticks_ms() # send 's' (started) state over LoRa packet_tx = json.dumps({'id': config.id, 'cr':0, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'s'}) lora.send(packet_tx, True) rider.countdown() crank.counter = 0 # change to the running state and notify the gateway state = 'RUNNING' packet_tx = json.dumps({'id': config.id, 'cr':0, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'r'}) lora.send(packet_tx, True) except Exception: print('Corrupted LoRa packet') else: time.sleep_ms(50) elif state == 'RUNNING': if rider.ride(crank): print('Going to finished state') state = 'FINISHED' packet_tx = json.dumps({'id': config.id, 'cr':crank.counter, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'f'}) lora.send(packet_tx, True) time_ms = time.ticks_ms() if time_ms < start_delay_ms: pass elif time_ms > last_sent_ms + LORA_SEND_PERIOD_MS: last_sent_ms = time_ms packet_tx = json.dumps({'id':config.id, 'cr':crank.counter, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'r'}) print(packet_tx + ' {}'.format(last_sent_ms)) lora.send(packet_tx, True) else: print('attempt to receive lora') packet_rx = lora.recv() if packet_rx: print(packet_rx) try: # I've seen this failing sometimes parsed_json = json.loads(packet_rx.decode('ascii')) # check the packet received and process the commands except Exception: print('Corrupted LoRa packet') time.sleep(1.0 - (((time.ticks_ms() / 1000) - rider.starttime) % 1.0)) else: print('finishing ride') rider.finish() # change to the running state and notify the gateway state = 'IDLE' packet_tx = json.dumps({'id': config.id, 'cr':crank.counter, 'ds':int(rider.distance()), 'sp':int(rider.avg_speed()), 'st':'i'}) lora.send(packet_tx, True) crank.counter = 0
""" OTAA Node example compatible with the LoPy Nano Gateway """ from network import LoRa import socket import binascii import struct import time # Initialize LoRa in LORAWAN mode. lora = LoRa(mode=LoRa.LORAWAN) # create an OTA authentication params dev_eui = binascii.unhexlify('007FFD9B1D113123'.replace(' ','')) app_eui = binascii.unhexlify('70B3D57EF0005B3B'.replace(' ','')) app_key = binascii.unhexlify('950942111D56A3812CAE94A0DD5048D9'.replace(' ','')) # set the 3 default channels to the same frequency (must be before sending the OTAA join request) lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) # join a network using OTAA lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0) # wait until the module has joined the network while not lora.has_joined(): time.sleep(2.5) print('Not joined yet...') # remove all the non-default channels for i in range(3, 16):
self.idRegistered.remove(msg.id_src) print("Delete ID:"+str(msg.id_src)+"from the table idRegistered") class TimerL: def __init__(self,timing,kind): global isListening self.seconds = 0 if kind == 1: self.__alarm = Timer.Alarm(self._first_handler, timing, periodic=True) else: self.__alarm = Timer.Alarm(self._seconds_handler, timing, periodic=True) def _first_handler(self, alarm): global isListening alarm.cancel() # stop it isListening=True def _seconds_handler(self, alarm): global isListening alarm.cancel() # stop it isListening=False lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) app_eui = '70 B3 D5 7E F0 00 49 E1'.replace(' ','') app_key = '30 4C 99 26 3E A5 E6 43 B5 A0 8C B3 25 4A 61 FA'.replace(' ','') dev_eui = binascii.hexlify(lora.mac()).decode('ascii').upper() del lora #del lora #print(app_eui) #print(app_key) #print(dev_eui) test= LGW(app_eui,app_key,dev_eui,36,1.0,20) test.start()
class Loramesh: """ Class for using Lora Mesh - openThread """ STATE_DISABLED = const(0) STATE_DETACHED = const(1) STATE_CHILD = const(2) STATE_ROUTER = const(3) STATE_LEADER = const(4) STATE_LEADER_SINGLE = const(5) # rgb LED color for each state: disabled, detached, child, router, leader and single leader #RGBLED = [0x0A0000, 0x0A0000, 0x0A0A0A, 0x000A00, 0x00000A, 0x0A000A] RGBLED = [0x0A0000, 0x0A0000, 0x0A0A0A, 0x000A00, 0x0A000A, 0x000A0A] # TTN conf mode #RGBLED = [0x200505, 0x200505, 0x202020, 0x052005, 0x200020, 0x001818] # for outside/bright sun #RGBLED = [0xFF0000, 0xFF0000, 0x808080, 0x00FF00, 0x0000FF, 0xFF00FF] # mesh node state string STATE_STRING_LIST = ['Disabled', 'Detached', 'Child', 'Router', 'Leader'] # address to be used for multicasting MULTICAST_MESH_ALL = 'ff03::1' MULTICAST_MESH_FTD = 'ff03::2' MULTICAST_LINK_ALL = 'ff02::1' MULTICAST_LINK_FTD = 'ff02::2' # Leader has an unicast IPv6: fdde:ad00:beef:0:0:ff:fe00:fc00 LEADER_DEFAULT_RLOC = 'fc00' def __init__(self, config): """ Constructor """ self.config_lora = config.get('LoRa') self._lora_init() # get Lora MAC address #self.MAC = str(ubinascii.hexlify(lora.mac()))[2:-1] self.MAC = int(str(ubinascii.hexlify(self.lora.mac()))[2:-1], 16) #last 2 letters from MAC, as integer self.mac_short = self.MAC & 0xFFFF #int(self.MAC[-4:], 16) print_debug( 5, "LoRa MAC: %s, short: %s" % (hex(self.MAC), self.mac_short)) self.rloc16 = 0 self.rloc = '' self.net_addr = '' self.ip_eid = '' self.ip_link = '' self.state = STATE_DISABLED # a dictionary with all direct neighbors # key is MAC for each neighbor # value is pair (age, mac, rloc16, role, rssi) #self.neigh_dict = {} self.router_data = RouterData() self.router_data.mac = self.MAC # a dictionary with all routers direct neighbors # key is MAC for each router # value is pair (age, rloc, neigh_num, (age, mac, rloc16, role, rssi)) #self.leader_dict = {} self.leader_data = LeaderData() self.leader_data.mac = self.MAC # set of all MACS from whole current Mesh Network self.macs = set() self.macs_ts = -65535 # very old # list of all pairs (direct radio connections) inside Mesh self.connections = list() self.connections_ts = -65535 # very old # set a new unicast address self._add_ipv6_unicast() def _lora_init(self): self.lora = LoRa(mode=LoRa.LORA, region=self.config_lora.get("region"), frequency=self.config_lora.get("freq"), bandwidth=self.config_lora.get("bandwidth"), sf=self.config_lora.get("sf")) self.mesh = self.lora.Mesh() #start Mesh def pause(self): self.mesh.deinit() def resume(self): self._lora_init() self._add_ipv6_unicast() def ip_mac_unique(self, mac): ip = self.unique_ip_prefix + hex(mac & 0xFFFF)[2:] return ip def _add_ipv6_unicast(self): self.unique_ip_prefix = "fdde:ad00:beef:0::" command = "ipaddr add " + self.ip_mac_unique(self.mac_short) self.mesh.cli(command) def update_internals(self): self._state_update() self._rloc16_update() self._update_ips() self._rloc_ip_net_addr() def _rloc16_update(self): self.rloc16 = self.mesh.rloc() return self.rloc16 def _update_ips(self): """ Updates all the unicast IPv6 of the Thread interface """ ips = self.mesh.ipaddr() for line in ips: if line.startswith('fd'): # Mesh-Local unicast IPv6 try: addr = int(line.split(':')[-1], 16) except Exception: continue if addr == self.rloc16: # found RLOC # RLOC IPv6 has x:x:x:x:0:ff:fe00:RLOC16 self.rloc = line elif ':0:ff:fe00:' not in line: # found Mesh-Local EID self.ip_eid = line elif line.startswith('fe80'): # Link-Local self.ip_link = line def is_connected(self): """ Returns true if it is connected if its Child, Router or Leader """ connected = False if self.state in (STATE_CHILD, STATE_ROUTER, STATE_LEADER, STATE_LEADER_SINGLE): connected = True return connected def _state_update(self): """ Returns the Thread role """ self.state = self.mesh.state() if self.state < 0: self.state = self.STATE_DISABLED return self.state def _rloc_ip_net_addr(self): """ returns the family part of RLOC IPv6, without last word (2B) """ self.net_addr = ':'.join(self.rloc.split(':')[:-1]) + ':' return self.net_addr def state_string(self): if self.state >= len(self.STATE_STRING_LIST): return 'none' return self.STATE_STRING_LIST[self.state] def led_state(self): """ Sets the LED according to the Thread role """ if self.state == STATE_LEADER and self.mesh.single(): pycom.rgbled(self.RGBLED[self.STATE_LEADER_SINGLE]) else: pycom.rgbled(self.RGBLED[self.state]) def ip(self): """ Returns the IPv6 RLOC """ return self.rloc # def parent_ip(self): # # DEPRECATED, unused # """ Returns the IP of the parent, if it's child node """ # ip = None # state = self.state # if state == STATE_CHILD or state == STATE_ROUTER: # try: # ip_words = self.rloc.split(':') # parent_rloc = int(self.lora.cli('parent').split('\r\n')[1].split(' ')[1], 16) # ip_words[-1] = hex(parent_rloc)[2:] # ip = ':'.join(ip_words) # except Exception: # pass # return ip # def neighbors_ip(self): # # DEPRECATED, unused # """ Returns a list with IP of the neighbors (children, parent, other routers) """ # state = self.state # neigh = [] # if state == STATE_ROUTER or state == STATE_LEADER: # ip_words = self.rloc.split(':') # # obtain RLOC16 neighbors # neighbors = self.lora.cli('neighbor list').split(' ') # for rloc in neighbors: # if len(rloc) == 0: # continue # try: # ip_words[-1] = str(rloc[2:]) # nei_ip = ':'.join(ip_words) # neigh.append(nei_ip) # except Exception: # pass # elif state == STATE_CHILD: # neigh.append(self.parent_ip()) # return neigh # def cli(self, command): # """ Simple wrapper for OpenThread CLI """ # return self.mesh.cli(command) def ipaddr(self): """ returns all unicast IPv6 addr """ return self.mesh.ipaddr() # def ping(self, ip): # """ Returns ping return time, to an IP """ # res = self.cli('ping ' + str(ip)) # """ # '8 bytes from fdde:ad00:beef:0:0:ff:fe00:e000: icmp_seq=2 hlim=64 time=236ms\r\n' # 'Error 6: Parse\r\n' # no answer # """ # ret_time = -1 # try: # ret_time = int(res.split('time=')[1].split('ms')[0]) # except Exception: # pass # return ret_time def blink(self, num=3, period=.5, color=None): """ LED blink """ if color is None: color = self.RGBLED[self.state] for _ in range(num): pycom.rgbled(0) time.sleep(period) pycom.rgbled(color) time.sleep(period) self.led_state() def neighbors_update(self): """ update neigh_dict from cli:'neighbor table' """ """ >>> print(lora.cli("neighbor table")) | Role | RLOC16 | Age | Avg RSSI | Last RSSI |R|S|D|N| Extended MAC | +------+--------+-----+----------+-----------+-+-+-+-+------------------+ | C | 0x2801 | 219 | 0 | 0 |1|1|1|1| 0000000000000005 | | R | 0x7400 | 9 | 0 | 0 |1|0|1|1| 0000000000000002 | """ x = self.mesh.neighbors() print_debug(3, "Neighbors Table: %s" % x) if x is None: # bad read, just keep previous neigbors return # clear all pre-existing neigbors self.router_data = RouterData() self.router_data.mac = self.MAC self.router_data.rloc16 = self.rloc16 self.router_data.role = self.state self.router_data.ts = time.time() self.router_data.coord = Gps.get_location() for nei_rec in x: # nei_rec = (role=3, rloc16=10240, rssi=0, age=28, mac=5) age = nei_rec.age if age > 300: continue # shouln't add neighbors too old role = nei_rec.role rloc16 = nei_rec.rloc16 # maybe we shouldn't add Leader (because this info is already available at Leader) # if rloc16 == self.leader_rloc(): # continue rssi = nei_rec.rssi mac = nei_rec.mac neighbor = NeighborData(( mac, age, rloc16, role, rssi, )) self.router_data.add_neighbor(neighbor) #print("new Neighbor: %s"%(neighbor.to_string())) #except: # pass # add own info in dict #self.neigh_dict[self.MAC] = (0, self.rloc16, self.state, 0) print_debug(3, "Neighbors: %s" % (self.router_data.to_string())) return def leader_add_own_neigh(self): """ leader adds its own neighbors in leader_dict """ self.leader_data.add_router(self.router_data) return def neighbors_pack(self): """ packs in a struct all neighbors as (MAC, RLOC16, Role, rssi, age) """ data = self.router_data.pack() return data def routers_neigh_update(self, data_pack): """ unpacks the PACK_ROUTER_NEIGHBORS, adding them in leader_dict """ # key is MAC for each router # value is pair (age, rloc, neigh_num, (age, mac, rloc16, role, rssi)) router = RouterData(data_pack) self.leader_data.add_router(router) return def leader_dict_cleanup(self): """ cleanup the leader_dict for old entries """ #print("Leader Data before cleanup: %s"%self.leader_data.to_string()) self.leader_data.cleanup() print("Leader Data : %s" % self.leader_data.to_string()) def routers_rloc_list(self, age_min, resolve_mac=None): """ return list of all routers IPv6 RLOC16 if mac parameter is present, then returns just the RLOC16 of that mac, if found """ mac_ip = None data = self.mesh.routers() print("Routers Table: ", data) '''>>> print(lora.cli('router table')) | ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC | +----+--------+----------+-----------+-------+--------+-----+------------------+ | 12 | 0x3000 | 63 | 0 | 0 | 0 | 0 | 0000000000000002 |''' if data is None: # bad read return () net_addr = self.net_addr routers_list = [] for line in data: # line = (mac=123456, rloc16=20480, id=20, path_cost=0, age=7) age = line.age if age > 300: continue # shouldn't add/resolve very old Routers rloc16 = line.rloc16 # check if it's own rloc16 if rloc16 == self.rloc16: continue if resolve_mac is not None: if resolve_mac == line.mac: mac_ip = rloc16 break # look for this router in Leader Data # if doesn't exist, add it to routers_list with max ts # if it exists, just add it with its ts last_ts = self.leader_data.get_mac_ts(line.mac) if time.time() - last_ts < age_min: continue # shouldn't add/resolve very "recent" Routers ipv6 = net_addr + hex(rloc16)[2:] routers_list.append((last_ts, ipv6)) if resolve_mac is not None: print("Mac found in Router %s" % str(mac_ip)) return mac_ip # sort the list in the ascending values of timestamp routers_list.sort() print("Routers list %s" % str(routers_list)) return routers_list def leader_data_pack(self): """ creates packet with all Leader data, leader_dict """ self.leader_data.rloc16 = self.rloc16 data = self.leader_data.pack() return data def leader_data_unpack(self, data): self.leader_data = LeaderData(data) print("Leader Data : %s" % self.leader_data.to_string()) return self.leader_data.ok def neighbor_resolve_mac(self, mac): mac_ip = self.router_data.resolve_mac(mac) return mac_ip def resolve_mac_from_leader_data(self, mac): mac_ip = self.leader_data.resolve_mac(mac) print("Mac %x found as IP %s" % (mac, str(mac_ip))) return mac_ip def macs_get(self): """ returns the set of the macs, hopefully it was received from Leader """ #print("Macs: %s"%(str(self.macs))) return (self.macs, self.macs_ts) def macs_set(self, data): MACS_FMT = '!H' field_size = calcsize(MACS_FMT) #print("Macs pack: %s"%(str(data))) n, = unpack(MACS_FMT, data) #print("Macs pack(%d): %s"%(n, str(data))) index = field_size self.macs = set() for _ in range(n): mac, = unpack(MACS_FMT, data[index:]) self.macs.add(mac) #print("Macs %d, %d: %s"%(index, mac, str(self.macs))) index = index + field_size self.macs_ts = time.time() pass def connections_get(self): """ returns the list of all connections inside Mesh, hopefully it was received from Leader """ return (self.connections, self.connections_ts) def connections_set(self, data): CONNECTIONS_FMT = '!HHb' field_size = calcsize(CONNECTIONS_FMT) n, = unpack('!H', data) index = calcsize('!H') self.connections = list() for _ in range(n): #(mac1, mac2, rssi) record = unpack(CONNECTIONS_FMT, data[index:]) self.connections.append(record) index = index + field_size self.connections_ts = time.time() pass def node_info_get(self, mac): """ returns the RouterData or NeighborData for the specified mac """ #try to find it as router or a neighbor of a router node, role = self.leader_data.node_info_mac(mac) if node is None: return {} # try to create dict for RPC answer data = {} data['ip'] = node.rloc16 data['r'] = node.role if role is self.STATE_CHILD: data['a'] = node.age elif role is self.STATE_ROUTER: data['a'] = time.time() - node.ts data['l'] = {'lat': node.coord[0], 'lng': node.coord[1]} data['nn'] = node.neigh_num() nei_macs = node.get_macs_set() data['nei'] = list() for nei_mac in nei_macs: nei = node.dict[nei_mac] data['nei'].append( (nei.mac, nei.rloc16, nei.role, nei.rssi, nei.age)) return data def node_info_set(self, data): (role, ) = unpack('!B', data) if role is self.STATE_ROUTER: router = RouterData(data[1:]) self.leader_data.add_router(router) print("Added as router %s" % router.to_string()) elif role is self.STATE_CHILD: node = NeighborData(data[1:]) router = RouterData(node) self.leader_data.add_router(router) print("Added as Router-Neigh %s" % router.to_string()) pass
# ----------------------------- loramacrx.py # check if string is empty def isNotBlank (myString): return bool(myString and myString.strip()) # ================================================ # Start program # # get the 6-byte unique id of the board (pycom MAC address) # get loramac loramac = binascii.hexlify(network.LoRa().mac()) # initialize LoRa in LORA mode # more params can also be given, like frequency, tx power and spreading factor lora = LoRa(mode=LoRa.LORA) # create a raw LoRa socket nMsgTx = 1 tStartMsec = time.ticks_ms() LoraStats = "" # get lora stats # ----------------------------- tstgps5.py # expansion board user led user_led = Pin("G16", mode=Pin.OUT) # expansion board button button = Pin("G17", mode=Pin.IN, pull=Pin.PULL_UP) pycom.heartbeat(False) pycom.rgbled(0x007f00) # green
def __init__(self): self.dev_eui = binascii.unhexlify("000000000000022d") self.app_eui = binascii.unhexlify("00000000000000b3") self.app_key = binascii.unhexlify("7a5a6e506f6e54495357705532737364") self.lora = LoRa(mode=LoRa.LORAWAN)
def getDeviceEUI(): lora = LoRa(mode=LoRa.LORAWAN) result = binascii.hexlify(lora.mac()).upper().decode('utf-8') print(result) return result
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( '70B3D57ED0019255') # these settings can be found from TTN #app_eui = ubinascii.unhexlify('70B3D57ED001C55E') dev_eui = ubinascii.unhexlify( '0058A97F44896904') # these settings can be found from TTN #dev_eui = ubinascii.unhexlify('006D2D7767E7BAFE') # these settings can be found from TTN app_key = ubinascii.unhexlify('AEAFACB81C594C7B7BE3466241CD38EF' ) # 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 self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) # make the socket non-blocking self.s.setblocking(False) self.lora.nvram_save() 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 change_txpower(self, power): self.lora.tx_power(power) 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) #lora=self.lora 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) self.s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, False) def EnviarGateway(self, data): self.s.bind(3) self.s.send(data) time.sleep(10) 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) misg_crc = misg + " " + str(self.calculate_crc(misg)) msg = iv + cipher.encrypt(misg_crc) self.s.send(msg) self.s.setblocking(False) def reciveData(self, f, rtc): 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: crc_OK, msg = self.check_crc(original) if crc_OK: if "Hay" not in msg: f = open('/sd/msgReceived_first.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 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 ApplyFormat_NeighboursTable(self, table, count): msg = b'' for i in range(len(table[0])): packet_power = ustruct.pack('b', int(table[1][i])) #signed char 1 byte packet_id = ustruct.pack('>Q', int(table[0][i], 16)) #long long: 8 bytes msg = msg + packet_id + packet_power #id=splitmsg[1].encode('utf-8') #id_aux=ustruct.pack('>Q',int(splitmsg[1],16)) #long long: 8 bytes msg = msg + ustruct.pack('H', count) return (msg) def neighbours_min(self, id, 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) if (crc_new != crc_rcv): print(crc_new, crc_rcv, splitmsg) return (crc_new == crc_rcv, aux)
from lib.Wifi import * from lib.Servidor import * from loramesh import Loramesh from Networkmesh import * pycom.wifi_on_boot(False) pycom.heartbeat(False) #wifi = Wifi("HITRON-92B0","pepe4444") #wifi = Wifi("IDEI","lagoenelcielo") #wifi.connect() lora = LoRa(mode=LoRa.LORA, region=LoRa.US915, tx_power=20,bandwidth=LoRa.BW_125KHZ, sf=12) #lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868,frequency = 863000000, bandwidth=LoRa.BW_125KHZ, sf=11) #lora = LoRa(mode=LoRa.LORA, region=LoRa.US915,frequency=903000000,tx_power=19, bandwidth=LoRa.BW_125KHZ, sf=12) MAC = str(ubinascii.hexlify(lora.mac()))[2:-1] print("LoRa MAC: %s"%MAC) #server = Servidor("0.0.0.0",10000) loram = Loramesh(lora) mesh= NetworkMesh(loram,MAC,1) #-------------------------------------------------------------------------------- # waiting until it connected to Mesh network # se queda intentando conectarse y muestra los vecinos mesh.connect() # create UDP socket
print('LoRa Joined') return True else: print('LoRa Not Joined') return False else: return True # Let's see if you inserted the required data if THE_APP_EUI == 'VOID': print("You must set the values of your app and device first!!") sys.exit() # Getting the LoRa MAC lora = LoRa(mode=LoRa.LORAWAN, public=1, adr=0, tx_retries=0) print("Device LoRa MAC:", binascii.hexlify(lora.mac())) # joining TTN join_lora(True) py = Pysense() tempHum = SI7006A20(py) ambientLight = LTR329ALS01(py) while True: # create a LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setsockopt(socket.SOL_LORA, socket.SO_DR, 0) s.setblocking(True)
class LoraCoverage: def __init__(self, host, port, ssid, wpa, log_path): self.host = host self.port = port self.ssid = ssid self.wpa = wpa self.path = log_path self.gps_buffer = None self.log_time = None self.log_file = None self.rxnb = 0 self.loramac = binascii.hexlify(network.LoRa().mac()) # to be refactored self.end = False self.lock = _thread.allocate_lock() # Create proper directory for log file self._init_log() # Setup wypy/lopy as a station self.wlan = network.WLAN(mode=network.WLAN.STA) self.wlan.connect(self.ssid, auth=(network.WLAN.WPA2, self.wpa)) while not self.wlan.isconnected(): print('Connecting to Android WIFI HOTPOST...') time.sleep(1) print('Connected to Android WIFI HOTPOST') # Lora socket self.lora = None self.lora_sock = None # TCP socket self.tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Connect self.tcp_sock.connect((self.host, self.port)) def _init_log(self): # create directory log if not exist try: os.mkdir(self.path) except OSError: pass # Check if string is empty def _isNotBlank (self, myString): return bool(myString and myString.strip()) def _get_log_name(self): #print(self.log_time[:19]) #print(type(ts)) # ts = ts.replace('-', '') # ts = ts.replace('T', '') # ts = ts.replace(':', '') #ts = '1974' #base = self.path + '/acq/' #return base + ts + 'list.csv' return self.path + '/acq.list.csv' def _lora_cb(self, lora): events = lora.events() if (events & LoRa.RX_PACKET_EVENT) and (self.gps_buffer is not None): #if self.log_file is None: # self.log_file = open(self._get_log_name(), 'w') data_rx = self.lora_sock.recv(256) stats = self.lora.stats() # get lora stats (data is tuple) if self._isNotBlank(data_rx): with self.lock: print(self.log_time) print(self.gps_buffer) #print(self.gps_buffer['time']) # time_stamp = stats[0] # get timestamp value # rssi = stats[1] # snr = stats[2] # sf = stats[3] # # msgData = '' # msgCrc = '' # if len(data_rx) >= 5: # msg_data = data_rx[:-5] # remove the last 5 char data crc # msg_crc = data_rx[-4:] # get the last 4 char # # # Calculate CRC # crc8 = utils.crc(msg_data) # # # Check CRC # crc_ok = True if crc8 == msg_crc.decode('utf-8') else False # # crc_ok = False # # if crc8 == msg_crc.decode('utf-8'): # # crc_ok = True # # # fields_lorastats(LoraStats) # # # form csv row # msg = str(self.rxnb) # msg = msg + ',' + self.loramac.decode('utf8') # msg = msg + ',' + self.gps_buffer['time'] # msg = msg + ',' + str(self.gps_buffer.lat) # msg = msg + ',' + str(self.gps_buffer.lon) # msg = msg + ',' + str(self.gps_buffer.alt) # # msg = msg + ',' + msg_data.decode('utf-8') # msg = msg + ',' + msg_crc.decode('utf-8') # msg = msg + ',' + str(crc8) # msg = msg + ',' + str(crc_ok) # msg = msg + ',' + str(time_stamp) # msg = msg + ',' + str(rssi) # msg = msg + ',' + str(snr) # msg = msg + ',' + str(sf) # # # # calc crc8 row # #crc8row = calc(msg.encode('utf-8')) # crc8row = utils.crc(msg.encode('utf-8')) # # # # add crc8row as last item # msg = msg + ',' + str(crc8row) # # # write csv and terminal # self.log_file.write(msg) # self.log_file.write('\n') # self.log_file.flush() # # print(msg) # show in repl # self.rxnb += 1 def start(self): # Initialize a LoRa sockect self.lora = LoRa(mode=LoRa.LORA) self.lora_sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.lora_sock.setblocking(False) #self.tcp_alarm = Timer.Alarm(handler=lambda u: self._tcp_gps(), s=1, periodic=True) self.lora.callback(trigger=LoRa.RX_PACKET_EVENT, handler=self._lora_cb) # Start the TCP thread receiving GPS coordinates _thread.start_new_thread(self._tcp_thread, ()) def stop(self): self.wlan.mode(network.WLAN.AP) self.tcp_sock.close() self.lora.callback(trigger=LoRa.RX_PACKET_EVENT, handler=None) self.lora_sock.close() #self.log_file.close() # Set end flag to terminate TCP thread self.end = True def _tcp_thread(self): while True: if self.end: _thread.exit() try: # Send request self.tcp_sock.send(b'?SHGPS.LOCATION;\r\n') # Get response rx_data = self.tcp_sock.recv(4096) # Release the lock in case of previous TCP error #self.lock.release() # Save last gps received to buffer with self.lock: self.gps_buffer = json.loads(rx_data.decode('ascii')) if not self.log_time: self.log_time = self.gps_buffer['time'] except socket.timeout: self.lock.locked() except OSError as e: if e.errno == errno.EAGAIN: pass else: self.lock.locked() print("Error: Android 'ShareGPS' connection status should be 'Listening'") print('Change mode and soft reboot Pycom device') except Exception: self.lock.locked() print("TCP recv Exception") time.sleep(0.5)
from network import LoRa import socket import binascii import struct import time import config # initialize LoRa in LORAWAN mode. lora = LoRa(mode=LoRa.LORAWAN) # create an ABP authentication params dev_addr = struct.unpack(">l", binascii.unhexlify('26 01 14 7D'.replace(' ','')))[0] nwk_swkey = binascii.unhexlify('3C 74 F4 F4 0C AE A0 21 30 3B C2 42 84 FC F3 AF'.replace(' ','')) app_swkey = binascii.unhexlify('0F FA 70 72 CC 6F F6 9A 10 2A 0F 39 BE B0 88 0F'.replace(' ','')) # remove all the channels for channel in range(0, 72): lora.remove_channel(channel) # set all channels to the same frequency (must be before sending the OTAA join request) for channel in range(0, 72): lora.add_channel(channel, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=3) # join a network using ABP (Activation By Personalization) lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey)) # 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.LORA_NODE_DR)