def send_data(self, data, data_length, frame_counter, timeout=5): # Data packet enc_data = bytearray(data_length) lora_pkt = bytearray(64) # Copy bytearray into bytearray for encryption enc_data[0:data_length] = data[0:data_length] # Encrypt data (enc_data is overwritten in this function) self.frame_counter = frame_counter aes = AES(self._ttn_config.device_address, self._ttn_config.app_key, self._ttn_config.network_key, self.frame_counter) enc_data = aes.encrypt(enc_data) # Construct MAC Layer packet (PHYPayload) # MHDR (MAC Header) - 1 byte lora_pkt[ 0] = REG_DIO_MAPPING_1 # MType: unconfirmed data up, RFU / Major zeroed # MACPayload # FHDR (Frame Header): DevAddr (4 bytes) - short device address lora_pkt[1] = self._ttn_config.device_address[3] lora_pkt[2] = self._ttn_config.device_address[2] lora_pkt[3] = self._ttn_config.device_address[1] lora_pkt[4] = self._ttn_config.device_address[0] # FHDR (Frame Header): FCtrl (1 byte) - frame control lora_pkt[5] = 0x00 # FHDR (Frame Header): FCnt (2 bytes) - frame counter lora_pkt[6] = self.frame_counter & 0x00FF lora_pkt[7] = (self.frame_counter >> 8) & 0x00FF # FPort - port field lora_pkt[8] = self._fport # Set length of LoRa packet lora_pkt_len = 9 if __DEBUG__: print("PHYPayload", ubinascii.hexlify(lora_pkt)) # load encrypted data into lora_pkt lora_pkt[lora_pkt_len:lora_pkt_len + data_length] = enc_data[0:data_length] if __DEBUG__: print("PHYPayload with FRMPayload", ubinascii.hexlify(lora_pkt)) # Recalculate packet length lora_pkt_len += data_length # Calculate Message Integrity Code (MIC) # MIC is calculated over: MHDR | FHDR | FPort | FRMPayload mic = bytearray(4) mic = aes.calculate_mic(lora_pkt, lora_pkt_len, mic) # Load MIC in package lora_pkt[lora_pkt_len:lora_pkt_len + 4] = mic[0:4] # Recalculate packet length (add MIC length) lora_pkt_len += 4 if __DEBUG__: print("PHYPayload with FRMPayload + MIC", ubinascii.hexlify(lora_pkt)) self.send_packet(lora_pkt, lora_pkt_len, timeout)
def handle_on_receive(self, event_source): self.set_lock(True) # lock until TX_Done aes = AES(self._ttn_config.device_address, self._ttn_config.app_key, self._ttn_config.network_key, self.frame_counter) # irqFlags = self.getIrqFlags() should be 0x50 if (self.get_irq_flags() & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0: if self._on_receive: payload = self.read_payload() self.set_lock(False) # unlock when done reading data = aes.decrypt_payload(payload) self._on_receive(self, data) self.set_lock(False) # unlock in any case. self.collect_garbage()