diff --git a/RaspberryPi_Receiver/Pi_Receiver.py b/RaspberryPi_Receiver/Pi_Receiver.py index 673dbeff00bb3f337d89763c095465ed652ff397..5af394b62e835271e452c18192802a9e861a445f 100644 --- a/RaspberryPi_Receiver/Pi_Receiver.py +++ b/RaspberryPi_Receiver/Pi_Receiver.py @@ -32,6 +32,7 @@ # Usage: python Pi_Receiver.py -f 433 -b BW125 -s 7 +from argparse import ArgumentError import sys sys.path.insert(0, '../') @@ -52,6 +53,24 @@ BOARD.setup() parser = LoRaArgumentParser("Continous LoRa receiver.") +# Recived from Sensors when they have data to send +class RxHello(object): + def __init__(self, uid, reservationTime): + self.uid = uid + self.reservationTime = reservationTime + self.okToTransmit = False + self.txAuthID = None + + def setOK(self, okToTransmit): + self.okToTransmit = okToTransmit + + def setTxAuthID(self, txAuthID): + self.txAuthID = txAuthID + + # Python Object to JSON Object + def ToJson(self): + return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4) + class SensorResponse(object): def __init__(self, sensorMetadata, data): self.sensorMetadata = SensorMetadata(**sensorMetadata) @@ -194,47 +213,118 @@ def getserial(): return cpuserial -# Parse LoRa response, validate, save / transmit -def handleData(data): +# Upon succesfully receiving a message, send back an ack +def ackMsg(sensorResponse): + data = Reply(sensorResponse.sensorMetadata.uid, sensorResponse.sensorMetadata.messageID) + data.setAckStatus(True) + + print(data.ToJson()) + + _length, _payload = packer.Pack_Str( data.ToJson() ) + + payload = [int(hex(c), 0) for c in _payload] + + loraReceiver.transmit(payload) + return + +# When a sensor has data to transmit, it will send a TxHello. +# Pick up that message here and decide if we can accept the message at this time. +def handleRxHello(data): + timeBegin = time() + print("\n[?] Try RX Hello!\nRaw data: %s" % data) + + try: + rxHelloJson = json.loads(data) + rxHello = RxHello(**rxHelloJson) + + except Exception as e: + print("[-] Not RX Hello\n") + return False + + print("[+] RX Hello Confirmed!\n") + # TODO Check i'm not expecting any methods within rxHello.reservationTime seconds + + # TODO Send "OK" + UID + TX_AUTH_ID + rxHello.setOK(True) # We are happy for this sensor to send it's data + rxHello.setTxAuthID(123) + print(rxHello.ToJson()) + + _length, _payload = packer.Pack_Str( rxHello.ToJson() ) # Send OK Back Back + payload = [int(hex(c), 0) for c in _payload] + + loraReceiver.transmit(payload) + print("\n[+] RX Hello \"OK\" Reply Sent\n") + + # Sleep until out transmit block expires (2 Seconds) + #sleep(2 - (time() - timeBegin)) + sleep(0.2) + return True + + +# handle SensorResponse data packet +def handleSensorResponsePacket(data): + timeBegin = time() + print("\n[?] Try Sensor Response Data!\nRaw data: %s" % data) + try: parsed = json.loads(data) p = SensorResponse(**parsed) except Exception as e: - print("[-] Unable to Parse response, ignoring") # TODO Error handling, log increased error rates etc + print("\n[-] Unable to Parse response, ignoring") # TODO Error handling, log increased error rates etc if DEBUG > 1: print("\tE: %e" % e) - return + return False - # TODO Transmit ACK - ackMsg(p) + print("[+] Sensor Response Data Confirmed!\n") + print(p.ToJson()) # TODO Validate response is valid and non-corrupt + # TODO Ack / process here + + # TODO Transmit ACK + print("\n[+] Sending Sensor Response Ack") + ackMsg(p) + print("[+] Sensor Response Ack Sent\n") + # Process response - print("Sensor ID: %s" % (p.sensorMetadata.uid)) - print("\tPPM 10: %s" % p.sensorReading.ppm.p10) - #SensorReading = SensorModule(parsed) - #sensorData = sensorData(parsed['sensorData']) + print("Sensor ID: %s \tPPM 10: %s\n" % (p.sensorMetadata.uid, p.sensorReading.ppm.p10)) # TODO Send To API + print("\n[+] Sending Data to API") p.sendToApi() - print(p.ToJson()) - + print("[+] Data Sent to API\n") -# Upon succesfully receiving a message, send back an ack -def ackMsg(sensorResponse): - data = Reply(sensorResponse.sensorMetadata.uid, sensorResponse.sensorMetadata.messageID) - data.setAckStatus(True) + # Sleep until out transmit block expires (2 Seconds) + #sleep(2 - (time() - timeBegin)) + sleep(0.2) - print(data.ToJson()) - _length, _payload = packer.Pack_Str( data.ToJson() ) - payload = [int(hex(c), 0) for c in _payload] +# Parse LoRa response, validate, save / transmit +def handleData(data): + # Handle TxHello Transmission + # Rx - "I've got data to send!" + UID (From Sensor) + # If not expecting any messages, continue + # Tx - "OK" + UID (Back to Sensor) + TX_Auth_ID + # + # <Do not Tx for 2s> + if (handleRxHello(data)): # Handled all OK + return + + # T-0 Rx - Packet + UID + Tx_Auth_ID (From Sensor) + # Handle message, ack / nak appropriately + # Tx - Ack + UID + Next_Send_Interval + # Tx - Nak + UID + # + # <Do not Tx for 3s> + if (handleSensorResponsePacket(data)): + return + + + # T+3 Tx reserved window expires - loraReceiver.transmit(payload) - return # Setup Receiver loraReceiver = LoRaReceiver(verbose=False)