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)
Exemple #2
0
    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()