s.setblocking(False) data = s.recv(64) if (len(data) > 0): pycom.rgbled(0x7f7f7f) try: sData = data.decode("utf-8") sData = sData.split("+") coord = l76.coordinates() rxTime = utime.ticks_ms() if not coord[0] or not coord[1]: pycom.rgbled(0x7f7f00) print("Invalid GNSS pos") print(coord, rxTime, nodeId) txTime = sData[0] txNodeId = sData[1] rssi = lora.stats().rssi snr = lora.stats().snr # to SD card f = open(FILENAME_RX, 'a') f.write(str(coord[0]) + ";" + str(coord[1]) + ";" + str(rxTime) + ";" + str(nodeId) + ";" + str(txTime) +";" + str(txNodeId) + ";" + str(rssi) + ";" + str(snr) + "\n") f.close() except: print("Error parsing packet. Not for us?") pycom.rgbled(0x000000)
fCsv = open(nameCsv, 'w') # --------------------------------- pressed = 0 count = 0 while True: GetGpsPosition("192.168.43.1", 2947) # create a raw LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setblocking(False) # dataRx = s.recv(64) dataRx = s.recv(256) LoraStats = lora.stats() # get lora stats (data is tuple) if isNotBlank (dataRx): timestamp=LoraStats[0] # get timestamp value rssi=LoraStats[1] snr=LoraStats[2] sf=LoraStats[3] msgData="" msgCrc="" if len(dataRx)>=5: msgData = dataRx[:-5] # remove the last 5 char data crc msgCrc = dataRx[-4:] # get the last 4 char # calc crc # crc8 = calc(dataRx)
class Comunication: def __init__(self): self.key = b'encriptaincendis' self.node_list = "" pass # Initialize LoRa in LORAWAN mode. def JoinLoraWan(self): self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) # create an OTA authentication params app_eui = ubinascii.unhexlify('70B3D57ED001C55E') dev_eui = ubinascii.unhexlify( '006D2D7767E7BAFE') # these settings can be found from TTN #app_eui = ubinascii.unhexlify('70B3D57ED0019255') # these settings can be found from TTN app_key = ubinascii.unhexlify('0A05862CEA15FC56C047FC03FBDF34DB' ) # these settings can be found from TTN # set the 3 default channels to the same frequency (must be before sending the OTAA join request) self.lora.add_channel(0, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(1, frequency=868100000, dr_min=0, dr_max=5) self.lora.add_channel(2, frequency=868100000, dr_min=0, dr_max=5) # join a network using OTAA self.lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0) # wait until the module has joined the network while not self.lora.has_joined(): time.sleep(2.5) print('Not joined yet...') # remove all the non-default channels for i in range(3, 16): self.lora.remove_channel(i) # create a LoRa socket self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate. DR5 means 5470 bits/s ans max payload=230 self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) # make the socket non-blocking self.s.setblocking(False) time.sleep(5) def start_LoraRaw(self): self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setblocking(False) #Aquesta instrucció igual sobra time.sleep(5) lora = self.lora #return(lora) def change_txpower(self, power): self.lora.tx_power(power) def savestate(self): self.lora.nvram_save() def Switch_to_LoraRaw(self): self.lora.nvram_save() self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setblocking(False) #Aquesta instrucció igual sobra time.sleep(5) def Switch_to_LoraWan(self): self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) self.lora.nvram_restore() time.sleep(2.5) #Si no es reinicia el socket self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) self.s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, False) def EnviarGateway(self, data): self.s.bind(2) self.s.send(data) time.sleep(10) def sendData(self, msg, rtc, f): if "Hay" not in msg: f = open('msg_sent_final.txt', 'a') f.write("{}/{}/{} {}:{}:{} msg {} stats {}\n".format( rtc.now()[2], rtc.now()[1], rtc.now()[0], rtc.now()[3], rtc.now()[4], rtc.now()[5], msg, self.lora.stats())) f.close() self.s.setblocking(True) iv = crypto.getrandbits( 128) # hardware generated random IV (never reuse it) cipher = AES(self.key, AES.MODE_CFB, iv) misg_crc = msg + " " + str(self.calculate_crc(msg)) msg = iv + cipher.encrypt(misg_crc) self.s.send(msg) #print("missatge amb crc", msg) self.s.setblocking(False) #print(msg) #print(len(msg)) #time.sleep(5) def reciveData(self, rtc, f): self.s.setblocking(False) msg = self.s.recv(128) #Get any data recieved #If there's any data, decrypt if (len(msg) > 0): try: #print("encriptat: ",msg) cipher = AES(self.key, AES.MODE_CFB, msg[:16]) # on the decryption side original = cipher.decrypt(msg[16:]) print("original ", original) if "Config" in original or "stop" in original or "Discover" in original or "Hello" in original or "Info" in original or "Token" in original or "Alarm" in original or "Hay" in original: crc_OK, msg = self.check_crc(original) if crc_OK: if "Hay" not in msg: f = open('msg_received_final.txt', 'a') f.write( "{}/{}/{} {}:{}:{} msg {} stats {}\n".format( rtc.now()[2], rtc.now()[1], rtc.now()[0], rtc.now()[3], rtc.now()[4], rtc.now()[5], msg, self.lora.stats())) f.close() return (msg) else: print("CRC not OK") return ("error") else: return ("error") print("Keyword not in msg") except: return ("error") print("Exception") else: return ("error") print("Empty msg") def update_neighbours(self, pow, id_n, neighbours): if id_n in neighbours[0]: if pow < neighbours[1][neighbours[0].index(id_n)]: neighbours[1][neighbours[0].index(id_n)] = pow else: neighbours[0].append(id_n) neighbours[1].append(pow) #print("I have a friend ") print(neighbours) return neighbours def neighbours_min(self, neighbours, neighbours_aux, id): for id in neighbours[0]: if id in neighbours_aux[0]: neighbours[1][neighbours[0].index(id)] = min( neighbours[1][neighbours[0].index(id)], neighbours_aux[1][neighbours_aux[0].index(id)]) print(neighbours) return (neighbours) def ApplyFormat(self, splitmsg): packet_dust = ustruct.pack('H', int(splitmsg[3])) #Unsigned short 2 bytes packet_tempC = ustruct.pack('H', int(splitmsg[4])) packet_Tht = ustruct.pack('H', int(splitmsg[5])) packet_Hht = ustruct.pack( 'B', round(int(splitmsg[6]) * 100)) #Form 0 to 1 -> 0% to 100% #Unsigned char 1 byte packet_tbmp = ustruct.pack('H', int(splitmsg[7])) packet_val = ustruct.pack('H', int(splitmsg[8])) packet_dhi = ustruct.pack('B', int(splitmsg[9])) #+packet_TCam=ustruct.pack('f',int(splitmsg[10])) #id=splitmsg[1].encode('utf-8') id_aux = ustruct.pack('>Q', int(splitmsg[1], 16)) #long long: 8 bytes return (packet_dust + packet_tempC + packet_Tht + packet_Hht + packet_tbmp + packet_val + packet_dhi + id_aux) #+packet_TCam) def calculate_crc(self, msg): """ Compute CRC """ if type(msg) == bytes: msg = bytes.decode(msg) crc = 0 data = bin(int(binascii.hexlify(msg), 16)) data = str.encode(data) for i in range(len(data)): byte = data[i] for b in range(8): fb_bit = (crc ^ byte) & 0x01 if fb_bit == 0x01: crc = crc ^ 0x18 crc = (crc >> 1) & 0x7f if fb_bit == 0x01: crc = crc | 0x80 byte = byte >> 1 return crc def check_crc(self, msg): """ Check if CRC received is correct """ if type(msg) == bytes: msg = bytes.decode(msg) splitmsg = msg.split() crc_rcv = int(splitmsg[-1]) aux = " ".join(splitmsg[:-1]) #Not including the CRC received crc_new = self.calculate_crc(aux) return (crc_new == crc_rcv, aux) def get_node_list(self, list): self.node_list = list
#f.write("{} - {}\n".format(coord, rtc.now())) # print("{} - {} - {}".format(coord, rtc.now(), gc.mem_free())) #print("{} - {}".format(coord, gc.mem_free())) pkt = bytes([cpt & 0xFF, (cpt >> 8) & 0xFF]) # TODO add coordinates (if PyTrack), LIS2HH12 values for acc print('Sending:', pkt) s.send(pkt) pycom.rgbled(GREEN) time.sleep(0.1) pycom.rgbled(OFF) time.sleep(9) rx, port = s.recvfrom(256) if rx: print('Received: {}, on port: {} ({})'.format( rx, port, lora.stats())) pycom.rgbled(BLUE) time.sleep(1) pycom.rgbled(OFF) # TODO special case for port=224 (set confirmation, ask for LinkCheck, force rejoin) # TODO port=123 (NTP) for setting RTC rtc.init((2017, 2, 28, 10, 30, 0, 0, 0)) # TODO port=?? for setting TX period, Acc threshhold, ... # if port=123, set RTC if port == 123: rtc.init( (rx[0] + 2000, rx[1], rx[2], rx[3], rx[4], rx[5], 0, 0)) print('Set RTC at ', rtc.now()) # if port=200, force to rejoin if port == 200:
with open("/flash/lib/config.json") as f: config = json.loads(f.read()) # create an OTAA authentication parameters app_eui = binascii.unhexlify(config['APP_EUI'].replace(' ','')) app_key = binascii.unhexlify(config['APP_KEY'].replace(' ','')) print("Keys: {} and {}".format(app_eui, app_key)) # 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(): print(lora.stats()) time.sleep(2.5) print('Not yet 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_DR, 5) # make the socket non-blocking s.setblocking(False) # send some data while True: try:
#request = functions.formatRequest(data) # """ try: sock.send(request) except: pass """ csv.CSV.writeData2(conf.MOUNT, str(count) + ".txt", None, [data['battery'], data['temperature_b'], data["pressure"], data["altitude"], data["temperature_t"], data["humidity"], data["dew_point"]]) ### [5] Check for received data pycom.nvs_set('count', count + 1) pycom.rgbled(0x00FF00) #while True: #time.sleep(30) while True: rc = sock.recv(64) if rc == b'012345678': #print(lora.stats()) csv.CSV.writeData2(conf.MOUNT, str(count) + ".txt", None, str(lora.stats())) print(str(lora.stats())) ### [6] Save network data in the NVRAM lora.nvram_save()
update_LED() # Free up memory by garbage collecting gc.collect() # periodically send message via Tracker sendTrackerMsg() # periodically send message via MQTT if use_MQTT and internet_OK: sendMqttMsg() # if we havent had a fix recently then time out the most recent fix if utime.time() - lastFix > FixTimeout: GPSFix = False # if it is time to check for a message then check for it if(utime.time() > last_recv_time + receiveInterval): # get some data from the LoRa buffer databytes = s.recv(256) stats = lora.stats() if len(databytes)>=40: print (' ') print ("Message Received") # record the time of this fix in local seconds last_recv_time = utime.time() theData = {} theData["fix"] = False msgReceived = True msgCount += 1 # check the crc on the recived message if crc16.checkcrc(databytes): # CRC is OK - process message theData = ujson.loads(databytes[6:].decode()) # check GPS data in the recived data if theData["fix"] and theData["lon"]!=0:
auth=original_auth, channel=6, antenna=WLAN.INT_ANT) # import network # server = network.Server() # server.deinit() # disable the server # server.init(login=('user', 'password'), timeout=600 client = MQTTClient("deviceid", "x.x.x.x", user="******", password="******", port=xxxx) client.connect() client.publish(topic="coordoner", msg="lon,lat,rssi,snr") print("lon,lat,rssi,snr") while True: data = s.recv(16) #corriger la taille d'un packet ! try: coordoner = unpack('ff', data) # lont , lat , rssi , snr data = str(coordoner[0]) + "," + str(coordoner[1]) + "," + str( lora.stats()[1]) + "," + str(lora.stats()[2]) print(data) client.publish(topic="coordoner", msg=data) time.sleep(1) except Exception as e: print("exeption:" + str(data))
s.setblocking(False) rcv_data = s.recv(64) if rcv_data: print(i, "rcv_data ",rcv_data) print(i, "len(rcv_data) ",len(rcv_data)) print(i, "type(rcv_data) ",type(rcv_data)) try: rcv_data1=rcv_data.decode("utf-8") except: print("decode on error") rcv_data1="dummy" print(i, "rcv_data1 ",rcv_data) print(i, "len(rcv_data1) ",len(rcv_data)) print(i, "type(rcv_data1) ",type(rcv_data)) s_rssi="rssi: " + str(lora.stats()[1]) s_snr="snr: " + str(lora.stats()[2]) s_freq="f: " + str(lora.stats()[9]/1000000) print(s_rssi, s_snr, s_freq) ##x.PrintStrings(str(i) + " new data:",s_rssi,s_snr,s_freq) if rcv_data1==CMD_ON: print("rcv_data==CMD_ON", rcv_data1 ) solenoid_state="GREEN" s.send(CMD_ON) elif rcv_data1==CMD_OFF: print("rcv_data==CMD_OFF", rcv_data1) solenoid_state="BLUE" s.send(CMD_OFF) else: print("Unknown lora message received: ", rcv_data,rcv_data1, s_rssi, s_snr, s_freq )
lora = LoRa(mode=LoRa.LORA, tx_power=14, sf=9, coding_rate=LoRa.CODING_4_6) sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) #sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) sock.setblocking(False) datas = {} while True: rc = sock.recv(64) if rc.decode().split(",")[0] == 'tx 4-06': print(rc.decode().split(",")) datas["id"] = rc.decode().split(",")[3] datas["lat"] = rc.decode().split(",")[1] datas["lon"] = rc.decode().split(",")[2] datas["rssi"] = lora.stats()[1] print(datas) csv.CSV.writeData2(data=datas) datas = {} # message = b"GW 4-02, " + str(lora.stats()[1]).encode() # print(message) # sock.send(message) # time.sleep(4) # datas["GW1"] = lora.stats()[1] # if rc.decode().split(",")[0]=="GW 4-02" and "GW2" not in datas: # datas["GW2"] = rc.decode().split(",")[1] # if rc.decode().split(",")[0]=="GW 4-10" and "GW3" not in datas: # datas["GW3"] = rc.decode().split(",")[1] # print(datas) # if len(datas)==3: # print(datas)
voltage, percentage = VoltMeter.read(i2c) led.transmit() s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.bind(FORMAT_VERSION + 200) s.setblocking(True) s.send(struct.pack("!HH", int(voltage * 100), int(percentage * 100))) led.success(0.5) lora.nvram_save() machine.deepsleep(int(config.INTERVAL * 1000)) else: led.processing() # TODO Should round before sending - just dropping precision otherwise? result_mean, result_stdev = DBMeter.read(modbus, modbus_psu, config.SAMPLE_PERIOD * 1000) led.transmit() s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.bind(FORMAT_VERSION + 100) s.setblocking(True) s.send(struct.pack("!HH", int(result_mean * 100), int(result_stdev * 100))) led.success(0.5) if lora.stats().tx_counter + 1 < config.RESTART_INTERVAL / (config.INTERVAL + config.SAMPLE_PERIOD + 10): # 10 seconds added for general processing time lora.nvram_save() machine.deepsleep(int(config.INTERVAL * 1000)) else: lora.nvram_erase() machine.reset()
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!")
def __init__(bandwidth=0, sf=7, buffersize=64, preamble=8, fichier='azer.txt', power=14, coding=1, timeout=0.5, maxretry=10): # fichier='azer.txt' # buffersize=64 #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 s = socket.socket( socket.AF_LORA, socket.SOCK_RAW) #définition d'un socket réseaux de type lora 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())) # #ne pouvant avoir une résolution en dessou de la seconde sans passer par des tick ces mort # ltime=int() # def crono(): # global ltime # b=time.time() # out=b-ltime # ltime=b # return out #fonction permetant de vider le buffer qui peut poser des soucis RArement mais ça peut vite être contrégniant dans le cas échéant def purge(): #purger les sockete s.setblocking(False) purgetemp = s.recv(buffersize) while purgetemp != b'': purgetemp = s.recv(buffersize) s.setblocking(True) #declaration startAt = 0 nbtrame = 0 indexManque = [] indexRecieve = [] stVarIndex = "" tVarIndex = "" playloadsize = 0 #autodetect arrayStat = [] def unboxing(rawtram): #on verifie si on peut umpack la trame try: #"H"+str(buffersize-2) unpackted = unpack( stVarIndex + "s", rawtram ) #on stoque la data qui est dans un tuple dans une variable except ValueError: #OSError print("Unboxing: raw: " + str(rawtram)) else: #pour le premier tour on empege une division par zero totaltemp = time.time() - startAt if totaltemp == 0: totaltemp = 1 totaldata = (len(indexRecieve) + 1) * int(playloadsize) # arrayStat.append((unpackted[0], (totaldata/totaltemp), time.time(), gps.coord,lora.stats()[1], lora.stats()[2])) print("Unboxing: chunk " + str(unpackted[0]) + " Download: " + str((len(indexRecieve) + 1) / nbtrame * 100) + "% débit moyen: " + str(totaldata / totaltemp) + "octée/s " + "position: " + str(gps.coord) + " power reçus " + str(lora.stats()[1]) + "dBm, SNR: " + str(lora.stats()[2]) + "dB ", end='') #pour verifier si un packet DOUBLON OU est malformer on verifi que l'index existe bien if unpackted[0] in indexManque: #on vérifie si ces bien une trame de data #try plus nécésaire ? try: #on archive le packet recus indexRecieve.append(unpackted) #caclule en% des trame perdu #####peut être opti print("packet perdu " + str(lostpacket(unpackted[0])) + "%") #on suprime le packet de la liste de packet a renvoiller indexManque.remove(unpackted[0]) except ValueError: #debug value print("List des packet a receptioner ", str(indexManque)) # print("liste des packet déja receptioner", str(indexRecieve)) print("chunk a suprimer :", unpackted[0]) print("packet unpackted", str(unpackted)) print("raw packet", str(rawtram)) else: #ajouter un compteur pour dire q'uon a un packet corrompu pour les packet perdu !! print( "Unboxing: BAD INDEX Duplicate Packet or Malformed packet ?" ) #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) time.sleep(0.1) if (i == maxretry): exit("connexion perdu") #s.setblocking(True) return retour def sendACKvrf(data, match): while True: mydata = sendACK(data) if (type(match) == bytes): if mydata == match: break else: print("ACKvfr attendue : ", match, "is byte reçus", mydata) if (type(match) == str): if mydata == match.encode(): break else: print("ACKvfr attendue : ", match.encode(), " is str reçus", mydata) return True #fonction qui va calculer les packet perdu def lostpacket(id): indexlost = indexManque.index(id) for a in range(len(indexRecieve)): if (indexRecieve[a][0] == id): indexadd = a break #trame perdu + trame reception = nombre trame totale totaltramesend = indexadd + indexlost + 1 #raport de perte return (indexlost + 1) / totaltramesend * 100 def writeTo(name): # global indexRecieve #ABON ? #on essay suprime le fichier si il existe #flmee de chercherune fonction de test si le fichier existe avant de le suprimer name = str(name) try: #on essaye de le supprimer os.remove(name) print("fichier supprimer") except OSError as e: print("fichier inéxistant") #on va ouvrire le fichiuer with open( name, 'w' ) as fout: #création de du fichier data.txt sur le module si il n'est pas present, ou sinon on l'ouvre en mode ajout de data. #on va parser notre tableaux de tuple for truc in indexRecieve: #on va selecioner la 2eme valeur de notre tuple (les data) fout.write(truc[1]) # on referme le fichier proprement fout.close() print("Attente Trame Datalenght") #purge le buffer au cas ou purge() s.settimeout(10) ##EXPERIMENTAL POUR PAS BLOQUER #pour définire nbtrame on va accepter que les trame étant sur 1 octée en Long varnul = 0 while True: try: nbtrame = unpack('L3s32s', s.recv(buffersize)) if nbtrame[1] == b'OwO': checksum = nbtrame[2] nbtrame = nbtrame[0] break except Exception as e: print("INITIALISATION: nombretrame err : Trame Non attendue", str(nbtrame)) varnul += 1 if (varnul == maxretry): exit("connexion perdu") print("nombre de trame", str(nbtrame)) s.settimeout(timeout) #on déduit le type de variable a utiliser en fonction du nombre de trame total if nbtrame < 256: tVarIndex = "B" stVarIndex = "B" + str(buffersize - 1) playloadsize = str(buffersize - 1) elif (nbtrame < 65536): tVarIndex = "H" stVarIndex = "H" + str(buffersize - 2) playloadsize = str(buffersize - 1) else: tVarIndex = "L" stVarIndex = "L" + str(buffersize - 4) playloadsize = str(buffersize - 1) #génération d'un tableaux qui contien toute les trame for number in range(int(nbtrame)): indexManque.append(number) print("envoit d'un ackitement") #Unboxing de la premierre trame de donnée qui fait office d'ackitment purge() startAt = time.time() unboxing(sendACK(str(nbtrame))) print("démarage reception") startAt = time.time() #je demande explicitement d'écouter j'usqua se que je recois une trame s.setblocking(True) while True: #tant que l'éméteur veux envoiller des donnée while True: #je reçois ma trame ##experimentale s.settimeout(10) ## trame = s.recv(buffersize) s.settimeout(timeout) ## #quand l'éméteur a fini ENvoit de stop pour passer a la partie suivante if trame == b'STOP': print("fin de flux reçus !") #s.send("OK") break #sinon on traite la trame normalement else: #on va traiter la trame recus unboxing(trame) print("Packet perdu" + str( len(indexManque) / (len(indexRecieve) + len(indexManque)) * 100) + "%") #si il n'y a plus de trame manquante if (len(indexManque) == 0): print("plus de trame manquante.") #sendACK("STOP") #on va indiquer a l'éméteur que ces fini s.send("STOP") #on sort de toute mes boucle affain de passer a au trie des data break print("trame perdu/restant:") print(indexManque) #Envoit des trame a retransmetre #+ ajout de la premierre trame reçus (data) #on copy explicitement le précédant tableaux dans un nouveaux indexManquetosend = indexManque.copy() time.sleep(0.250) #tant qu'il reste des trame dans la liste TEMPORAIRE des trame qui manque while len(indexManquetosend): #vieux conmpeur i = 0 #on initialise ma future trame en déclarant que ça serat du binaire temp = b'' #je crée une trame qui sera égale a la taille du buffer ou inferieure tant qu'il me reste des valeur a y metre ## i<(buffersize/2) #mieux ? ########################### while i < 32 and len(indexManquetosend): #je rajoute de nouveaux Idex de trame manquante a ma trame éxistante temp += pack('H', indexManquetosend[0]) #je suprime la valeur ajouter indexManquetosend.pop(0) i += 1 #je m'assurt que l'éméteur a bien recus la trame qu'il a recus est qu'il n'es pas perdu [utile quand je chercherer a débusquer les trame malformer] sendACKvrf( temp, "indexOKforNext" ) #######a la place de indexOk peut metre un ckecksum print("INDEXE echangée " + str(i) + " liste des chunck") #on envoit a l'éméteur un signial indiquant qu'il n'y a plus de trame a envoiller est on verifi qu'il est bien sincro print("on STOP la l'émition") sendACKvrf("STOPliste", "indexFIN") print("liste trame manquante bien réceptioner" ) ## ligne 160 et 163 redondante ? print(indexManque) #on envoit une trame pour trigguer l'éméteur pour qu'il passe en mode émition et on traite la premierre valeur reçus ###metre un time out a l'éméteur #on commence la reception qqd on est sur d'avoir du binaire tmpp = b'indexFIN' while tmpp == b'indexFIN': print(tmpp) #debug tmpp = sendACK("GO") print(tmpp) #debug unboxing(tmpp) print("début de la rerectption") #### print("récéption terminer:") purge() s.setblocking(False) s.send("FinTransmition") s.send("FinTransmition") s.send("FinTransmition") stopAt = time.time() print("trie:") #on va trier en fonction du 1er élémenet du tuple du tableaux indexRecieve.sort(key=itemgetter(0)) #print(indexRecieve) datafile = b'' for truc in indexRecieve: if (truc[1] == b''): break datafile += truc[1] print("durée du transfer:", str(stopAt - startAt), "seconde débit moyen de", str(len(datafile) / (stopAt - startAt)), "octée/s") m = hashlib.sha256() m.update(datafile) print("################") if checksum == m.digest(): print("Fichier intègre !") else: print("/!\ bad checksum ! /!\ ") print("################") print("Phase écriture:") writeTo(fichier) # print("durée du transfer:",str(stopAt-startAt),"débit moyen de", str(os.stat("imgOut.txt")[5]/(stopAt-startAt))) print("transfer terminer") print(str(indexRecieve))
class Transceiver: def __init__(self, app_eui=0, app_key=0, dev_addr=0, nwk_swkey=0, app_swkey=0, dataRate=0, adr=False, useSavedState=True): self.app_eui = app_eui self.app_key = app_key self.dev_addr = dev_addr self.nwk_swkey = nwk_swkey self.app_swkey = app_swkey self.dataRate = dataRate self.adr = adr self.useSavedState = useSavedState # Initialize LoRa in LORAWAN mode self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868, power_mode=LoRa.TX_ONLY, adr=self.adr) # Restore LoRa state from memory (join state, frame counter) if self.useSavedState: self.lora.nvram_restore() else: self.lora.nvram_erase() # Only (re)join if not joined before if not self.lora.has_joined(): if self.app_eui != 0 and self.app_key != 0: # join a network using OTAA (Over the Air Activation). Start with sf12 self.lora.join(activation=LoRa.OTAA, auth=(self.app_eui, self.app_key), dr=0, timeout=0) elif self.dev_addr != 0 and self.nwk_swkey != 0 and self.app_swkey != 0: # join a network using ABP (Authentication By Personalization) self.lora.join(activation=LoRa.ABP, auth=(self.dev_addr, self.nwk_swkey, self.app_swkey)) else: print("Invalid ABP or OTAA keys") return # wait until the module has joined the network (ToDo: timeout to prevent indefinite loop) while not self.lora.has_joined(): time.sleep(2.5) print('.', end='') return def transmit(self, payload): self.lora.set_battery_level(self.__getLoraBattLevel()) # create a LoRa socket self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) # set the LoRaWAN data rate self.s.setsockopt(socket.SOL_LORA, socket.SO_DR, self.dataRate) # selecting non-confirmed type of messages self.s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, False) # make the socket blocking # (waits for the data to be sent and for the 2 receive windows to expire) self.s.setblocking(True) # select port self.s.bind(1) # Send the LoRa message self.s.send(payload) # make the socket non-blocking # (because if there's no data received it will block forever...) self.s.setblocking(False) # get any data received (if any...) self.receivePayload = self.s.recv(64) #print("Store LoRa state in memory") self.lora.nvram_save() return def receive(self): return self.receivePayload def getMac(self): return binascii.hexlify(self.lora.mac()).upper().decode('utf-8') def stats(self): return self.lora.stats() def __getLoraBattLevel(self): adc = machine.ADC() battReg = adc.channel(pin='P16', attn=1) #print('Battery voltage:', battReg() * 3 * 1.334 / 4095) loraBattLevel = int(battReg() / 14.9) if loraBattLevel > 254: loraBattLevel = 0 battVoltage = battReg() * 3 * 1.334 / 4095 #print("Battery level: %d (%f V)" % (loraBattLevel, battVoltage)) return loraBattLevel
if events & LoRa.RX_PACKET_EVENT: print("Packet received") print(s.recv(64)) except Exception: print('Exception') cb = lora.callback(handler=lora_cb_handler, trigger=LoRa.TX_PACKET_EVENT | LoRa.RX_PACKET_EVENT) s.setblocking(True) for i in range(2): print(s.send("Sending pk #%d" % i)) time.sleep(0.5) lst = (lora, s) cb = lora.callback(handler=lora_cb_handler, trigger=LoRa.TX_PACKET_EVENT | LoRa.RX_PACKET_EVENT, arg=lst) s.setblocking(True) for i in range(2): print(s.send("Sending pk #%d" % i)) time.sleep(0.5) print(lora.stats().rx_timestamp > 0) print(lora.stats().rssi < 0) print(lora.stats().snr > 0) print(lora.stats().sftx >= 0) print(lora.stats().sfrx >= 0) print(lora.stats().tx_trials >= 1)
class Comunication: def __init__(self): self.key = b'encriptaincendis' pass def start_LoraRaw(self): self.lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868) self.s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.s.setblocking(False)#Aquesta instrucció igual sobra time.sleep(5) lora=self.lora #return(lora) def change_txpower(self,power): self.lora.tx_power(power) def savestate(self): self.lora.nvram_save() def sendData(self,msg,rtc,f): if "Hay" not in msg: f=open('/sd/msg_sent_middle1.txt','a') f.write("{}/{}/{} {}:{}:{} msg {} stats {}\n".format(rtc.now()[2],rtc.now()[1],rtc.now()[0],rtc.now()[3],rtc.now()[4],rtc.now()[5],msg,self.lora.stats())) f.close() self.s.setblocking(True) iv = crypto.getrandbits(128) # hardware generated random IV (never reuse it) cipher = AES(self.key, AES.MODE_CFB, iv) misg_crc=msg+" "+str(self.calculate_crc(msg)) msg = iv + cipher.encrypt(misg_crc) self.s.send(msg) self.s.setblocking(False) #print(msg) #print(len(msg)) #time.sleep(5) def reciveData(self,rtc,f): self.s.setblocking(False) msg=self.s.recv(128)#Get any data recieved #If there's any data, decrypt if (len(msg)>0): try: #print("encriptat: ",msg) cipher = AES(self.key, AES.MODE_CFB, msg[:16]) # on the decryption side original = cipher.decrypt(msg[16:]) print("original ",original) if "Config" in original or "stop" in original or "Discover" in original or "Hello" in original or "Info" in original or "Token" in original or "Alarm" in original or "Hay" in original: crc_OK,msg=self.check_crc(original) if crc_OK: if "Hay" not in msg: f=open('/sd/msg_received_middle1.txt','a') f.write("{}/{}/{} {}:{}:{} msg {} stats {}\n".format(rtc.now()[2],rtc.now()[1],rtc.now()[0],rtc.now()[3],rtc.now()[4],rtc.now()[5],msg,self.lora.stats())) f.close() return(msg) else: print("CRC not OK") return("error") else: return("error") except Exception as e: print(e) return("error") else: return("error") def update_neighbours(self,pow,id_n,neighbours): if id_n in neighbours[0]: if pow < neighbours[1][neighbours[0].index(id_n)]: neighbours[1][neighbours[0].index(id_n)]=pow else: neighbours[0].append(id_n) neighbours[1].append(pow) #print("I have a friend ") print(neighbours) return neighbours def neighbours_min(self,neighbours,neighbours_aux): for id in neighbours[0]: if id in neighbours_aux[0]: neighbours[1][neighbours[0].index(id)]=min(neighbours[1][neighbours[0].index(id)],neighbours_aux[1][neighbours_aux[0].index(id)]) print(neighbours) return(neighbours) def calculate_crc(self,msg): """ Compute CRC """ if type(msg)==bytes: msg=bytes.decode(msg) crc = 0 data=bin(int(binascii.hexlify(msg),16)) data=str.encode(data) for i in range(len(data)): byte = data[i] for b in range(8): fb_bit = (crc ^ byte) & 0x01 if fb_bit == 0x01: crc = crc ^ 0x18 crc = (crc >> 1) & 0x7f if fb_bit == 0x01: crc = crc | 0x80 byte = byte >> 1 return crc def check_crc(self,msg): """ Check if CRC received is correct """ if type(msg)==bytes: msg=bytes.decode(msg) splitmsg=msg.split( ) crc_rcv=int(splitmsg[-1]) aux=" ".join(splitmsg[:-1]) #Not including the CRC received crc_new = self.calculate_crc(aux) return (crc_new==crc_rcv,aux)
def receive_data(): global index global guard global slot global packet_size lora = LoRa(mode=LoRa.LORA, rx_iq=True, frequency=freqs[my_sf - 5], region=LoRa.EU868, power_mode=LoRa.ALWAYS_ON, bandwidth=my_bw, sf=my_sf) lora_sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) lora_sock.setblocking(False) guard = 1000 * guard (overall_received, overall_sent) = (0, 0) airt = int(airtime_calc(my_sf, 1, packet_size + 2, my_bw_plain) * 1000) duty_cycle_limit_slots = math.ceil(100 * airt / (airt + 2 * guard)) print("duty cycle slots:", duty_cycle_limit_slots) print("packet airtime (ms):", airt / 1000) print("guard time (ms):", guard / 1000) chrono = Timer.Chrono() chrono.start() i = 1 while (True): print(i, "----------------------------------------------------") print("Net size is:", index + 1) chrono.reset() round_start = chrono.read_us() received = 0 acks = [] if (int(index) > duty_cycle_limit_slots): round_length = math.ceil(int(index) * (airt + 2 * guard)) else: round_length = math.ceil(duty_cycle_limit_slots * (airt + 2 * guard)) lora.init(mode=LoRa.LORA, rx_iq=True, region=LoRa.EU868, frequency=freqs[my_sf - 5], power_mode=LoRa.ALWAYS_ON, bandwidth=my_bw, sf=my_sf) rec_start = chrono.read_us() pycom.rgbled(green) while ((chrono.read_us() - round_start) < round_length - (airt + 2 * guard)): # kill the last slot recv_pkg = lora_sock.recv(256) if (len(recv_pkg) > 2): recv_pkg_len = recv_pkg[1] recv_pkg_id = recv_pkg[0] if (int(recv_pkg_id) <= 35) and (int(recv_pkg_len) == int(packet_size)): dev_id, leng, msg = struct.unpack( _LORA_RCV_PKG_FORMAT % recv_pkg_len, recv_pkg) if (len(msg) == packet_size): # format check received += 1 # print('Received from: %d' % dev_id) print(dev_id, lora.stats()) acks.append(str(int(dev_id))) pycom.rgbled(off) print(received, "packets received") rec_lasted = chrono.read_us() - rec_start if (rec_lasted < round_length): print("I'll sleep a bit to align with the round length") time.sleep_us(int(round_length - rec_lasted)) print("Receiving lasted (ms):", (chrono.read_us() - rec_start) / 1000) print("...should last (ms):", round_length / 1000) proc_t = chrono.read_us() ack_msg = "" for n in range(int(index) + 1): if n in slot: id = str(slot[n]) if id in acks: ack_msg = ack_msg + "1" else: ack_msg = ack_msg + "0" if (ack_msg != ""): ack_msg = str(hex(int(ack_msg, 2)))[2:] print("proc time (ms):", (chrono.read_us() - proc_t) / 1000) proc_t = chrono.read_us() - proc_t sync_start = chrono.read_us() pycom.rgbled(white) time.sleep_us(int(3 * guard / 2)) lora.init(mode=LoRa.LORA, tx_iq=True, frequency=freqs[my_sf - 5], region=LoRa.EU868, power_mode=LoRa.TX_ONLY, bandwidth=my_bw, sf=my_sf, tx_power=14) data = str(index + 1) + ":" + str(int(proc_t / 1000)) + ":" + ack_msg pkg = struct.pack(_LORA_PKG_FORMAT % len(data), MY_ID, len(data), data) pycom.rgbled(red) lora_sock.send(pkg) print("Sent sync: " + data) pycom.rgbled(off) time.sleep_ms(17) # node time after sack print("sync lasted (ms):", (chrono.read_us() - sync_start) / 1000) print("round lasted (ms):", (chrono.read_us() - round_start) / 1000) i += 1
class LoRaHelper: def __init__(self, app_eui_hexstr, app_key_hexstr, debug_led=True, debug_output=True): self._debug = debug_output self._led = debug_led if self._led: pycom.heartbeat(False) pycom.rgbled(0x500000) self._app_eui = binascii.unhexlify(app_eui_hexstr) self._app_key = binascii.unhexlify(app_key_hexstr) self._air_time_base = 0 tmp = pycom.nvs_get('air') if tmp is not None: self._air_time_base = tmp self._air_time = self._air_time_base self._sock = None self._lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) if self._led: pycom.rgbled(0x500000) if self._debug: print('LoRaHelper (debug): LoRa MAC: ' + str(binascii.hexlify(self._lora.mac()))) print('LoRaHelper (debug): Joining network ...') self._lora.join(activation=LoRa.OTAA, auth=(self._app_eui, self._app_key), timeout=0) tmp_on = True while not self._lora.has_joined(): if self._debug: print('LoRaHelper (debug): Joining ...') time.sleep(1) tmp_on = not tmp_on if self._led: if tmp_on: pycom.rgbled(0x502000) else: pycom.rgbled(0x000000) if self._led: pycom.rgbled(0x505000) if self._debug: print('LoRaHelper (debug): LoRaWan network joined!') if self._debug: print('LoRaHelper (debug): Creating socket') self._sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self._sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) if self._led: pycom.rgbled(0x005000) if self._debug: print('LoRaHelper (debug): Creating socket') def mac(self): return binascii.hexlify(self._lora.mac()).upper().decode('utf-8') def has_joined(self): return self._lora.has_joined() def air_time(self): self._air_time = self._air_time_base + self._lora.stats().tx_time_on_air pycom.nvs_set('air', self._air_time) return self._air_time def send(self, data: bytes): if self._sock is None: self._sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self._sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) self._sock.setblocking(True) self._sock.send(data) self._sock.setblocking(False) self._air_time = self._air_time_base + self._lora.stats().tx_time_on_air pycom.nvs_set('air', self._air_time) def recv(self): if self._sock is None: self._sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self._sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) self._sock.setblocking(False) data = self._sock.recv(128) return data
class LoraController: def __init__(self, options, logger, eventLog, ledController): self.options = options self.logger = logger self.eventLog = eventLog self.led = ledController self.lora = LoRa(mode=LoRa.LORA, power_mode=LoRa.SLEEP) self.tx_runner = None # thread which sends events over lora self.lastJoin = 0 # when did we join the lora network self.isJoinLogged = False # did we log the initial LORA join self.lastEventId = 0 # last sent event id self.sendLock = _thread.allocate_lock() self.socketLock = _thread.allocate_lock() self.isAckingCounter = 0 self.noDownlinkCounter = 0 self.lastUplinkTime = 0 self.isAcking = False # logging def log(self, *text): self.logger.log("LORA", *text) # start lora connectivity def start(self): # setup lorawan self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868, device_class=LoRa.CLASS_A, tx_retries=3, adr=True, sf=12) self.lora.nvram_restore() self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT | LoRa.TX_FAILED_EVENT), handler=self.lora_callback) self.log('Lora DevEUI is', self.getDeviceEUI()) self.log('Lora AppEUI is', self.options['lora_app_eui']) if len(self.options['lora_app_eui']) != 16: self.log("ERROR", "Setting 'lora_app_eui' is invalid:", self.options['lora_app_eui']) return # issue join if self.options['lora_mode'] == "abp": self.join() elif self.lora.has_joined(): self.log("Lora network is already joined, re-joining anyway") else: self.join() def lora_callback(self, lora): events = lora.events() if events & LoRa.TX_FAILED_EVENT: self.log('Lora TX FAILED') # determines the LORA MAC address (string) def getDeviceEUI(self): return ubinascii.hexlify(self.lora.mac()).decode('ascii').upper() # joins the lora network via OTAA def joinOTAA(self): app_eui = ubinascii.unhexlify(self.options['lora_app_eui']) app_key = ubinascii.unhexlify(self.options['lora_app_key']) self.lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) self.log("Joining via OTAA") self.lastJoin = time.time() # joins the lora network via ABP def joinABP(self): net_key = ubinascii.unhexlify(self.options['lora_net_key']) app_key = ubinascii.unhexlify(self.options['lora_app_key']) # note: TTN seems to want the reverse bytes of this address device_address = ubinascii.unhexlify(self.options['lora_dev_adr']) self.lora.join(activation=LoRa.ABP, auth=(device_address, net_key, app_key)) self.log("Joining via ABP with device address", device_address) self.lastJoin = time.time() # joins the lora network via ABP or OTAA def join(self): if self.options['lora_mode'] == "abp": self.joinABP() else: self.joinOTAA() def hasJoined(self): return self.lora.has_joined() def stats(self): return self.lora.stats() def makePayload(self, event): payload = None command = event['Command'] idbytes = event['ID'].to_bytes(2, 'little') event_ts = event['Time'] try: if command == eventlog.CMD_TAG_DETECTED: # Tag with 4-Byte UID detected # <0x01> <Event ID 0..1> <Timestamp 0..3> <UID 0..3/6/9> timeBytes = event_ts.to_bytes(4, 'little') uid = event['Data'][0:10] # remove trailing 0x00 uid_size = 10 for i in range(uid_size - 1, 3, -1): if uid[i] != 0x00: break uid_size = uid_size - 1 uid = uid[:uid_size] payload = bytes([0x01]) + idbytes + timeBytes + uid uidText = ubinascii.hexlify(uid).decode() self.log("CMD 0x01 [NFC_DETECTED] SEQ#", event['ID'], ". uid =", uidText, ", ts =", event_ts) if command == eventlog.CMD_TIME_REQUEST2: # ask backend for current time (new) # <0x04> <ID 0..1> <Our Time 0..3> mytime = time.time().to_bytes(4, 'little') payload = bytes([command]) + idbytes + mytime self.log("CMD 0x04 [TIME_REQUEST] ID#", event['ID'], ". our_time =", time.time(), utime.gmtime(time.time())) if command == eventlog.CMD_TIME_CHANGED: # <0x05> <Event ID 0..1> <Our Time 0..3> <Old Time 0..3> mytime = event_ts.to_bytes(4, 'little') oldTime = event['Data'][0:4] payload = bytes([eventlog.CMD_TIME_CHANGED ]) + idbytes + mytime + oldTime self.log("CMD 0x05 [TIME_CHANGED] SEQ#", event['ID'], ". our_time =", event_ts, utime.gmtime(event_ts), ", old_time =", oldTime) except Exception as e: self.log("ERROR: Unable to prepare LORA payload:", e.args[0], e) return payload # attempts to send the given event def sendEvent(self, event): with self.sendLock: eventId = event['ID'] command = event['Command'] self.log("Preparing to send CMD =", command, ", SEQ_NO =", eventId) if self.lastEventId > 0 and eventId > self.lastEventId + 1: self.log("ERROR", "Event IDs are not in sequence - last:", self.lastEventId, ", current:", eventId) self.lastEventId = eventId # prepare lora payload for supported event log entries payload = self.makePayload(event) if payload == None: self.log( "WARN: Event payload is None and therefore ignored for lora transmission" ) return True # send payload return self.sendAndHandleResponse(payload) # sends the payload and handles the optional response def sendAndHandleResponse(self, payload): if not self.hasJoined(): self.log("ERROR", "Unable to send LORA payload because not joined") return False # send responseData = self.sendPayload(payload) if responseData == False: self.noDownlinkCounter = self.noDownlinkCounter + 1 return False # handle response if responseData != None and len(responseData) > 0: try: return True except Exception as e: self.log("ERROR: Unable to handle LORA payload: ", e.args[0], e) self.noDownlinkCounter = self.noDownlinkCounter + 1 else: self.noDownlinkCounter = self.noDownlinkCounter + 1 # the message has been sent return True def sendTimeRequest(self, clockSyncEvent, clockSyncRequests): clockSyncEvent['Command'] = eventlog.CMD_TIME_REQUEST2 payload = self.makePayload(clockSyncEvent) try: with self.sendLock: # send lora uplink responseData = self.sendPayload(payload, False) if responseData == False: return None except Exception as e: self.log("ERROR", "Unable to sync clock via LORA:", e.args[0], e) return None # send the specified payload def sendPayload(self, data, updateTime=True): try: with self.socketLock: self.log("> sending", len(data), "bytes:", binascii.hexlify(data)) responseData = None # create a LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setblocking(False) try: """free_memory = gc.mem_free() allocated_memory = gc.mem_alloc() print("Free Memory: " + str(free_memory) + " -- Allocated Memory : " + str(allocated_memory))""" s.send(data) time.sleep(5) responseData = s.recv(64) except Exception as e: self.log("ERROR", "LORA Socket Exception", e) s.close() if responseData != None: responseLen = len(responseData) if responseLen > 0: self.log("< received", responseLen, "bytes:", binascii.hexlify(responseData)) else: self.log("< no downlink") # log if updateTime == True: self.lastUplinkTime = time.time() self.log(self.stats()) time.sleep_ms(10) # save frame counters self.lora.nvram_save() time.sleep_ms(5) return responseData except Exception as e: self.log("ERROR", "Unable to send payload", e.args[0], e) return False
class LORA(object): 'Wrapper class for LoRa' def __init__(self, dr=2): # LoRa and socket instances # Initialize LoRa in LORAWAN mode self.lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) self.callback = None self.sockets = [] self.dr = dr # socket dr self.LED = None self.debug = False def connect(self, method, ports=1, callback=None, myLED=None, dr=None, debug=False): """ Connect device to LoRa. Set the socket and lora instances. myLED is led object, on resume use lora nvram """ self.callback = callback # call back routine on LoRa reply callback(port,response) self.debug = debug self.LED = myLED if myLED: myLED.heartbeat(False) self.restore sleep_ms(100) if self.lora.has_joined() or self.status: # resume LoRa OTAA or ABP self.getPorts(ports) return True if self.debug: print("No previous LoRa join. Try to join.") if (not type(method) is dict): raise ValueError("No activation method defined.") fnd = False try: if not method['OTAA'][0]: raise ValueError() fnd = True except: try: # OTAA from Config import dev_eui except: from machine import unique_id from ubinascii import hexlify dev_eui = 'AAAA' + hexlify(unique_id()) # use dflt try: from Config import app_eui, app_key method['OTAA'] = (dev_eui, app_eui, app_key) fnd = True except: pass if not fnd: try: if not method['ABP'][0]: raise ValueError() fnd = True except: # ABP try: from Config import dev_addr, nwk_swkey, app_swkey method['ABP'] = (dev_addr, nwk_swkey, app_swkey) fnd = True except: pass if not fnd: raise ValueError("No LoRa keys defined") if self.debug: print("LoRa keys load from Config") count = 0 if self.debug: print("Try to join LoRa/%s" % str(method.keys())) if 'OTAA' in method.keys(): # first OTAA from ubinascii import unhexlify # Join a network using OTAA (Over the Air Activation) next code looks strange dev_eui = method['OTAA'][0] dev_eui = unhexlify(dev_eui) app_eui = method['OTAA'][1] app_eui = unhexlify(app_eui) app_key = method['OTAA'][2] app_key = unhexlify(app_key) self.lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=dr) # Wait until the module has joined the network if myLED: myLED.blink(4, 2.5, 0x04acf6) else: sleep_ms(10000) while not self.lora.has_joined(): if count > 15: break # machine.reset()? print("Wait for OTAA join: ", count) count += 1 if myLED: myLED.blink(2, 2.5, 0xff0000) else: sleep_ms(5000) if self.lora.has_joined(): count = 1 print("LoRa OTAA join.") else: count = 0 if not count: # if not ABP if not 'ABP' in method.keys(): print("No ABP TTN keys defined.") return False import struct from ubinascii import unhexlify # next code is strange. ABP method is not yet operational dev_addr = method['ABP'][0] dev_addr = unhexlify(dev_addr) dev_addr = struct.unpack('>l', dev_addr)[0] nwk_swkey = method['ABP'][1] nwk_swkey = unhexlify(nwk_swkey) app_swkey = method['ABP'][2] app_swkey = unhexlify(app_swkey) print("LoRa ABP join.") self.lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey)) self.getPorts(ports) if myLED: myLED.blink(2, 0.1, 0x009900) self.dump return True def getPorts(self, ports): # Create a LoRa sockets self.sockets = [] self.sockets.append(socket.socket(socket.AF_LORA, socket.SOCK_RAW)) # Set the LoRaWAN data rate self.sockets[0].setsockopt(socket.SOL_LORA, socket.SO_DR, self.dr) # Make the socket non-blocking self.sockets[0].setblocking(False) # Create a raw LoRa socket # default port 2 self.sockets.append(None) for nr in range(ports): self.sockets.append(socket.socket(socket.AF_LORA, socket.SOCK_RAW)) self.sockets[nr + 2].setblocking(False) if nr: self.sockets[nr + 2].bind(nr + 2) if self.debug: print("Installed LoRa port %d" % (nr + 2)) return True def send(self, data, port=2): """ Send data over the network. """ if (port < 2) or (port > len(self.sockets)): raise ValueError('Unknown LoRa port %d' % port) if not self.sockets[port]: raise OSError('No socket') rts = True try: self.sockets[port].send(data) if self.LED: self.LED.blink(2, 0.1, 0x0000ff) if self.debug: print("Sending data") # print(data) except OSError as e: if e.errno == 11: print("Caught exception while sending") print("errno: ", e.errno) else: print("Lora ERROR: %s" % e) rts = False if self.LED: self.LED.off data = self.sockets[port].recv(64) if self.debug: print("Received data:", data) if self.callback and data: self.callback(port, data) sleep_ms(1000) self.dump # save status return rts @property def dump(self): from time import sleep_ms sleep_ms(2000) if self.debug: print("Save LoRa keys") return self.lora.nvram_save() @property def restore(self): self.lora.nvram_restore() if self.debug: print("Restore LoRa keys") return self.lora.stats().tx_counter @property def status(self): return self.lora.stats().tx_counter @property def clear(self): if self.debug: print("Clear LoRa keys") self.lora.nvram_erase()
public=pub, tx_retries=tx_retr, device_class=dev_class) # Get loramac as id to be sent in message 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 # s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5) tStartMsec = time.ticks_ms() LoraStats = "" # init lora stats print("Start lora rx") while True: #### # get any data received... #s.setblocking(True) print("Recibiendo") dataRx,a = swlp.trecvcontrol(s, lora_mac, ANY_ADDR) LoraStats = lora.stats() # get lora stats if isNotBlank (dataRx): print("rx[{}] stats[{}]".format(dataRx, LoraStats)) # wait a random amount of time # time.sleep(machine.rng() & 0x07)
### Encrypt data function to send via LPWAN def encrypt(send_pkg): cipher = AES(configs.key, AES.MODE_CFB, iv) send_pkg = iv + cipher.encrypt(send_pkg) return (send_pkg) ### Send data via LPWAN def LoRaSend(string): sl = socket.socket(socket.AF_LORA, socket.SOCK_RAW) sl.setblocking(True) sl.send(encrypt(configs.SITE + mac() + '&' + string)) # Send on LoRa Network sl.setblocking(False) print('Sent: ' + string) ### Establish Connection and Prepare to Send Package lora = LoRa(mode=LoRa.LORA, region=LoRa.AU915, power_mode=LoRa.TX_ONLY) string = '{"val":' + str(ch1.getData()) + ',"volt":' + str( getVoltage()) + ',"msgID":' + str(lora.stats()[8]) + '}' LoRaSend(string) lora = LoRa(mode=LoRa.LORA, region=LoRa.AU915, power_mode=LoRa.SLEEP) indicate() #Data Sent Successfully ### Cleanup and Enter Hibernation print('Entering Hibernation') wdt.feed() wdt = WDT(timeout=3610000) gc.collect() machine.deepsleep(3600000)
"\n\n\n") # 3 saut à la ligne pour diferentier les data precedentes datafile.close() # on referme le fichier while (True): s.setblocking(False) # module en position d'écoute data = s.recv(64) # data avec un buffer de 64 time.sleep(2) # patienter 2 sec pour que les data arrive coord = l76.coordinates() #récupération des coordoné GPS if coord == (None, None) and data == b'': pycom.rgbled(0x7f0000) # rouge => - Coordoné ; - data if coord != (None, None) and data == b'': pycom.rgbled(0x0000ff) # bleu => + Coordoné ; - data if coord == (None, None) and data != b'': pycom.rgbled(0xffff00) # jaune => - Coordoné ; + data if coord != (None, None) and data != b'': pycom.rgbled(0x007f00) # vert => + Coordoné ; + data txt = coord, lora.stats(), data with open('data.txt', 'a') as datafile: tx = str( txt ) + "\n" #on note les coordonées GPS, les statistique du module et les data recu datafile.write(tx) datafile.close() print( txt ) # lorsque l'on est brancher au pc, on observe les data mis dans le fipy
request = 0 # Inicialización índice del array de petición nstations = len(stations) # Número de estaciones timOut = 0 # Contador de iteraciones while True: try: s.send(stations[request]) # Petición de envío a un emisor del array print(stations[request]) time.sleep(0.5) loraread = s.recv(1024) # Lectura del puerto Lora # Decodificación del mensaje a utf-8 msg = loraread.decode("utf-8") # Filtro para detectar mensaje correcto if len(loraread) > 5 and stations[request] in msg: stats = lora.stats() # Parámetros de la com. Lora print(stats) # Muestra lso parámetros de la comunicación rssidB = str(stats.rssi) # Obtención del rssi telegram = msg.replace("rssi", rssidB) # Introducir rssi en el Telegrama uart.write(telegram) # Mandar telegrama por puerto serie print(telegram) time.sleep(1.0) timOut = 0 # Reinicio del contador de intentos # Cambio del módulo a llamar if request == nstations - 1: request = 0 else: request = request + 1 time.sleep(1.0) else: # Aumento el contador de intentos
# more params can also be given, like frequency, tx power and spreading factor lora = LoRa(mode=LoRa.LORA) # get LoRa MAC address loramac = binascii.hexlify(network.LoRa().mac()) print(loramac) loramac2 = binascii.unhexlify(loramac) # create a raw LoRa socket s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) while True: # get any data received... s.setblocking(False) data = s.recv(64) data2 = str(data) if data != b'': macorigen, sender, receiver, message = data2.split(",") print(data) largo = len(message) messagef = message[:largo - 1] print(messagef) LoraStats = lora.stats() # get lora stats (data is tuple) print(LoraStats) if messagef.lower() == "rojo": flash_led_to(RED) time.sleep(5) # wait a random amount of time rat = machine.rng() & 0x05 time.sleep(rat)
# ANTES DE TUDO, O DEVICE E QUEM INICIA A COMUNICACAO, PORTANTO, VOU ENVIAR A PRIMEIRA MENSAGEM s.setblocking(True) s.send("Inicio") s.setblocking(False) print("Iniciando a comunicacao...") # LOOP DE ENVIO E RECEPCAO DE MENSAGENS while (True): # RECEBENDO MENSAGEM msgRecebida = s.recv(64) if len(str(msgRecebida)) > 3: # SE CHEGAR ALGUMA COISA print("Resposta obtida!") rssi = lora.stats()[1] + 0 msgEnviada = str(rssi) # RESPONDENDO s.setblocking(True) s.send(msgEnviada) s.setblocking(False) print("Enviando: " + msgEnviada) else: # SE NAO CHEGAR RESPOSTA s.setblocking(True) s.send("Sem resposta") s.setblocking(False) print("Enviando: Sem resposta")
#if (chrono.read_ms() > 2000): #print('Packet Dropped') #machine.pin_deepsleep_wakeup(pins=['P10'], mode=machine.WAKEUP_ANY_HIGH ) #machine.deepsleep(600000) #return #print('Send Success') #ammend_to_file() #pycom.nvs_set('val', 0) #try: #pycom.nvs_set('msgID', int(pycom.nvs_get('msgID'))+1) #except: #pycom.nvs_set('msgID', 0) pycom.rgbled(0) # Turn on Green LED lora = LoRa(mode=LoRa.LORA, region=LoRa.AU915, power_mode=LoRa.TX_ONLY) sl = socket.socket(socket.AF_LORA, socket.SOCK_RAW) LoRaSend('{"val":' + str(getPressure()) + ',"volt":' + str(getVoltage()) + ',"msgID":' + str(lora.stats()[8]) + '}') print('Send: {"val":' + str(getPressure()) + ',"volt":' + str(getVoltage()) + ',"msgID":' + str(lora.stats()[8]) + '}') lora = LoRa(mode=LoRa.LORA, region=LoRa.AU915, power_mode=LoRa.SLEEP) dac.write(0) dac.deinit() utime.sleep_ms(100) print('Sleeping') wdt.feed() machine.deepsleep(3600000)
class LoRaNode(): def __init__(self, i2c, rtc): self.now = 0 self.lastReportTime = 0 self.ID = machine.unique_id() self.IDhex = str(binascii.hexlify(machine.unique_id()))[2:-1] self.i2c = i2c self.i2cBuffer = bytearray(2) self.SHT31buffer = bytearray(6) #self.uart2 = uart2 self.rtc = rtc self.currentTimeDate = self.rtc.now() self.lora = None self.lora_sock = None self.voltage = 100 self.distance = 0 self.WiFiIsConnected = False self.WiFiIsConnectedLast = False self.config = None self.loadConfig() self.authBase64 = str(binascii.b2a_base64("%s:%s" % (self.config['deviceLogin'], self.config['devicePassword'])))[2:-3] self.authBase64default = str(binascii.b2a_base64("%s:%s" % ("devicebootstrap", "Fhdt1bb1f")))[2:-3] self.rebootSW = Pin('P10', mode=Pin.IN, pull=Pin.PULL_UP) def rebootSWcallback(self, arg): if self.config["bootToConfigMode"] == 0: self.config["bootToConfigMode"] = 1 self.p("WARNING", "Rebooting to configuration mode...") else: self.config["bootToConfigMode"] = 0 self.p("WARNING", "Rebooting to operational mode...") self.saveConfig() machine.reset() def p(self, logItemSeverity, message): self.currentTimeDate = self.rtc.now() if (logItemSeverity == "ERROR" and self.config['serialVerbose'] > 0) or (logItemSeverity == "WARNING" and self.config['serialVerbose'] > 0) or (logItemSeverity == "INFO" and self.config['serialVerbose'] > 1) or ((logItemSeverity == "LORA" or logItemSeverity == "WAN"or logItemSeverity == "CoT") and self.config['serialVerbose'] > 2): print("%sB [%s-%02d-%02d %02d:%02d:%02d] %s: %s" %(gc.mem_free(), self.currentTimeDate[0],self.currentTimeDate[1],self.currentTimeDate[2],self.currentTimeDate[3],self.currentTimeDate[4],self.currentTimeDate[5],logItemSeverity,message)) def loadConfig(self): try: configFile = open('/flash/nodeConfig.json', 'r') data = configFile.readall() self.config = json.loads(data) configFile.close() del data del configFile self.p("INFO", "Configuration loaded") except Exception as e: self.p("ERROR", "Loading of configuration failed") def saveConfig(self): configFile = open('/flash/nodeConfig.json', 'w') configFile.write(json.dumps(self.config)) configFile.close() self.p("INFO", "Config updated") def rebootToConfigMode(self): self.config["bootToConfigMode"] = 1 self.saveConfig() machine.reset() def run(self): self.p("INFO", "Device ID: %s" % (self.IDhex)) swVersion = os.uname() self.p("INFO", "Firmware version: %s" % (swVersion[3])) del swVersion self.p("INFO", "Software version: %s" % (VERSION)) self.p("INFO", "Auth string: %s" % (self.authBase64)) #self.rebootSW.callback(Pin.IRQ_FALLING, self.rebootSWcallback) if self.config["bootToConfigMode"]: self.configMode() else: self.gatewayMode() def startupPhaseCoT(self): global response if self.statusCoT == "STARTING": if self.config['deviceLogin'] == "" or self.config['devicePassword'] == "": self.statusCoT = "REQ_CREDENTIALS" self.p("CoT", "Requesting device credentials from Cloud of Things") else: self.statusCoT = "CHECK_REGISTRATION" elif (self.statusCoT == "REQ_CREDENTIALS" or self.statusCoT == "REQ_CREDENTIALS_REPEATED") and self.now > self.lastRequestTime + self.config['requestIntervalCoT']: try: self.lastRequestTime = self.now response = urequests.post("https://management.ram.m2m.telekom.com/devicecontrol/deviceCredentials", headers={"Authorization": "Basic %s" % self.authBase64default, "Content-Type": "application/vnd.com.nsn.cumulocity.deviceCredentials+json", "Accept": "application/vnd.com.nsn.cumulocity.deviceCredentials+json"}, data='{"id": "%s"}' % self.IDhex) responseJSON = json.loads(response.text) print(responseJSON) if "error" in responseJSON and self.statusCoT == "REQ_CREDENTIALS": # http status code could be checked for 404 as well if responseJSON["error"].find("Not Found") != -1: self.p("WARNING", "No device request for Device ID %s" % (self.IDhex)) self.statusCoT = "REQ_CREDENTIALS_REPEATED" else: print(responseJSON) elif "username" and "password" and "id" in responseJSON: self.p("CoT", "Device ID %s username/password is %s/%s" % (responseJSON["id"], responseJSON["username"], responseJSON["password"])) self.config['deviceLogin'] = responseJSON["username"] self.config['devicePassword'] = responseJSON["password"] self.saveConfig() self.statusCoT = "CHECK_REGISTRATION" except Exception as e: self.p("WARNING", "Could not send request to Cloud of Things (%s)" % (e)) self.CoTisConnected = False elif self.statusCoT == "CHECK_REGISTRATION" and self.now > self.lastRequestTime + self.config['requestIntervalCoT']: try: self.lastRequestTime = self.now response = urequests.get("https://iotatst.ram.m2m.telekom.com/identity/externalIds/c8y_Serial/parking_gateway-%s" % self.IDhex, headers={"Authorization": "Basic %s" % self.authBase64, "Content-Type": "application/vnd.com.nsn.cumulocity.externalID+json"}) if response.status_code == 404: self.p("CoT", "Device not created & registered yet") self.statusCoT = "CREATE_DEVICE" elif response.status_code == 200: responseJSON = json.loads(response.text) self.deviceCoTID = responseJSON["managedObject"]["id"] self.p("CoT", "Device already created & registered with id %s" % (self.deviceCoTID)) self.statusCoT = "UPDATE_DEVICE" except Exception as e: self.p("WARNING", "Could not send request to Cloud of Things (%s)" % (e)) self.CoTisConnected = False elif self.statusCoT == "CREATE_DEVICE" and self.now > self.lastRequestTime + self.config['requestIntervalCoT']: try: self.lastRequestTime = self.now response = urequests.post("https://iotatst.ram.m2m.telekom.com/inventory/managedObjects", headers={"Authorization": "Basic %s" % self.authBase64, "Content-Type": "application/vnd.com.nsn.cumulocity.managedObject+json", "Accept": "application/vnd.com.nsn.cumulocity.managedObject+json"}, data='{"c8y_IsDevice": {}, "name": "Parking gateway %s"}' % self.IDhex) if response.status_code == 201: responseJSON = json.loads(response.text) self.deviceCoTID = responseJSON["id"] self.p("CoT", "Device %s created with Cloud of Things ID %s" % (responseJSON["name"], self.deviceCoTID)) self.statusCoT = "REGISTER_DEVICE" except Exception as e: self.p("WARNING", "Could not send request to Cloud of Things (%s)" % (e)) self.CoTisConnected = False elif self.statusCoT == "REGISTER_DEVICE" and self.now > self.lastRequestTime + self.config['requestIntervalCoT']: try: self.lastRequestTime = self.now response = urequests.post("https://iotatst.ram.m2m.telekom.com/identity/globalIds/%s/externalIds" % self.deviceCoTID, headers={"Authorization": "Basic %s" % self.authBase64, "Content-Type": "application/vnd.com.nsn.cumulocity.externalId+json", "Accept": "application/vnd.com.nsn.cumulocity.externalId+json"}, data='{"type": "c8y_Serial", "externalId": "parking_gateway-%s"}' % self.IDhex) if response.status_code == 201: responseJSON = json.loads(response.text) self.p("CoT", "External ID %s registered with Cloud of Things ID %s" % (responseJSON["externalId"], self.deviceCoTID)) self.statusCoT = "STARTUP_FINISHED" else: print(response.status_code, response.text) except Exception as e: self.p("WARNING", "Could not send request to Cloud of Things (%s)" % (e)) self.CoTisConnected = False elif self.statusCoT == "UPDATE_DEVICE" and self.now > self.lastRequestTime + self.config['requestIntervalCoT']: self.p("CoT", "Updatng device information on Cloud of Things (to be implemented...)") self.statusCoT = "STARTUP_FINISHED" def sendMeasurementToCoT(self, sensorNr, distance, voltage): global data global response self.rtcNow = self.rtc.now() #print("source: {id %s}, time: %s-%02d-%02dT%02d:%02d:%02d.%03d+00:00, type: parking_sensor, c8y_measurement: {measuredDistance-%02d: {value: %s, unit: %02d}%s}}" % (self.deviceCoTID, self.rtcNow[0], self.rtcNow[1], self.rtcNow[2], self.rtcNow[3], self.rtcNow[4], self.rtcNow[5], self.rtcNow[6] // 1000, sensorNr, distance, sensorNr, vol)) data='{"source": {"id": "%s"}, "time": "%s-%02d-%02dT%02d:%02d:%02d.%03d+00:00", "type": "parking_sensor", "c8y_measurement": {"measuredDistance-%02d": {"value": %s, "unit": "cm"}, "batteryPercentage-%02d": {"value":%s, "unit": "per" }}}' % (self.deviceCoTID, self.rtcNow[0], self.rtcNow[1], self.rtcNow[2], self.rtcNow[3], self.rtcNow[4], self.rtcNow[5], self.rtcNow[6] // 1000, sensorNr, distance, sensorNr, voltage) self.p("CoT", "Sending measurement to Cloud of Things > %s" % (data)) try: response = urequests.post("https://iotatst.ram.m2m.telekom.com/measurement/measurements", headers={"Authorization": "Basic %s" % self.authBase64, "Content-Type": "application/vnd.com.nsn.cumulocity.measurement+json", "Accept": "application/vnd.com.nsn.cumulocity.measurement+json"}, data=data) responseJSON = json.loads(response.text) if response.status_code != 201: print(response.status_code, response.text) except Exception as e: self.p("WARNING", "Could not send request to Cloud of Things (%s)" % (e)) self.CoTisConnected = False def gatewayMode(self): self.p("INFO", "Starting in LoRa gateway mode") self.targetGatewayID = bytearray(6) self.sensorID = bytearray(6) self.sensorNr = 0 self.wlan = network.WLAN(mode=network.WLAN.STA, antenna=network.WLAN.INT_ANT) self.statusCoT = "STARTING" self.lastRequestTime = 0 self.timeSynchonized = False try: self.wlan.ifconfig(config='dhcp') except Exception as e: self.p("WARNING", e) self.p("WAN", "Trying to connect to WiFi SSID %s" % (self.config['WiFiSSID'])) self.wlan.connect(ssid=self.config['WiFiSSID'], auth=(network.WLAN.WPA2, self.config['WiFiPassword'])) try: self.lora = LoRa(mode=LoRa.LORA, frequency=self.config['frequency'], tx_power=int(self.config['powerTX']), bandwidth=self.config['bandwidth'], sf=self.config['spreadingFactor'], coding_rate=self.config['codingRate'], rx_iq=True) self.p("INFO", "LoRa radio interface initialized at %sHz with %sdBm TX power, %skHz bandwidth, spreading factor %s and coding rate %s" % (self.config['frequency'], self.config['powerTX'], BANDWIDTH[self.config['bandwidth']], self.config['spreadingFactor'], CODING_RATE[self.config['codingRate']-1])) except Exception as e: self.p("WARNING", "Error during Lora radio interface initialization: %s" % e) self.lora_sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW) self.lora_sock.setblocking(False) while True: self.now = time.time() self.WiFiIsConnected = self.wlan.isconnected() if self.WiFiIsConnected and not self.WiFiIsConnectedLast: self.p("WAN", "Connected to WiFi SSID %s (IP address %s)" % (self.config['WiFiSSID'], self.wlan.ifconfig()[0])) if not self.WiFiIsConnected and self.WiFiIsConnectedLast: self.p("WAN", "Disconnected from WiFi SSID %s" % (self.config['WiFiSSID'])) self.WiFiIsConnectedLast = self.WiFiIsConnected if self.WiFiIsConnected: if not self.timeSynchonized: try: self.rtc.ntp_sync("pool.ntp.org") self.p("INFO", "Time synchronized") self.timeSynchonized = True except: self.p("WARNING", "Could not synchronize time") if self.statusCoT != "STARTUP_FINISHED": self.startupPhaseCoT() encryptedPkg = self.lora_sock.recv(512) if len(encryptedPkg) > 0: if len(encryptedPkg) == 31: cipher = crypto.AES(self.config["AESkey"], crypto.AES.MODE_CFB, encryptedPkg[:16]) recv_pkg = cipher.decrypt(encryptedPkg[16:]) self.sensorNr, self.voltage, self.distance, self.targetGatewayID[0], self.targetGatewayID[1], self.targetGatewayID[2], self.targetGatewayID[3], self.targetGatewayID[4], self.targetGatewayID[5], self.sensorID[0], self.sensorID[1], self.sensorID[2], self.sensorID[3], self.sensorID[4], self.sensorID[5] = struct.unpack(_LORA_PKG_FORMAT, recv_pkg) if self.IDhex == str(binascii.hexlify(self.targetGatewayID))[2:-1]: self.p("INFO", "Sensor Nr:%s Sensor ID:%s Target GW:%s > Voltage:%sV Distance:%scm RSSI:%sdBm SNR:%sdB" % (self.sensorNr, str(binascii.hexlify(self.sensorID))[2:-1], str(binascii.hexlify(self.targetGatewayID))[2:-1], self.voltage, self.distance, self.lora.stats()[1], self.lora.stats()[2])) if self.statusCoT == "STARTUP_FINISHED": self.sendMeasurementToCoT(self.sensorNr, self.distance, self.voltage) else: self.p("WARNING", "Unexpected lenght of LoRa message: %sbytes (%s)" % (len(encryptedPkg), encryptedPkg)) gc.collect()
# create an OTAA authentication parameters app_eui = binascii.unhexlify('<Insert your app eui here!>'.replace(' ', '')) app_key = binascii.unhexlify('<Insert your app key here!>'.replace(' ', '')) # join a network using ABP (Activation By Personalization) 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(): # join a network using ABP (Activation By Personalization) time.sleep(1) print("retrying...") print("Joined LoRa Network!") # Print LoRa Stats lora.stats() # Call back for T/RX Messages def lora_cb(lora): events = lora.events() if events & LoRa.RX_PACKET_EVENT: print('Lora packet received') if events & LoRa.TX_PACKET_EVENT: print('Lora packet sent') lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=lora_cb) # create a LoRa socket
global s print(type(lora)) try: events = lora.events() if events & LoRa.TX_PACKET_EVENT: print("Packet sent") if events & LoRa.RX_PACKET_EVENT: print("Packet received") print(s.recv(64)) except Exception: print('Exception') cb = lora.callback(handler=lora_cb_handler, trigger=LoRa.TX_PACKET_EVENT | LoRa.RX_PACKET_EVENT,) s.setblocking(True) for i in range(2): print(s.send("Sending pk #%d" % i)) time.sleep(0.5) lst = (lora, s) cb = lora.callback(handler=lora_cb_handler, trigger=LoRa.TX_PACKET_EVENT | LoRa.RX_PACKET_EVENT, arg=lst) s.setblocking(True) for i in range(2): print(s.send("Sending pk #%d" % i)) time.sleep(0.5) print(lora.stats().timestamp > 0) print(lora.stats().rssi < 0) print(lora.stats().snr > 0) print(lora.stats().sf >= 0)