예제 #1
0
    def basic_check(self, received_testscript_msg_bytes):
        """
        Basic check for all the LoRaWAN test steps. It verifies the MIC of the message and sets
        a flag if the received message if of a CONFIRMED_UP type
        (so an ACK could be sent to the DUT).
        """
        super().basic_check(
            received_testscript_msg_bytes=received_testscript_msg_bytes)
        self.received_testscript_msg = flora_messages.GatewayMessage(
            json_ttm_str=received_testscript_msg_bytes.decode())
        lorawan_msg = self.received_testscript_msg.parse_lorawan_message()
        mtype_str = lorawan_msg.mhdr.mtype_str
        # Register in flag if the received message needs Acknowdlegment knowdlege
        if mtype_str in ('CONFIRMED_UP', ):
            self.ctx_test_manager.device_under_test.message_to_ack = True
        else:
            self.ctx_test_manager.device_under_test.message_to_ack = False
        network_key = self.ctx_test_manager.device_under_test.loramac_params.nwkskey
        if mtype_str in ('JOIN_REQUEST', ):
            network_key = self.ctx_test_manager.device_under_test.appkey
        logger.info(
            f"Checking MIC using key {utils.bytes_to_text(network_key)}.")
        calculated_mic = lorawan_msg.calculate_mic(key=network_key)

        if not lorawan_msg.mic_bytes == calculated_mic:
            description_template = "Wrong MIC.\nKey: {key}\nMIC: {received_mic}\nCalculated: {calc}"
            raise lorawan_errors.MICError(
                description=description_template.format(
                    key=utils.bytes_to_text(network_key),
                    received_mic=utils.bytes_to_text(lorawan_msg.mic_bytes),
                    calc=utils.bytes_to_text(calculated_mic)),
                test_case=self.ctx_test_manager.tc_name,
                step_name=self.name,
                last_message=self.received_testscript_msg.get_printable_str())
예제 #2
0
 def raise_unexpected_response_error(self, last_message_bytes):
     self.received_testscript_msg = flora_messages.GatewayMessage(
         json_ttm_str=last_message_bytes.decode())
     exeption_raised = test_errors.UnexpectedResponseError(
         description="Unexpected msg.",
         test_case=self.ctx_test_manager.tc_name,
         step_name=self.name,
         last_message=str(self.received_testscript_msg))
     logger.debug(str(exeption_raised))
     raise exeption_raised
예제 #3
0
 def step_handler(self, ch, method, properties, body):
     """
     Accepts a join request if it has the correct format and is not a replay
     (devnonce not previously used).
     """
     if not self.received_testscript_msg:
         self.received_testscript_msg = flora_messages.GatewayMessage(
             json_ttm_str=body.decode())
     lw_joinrequest = self.received_testscript_msg.parse_lorawan_message()
     if lw_joinrequest.mhdr.mtype_str == "JOIN_REQUEST":
         self.process_join_request(body_bytes=body)
     else:
         raise test_errors.UnexpectedResponseError(
             description="A Join Request message was expected.",
             step_name=self.name,
             last_message=self.received_testscript_msg.get_printable_str(),
             test_case=self.ctx_test_manager.tc_name)
예제 #4
0
    def step_handler(self, ch, method, properties, body):
        if not self.received_testscript_msg:
            self.received_testscript_msg = flora_messages.GatewayMessage(
                json_ttm_str=body.decode())

        frmpayload_response = tests_parameters.FRMPAYLOAD.TEST_DEACTIVATE
        end_device = self.ctx_test_manager.device_under_test
        lw_response = end_device.prepare_lorawan_data(
            frmpayload=frmpayload_response, fport=224)
        if self.default_rx1_window:
            json_nwk_response = self.received_testscript_msg.create_nwk_response_str(
                phypayload=lw_response,
                delay=end_device.loramac_params.rx1_delay,
                datr_offset=end_device.loramac_params.rx1_dr_offset)
        else:
            json_nwk_response = self.received_testscript_msg.create_nwk_response_str(
                phypayload=lw_response,
                delay=end_device.loramac_params.rx2_delay,
                data_rate=end_device.loramac_params.rx2_dr,
                frequency=end_device.loramac_params.rx2_frequency)
        self.send_downlink(routing_key=message_broker.routing_keys.toAgent +
                           '.gw1',
                           msg=json_nwk_response)
        received_lorawan = self.received_testscript_msg.parse_lorawan_message(
            ignore_format_errors=True)

        step_report = ui_reports.InputFormBody(
            title="{TC}: Print message".format(
                TC=self.ctx_test_manager.tc_name.upper()),
            tag_key=self.ctx_test_manager.tc_name,
            tag_value=" ")

        step_report.add_field(
            ui_reports.ParagraphField(name="Received in Step: {}".format(
                self.name),
                                      value=str(received_lorawan)))
        step_report.add_field(
            ui_reports.ParagraphField(
                name="Sent in Step: {}".format(self.name),
                value=str(lorawan_parser.LoRaWANMessage(lw_response))))
        ui_publisher.display_on_gui(
            msg_str=str(step_report),
            key_prefix=message_broker.service_names.test_session_coordinator)
        self.print_step_info(
            sending=tests_parameters.FRMPAYLOAD.TEST_DEACTIVATE)
예제 #5
0
    def step_handler(self, ch, method, properties, body):
        """ Pong message handler."""
        if not self.received_testscript_msg:
            self.received_testscript_msg = flora_messages.GatewayMessage(
                json_ttm_str=body.decode())

        received_lorawan = self.received_testscript_msg.parse_lorawan_message()

        appskey = self.ctx_test_manager.device_under_test.loramac_params.appskey
        received_frmpayload = received_lorawan.get_frmpayload_plaintext(
            key=appskey)

        mtype_str = received_lorawan.mhdr.mtype_str
        if mtype_str in ('UNCONFIRMED_UP', 'UNCONFIRMED_DOWN', 'CONFIRMED_UP',
                         'CONFIRMED_DOWN'):
            if (received_lorawan.macpayload.fport_int == 224
                    and received_frmpayload[0:1]
                    == lorawan.lorawan_parameters.testing.TEST_CODE.PINGPONG):

                if not received_frmpayload == self.expected_bytes:
                    raise lorawan_errors.EchoError(
                        description="PONG {0} received when expecting {1}.".
                        format(utils.bytes_to_text(received_frmpayload),
                               utils.bytes_to_text(self.expected_bytes)),
                        step_name=self.name,
                        test_case=self.ctx_test_manager.tc_name,
                        last_message=self.received_testscript_msg.
                        get_printable_str(encryption_key=appskey))
            else:
                # If it's a data message, but not a PONG, the FRMPayload is decrypted and showed in the GUI.
                raise test_errors.UnexpectedResponseError(
                    description="Waiting for a PONG response.",
                    step_name=self.name,
                    last_message=self.received_testscript_msg.
                    get_printable_str(encryption_key=appskey),
                    test_case=self.ctx_test_manager.tc_name)
        else:
            raise test_errors.UnexpectedResponseError(
                description="Waiting for a PONG response.",
                step_name=self.name,
                last_message=self.received_testscript_msg.get_printable_str(),
                test_case=self.ctx_test_manager.tc_name)
예제 #6
0
    def step_handler(self, ch, method, properties, body):
        """
        Actions performed in this step of the test.
        """

        if not self.received_testscript_msg:
            self.received_testscript_msg = flora_messages.GatewayMessage(
                json_ttm_str=body.decode())
        frmpayload_response = tests_parameters.FRMPAYLOAD.TEST_ACT
        lw_received = self.received_testscript_msg.parse_lorawan_message()
        mtype_str = lw_received.mhdr.mtype_str
        if mtype_str == "JOIN_REQUEST":
            self.process_join_request(body_bytes=body)
        # If it's a TESTING MESSAGE (LoRaWAN data using port 224):
        elif (mtype_str in ('UNCONFIRMED_UP', 'CONFIRMED_UP')
              and not lw_received.macpayload.fport_int == 224):
            end_device = self.ctx_test_manager.device_under_test
            lw_response = end_device.prepare_lorawan_data(
                frmpayload=frmpayload_response, fport=224)
            if self.default_rx1_window:
                json_nwk_response = self.received_testscript_msg.create_nwk_response_str(
                    phypayload=lw_response,
                    delay=end_device.loramac_params.rx1_delay,
                    datr_offset=end_device.loramac_params.rx1_dr_offset)
            else:
                json_nwk_response = self.received_testscript_msg.create_nwk_response_str(
                    phypayload=lw_response,
                    delay=end_device.loramac_params.rx2_delay,
                    data_rate=end_device.loramac_params.rx2_dr,
                    frequency=end_device.loramac_params.rx2_frequency)
            self.send_downlink(
                routing_key=message_broker.routing_keys.toAgent + '.gw1',
                msg=json_nwk_response)
            self.ctx_test_manager.ctx_test_session_coordinator.downlink_counter = 0
            self.print_step_info(sending=frmpayload_response)
        else:
            raise test_errors.UnexpectedResponseError(
                description="Waiting for a data message (any port but 224).",
                step_name=self.name,
                last_message=self.received_testscript_msg.get_printable_str(),
                test_case=self.ctx_test_manager.tc_name)
예제 #7
0
    def process_join_request(self, body_bytes):
        """
        Process a Join Request message and sends the Join Accept in the default RX1 with the
        configured parameters.
        :param body_bytes: byte sequence of the Join Request.
        :return: None.
        """
        if not self.received_testscript_msg:
            self.received_testscript_msg = flora_messages.GatewayMessage(
                json_ttm_str=body_bytes.decode())

        lw_joinrequest = self.received_testscript_msg.parse_lorawan_message()
        devnonce = lw_joinrequest.macpayload.devnonce_bytes
        end_device = self.ctx_test_manager.device_under_test
        previous_rx1_dr = end_device.loramac_params.rx1_dr_offset
        previous_rx2_dr = end_device.loramac_params.rx2_dr
        jaccept_phypayload = self.ctx_test_manager.device_under_test.accept_join(
            devnonce=devnonce,
            dlsettings=self.accept_dlsettings,
            rxdelay=self.accept_rxdelay,
            cflist=self.accept_cflist)
        if self.default_rx1_window:
            json_nwk_response = self.received_testscript_msg.create_nwk_response_str(
                phypayload=jaccept_phypayload,
                delay=end_device.loramac_params.joinaccept_delay1,
                datr_offset=previous_rx1_dr)
        else:
            json_nwk_response = self.received_testscript_msg.create_nwk_response_str(
                phypayload=jaccept_phypayload,
                delay=end_device.loramac_params.joinaccept_delay2,
                data_rate=previous_rx2_dr,
                frequency=end_device.loramac_params.rx2_frequency)
        self.send_downlink(routing_key=message_broker.routing_keys.toAgent +
                           '.gw1',
                           msg=json_nwk_response)

        self.print_step_info(
            received_str=self.received_testscript_msg.get_printable_str(),
            sending=jaccept_phypayload,
            additional_message="Session Updated.\n" +
            str(self.ctx_test_manager.device_under_test))
예제 #8
0
    def step_handler(self, ch, method, properties, body):
        """ Checks the downlink counter of an Activation Ok message."""
        if not self.received_testscript_msg:
            self.received_testscript_msg = flora_messages.GatewayMessage(
                json_ttm_str=body.decode())
        lw_message = self.received_testscript_msg.parse_lorawan_message()
        appskey = self.ctx_test_manager.device_under_test.loramac_params.appskey
        received_frmpayload = lw_message.get_frmpayload_plaintext(key=appskey)

        mtype_str = lw_message.mhdr.mtype_str
        if (mtype_str in ('UNCONFIRMED_UP', 'CONFIRMED_UP')
                and lw_message.macpayload.fport_int == 224
                and len(received_frmpayload) == 2 and received_frmpayload[0:1]
                != lorawan.lorawan_parameters.testing.TEST_CODE.PINGPONG):
            self.check_act_ok(received_frmpayload=received_frmpayload)
        else:
            raise test_errors.UnexpectedResponseError(
                description="Waiting for an ACT OK with downlink counter.",
                step_name=self.name,
                last_message=self.received_testscript_msg.get_printable_str(),
                test_case=self.ctx_test_manager.tc_name)
    def up_message_handler(self, body_str):

        received_testscript_msg = flora_messages.GatewayMessage(
            json_ttm_str=body_str)
        lorawan_msg = received_testscript_msg.parse_lorawan_message()
        logger.info("--------------------------------------------------------\n")
        logger.info(f"Received Uplink: {str(lorawan_msg)}")

        mtype_int = lorawan_msg.mhdr.mtype_int

        if lorawan_msg.mhdr.mhdr_bytes == lorawan_parameters.MHDR.JOIN_REQUEST:
            try:
                devnonce = lorawan_msg.macpayload.devnonce_bytes
                deveui_hex = utils.bytes_to_text(lorawan_msg.macpayload.deveui_bytes).upper()
                appeui_hex = utils.bytes_to_text(lorawan_msg.macpayload.appeui_bytes).upper()
                if not self.sessions_handler.is_registered(dev_eui_hex=deveui_hex,
                                                           app_eui_hex=appeui_hex):
                    logger.info(f"Device Not Registered: {deveui_hex}")
                    return
                self.sessions_handler.process_otta_join(
                    deveui_hex=deveui_hex, devnonce=devnonce,
                    dlsettings=self.accept_dlsettings,
                    rxdelay=self.accept_rxdelay,
                    cflist=self.accept_cflist)
                jaccept_phypayload = self.sessions_handler.get_joinaccept_bytes(
                    deveui_hex=deveui_hex)
                json_nwk_response = received_testscript_msg.create_nwk_response_str(
                    phypayload=jaccept_phypayload,
                    delay=lorawan_parameters.TIMING.JOIN_ACCEPT_DELAY1,
                    datr_offset=lorawan_parameters.DR_OFFSET.RX1_DEFAULT)
                logger.info(f"Sending Join Accept: {str(json_nwk_response)}")

                self.downlink_mq_interface.send(routing_key=routing_keys.fromSchedulerToAgent,
                                                data=json_nwk_response)
            except scheduler_errors.DuplicatedNonce as dne:
                logger.info(f"Ignoring Duplicated nonce {devnonce}")
        elif lorawan_msg.mhdr.mhdr_bytes == lorawan_parameters.MHDR.UNCONFIRMED_UP:
            devaddrhex = utils.bytes_to_text(lorawan_msg.macpayload.fhdr.devaddr_bytes).upper()
            network_key_hex = self.sessions_handler.get_nwk_s_key_hex(dev_addr_hex=devaddrhex)
            if network_key_hex is None:
                logger.info(f"No active session for device: {devaddrhex}")
                return
            network_key = bytes.fromhex(network_key_hex)
            calculated_mic = lorawan_msg.calculate_mic(key=network_key)
            dev_eui_hex = self.sessions_handler.get_dev_eui_hex(dev_addr_hex=devaddrhex)
            if not lorawan_msg.mic_bytes == calculated_mic:
                logger.info(
                    f"Wrong MIC. Expecting {calculated_mic}, Device {dev_eui_hex} ({devaddrhex}).")
            logger.info(f"MIC OK (NwkSKey: {utils.bytes_to_text(network_key)}, dev {dev_eui_hex})")

            frmpayload_command = bytes.fromhex(
                self.sessions_handler.get_command_hex(dev_addr_hex=devaddrhex))
            lw_response = self.sessions_handler.prepare_lorawan_data(dev_eui_hex=dev_eui_hex,
                                                                     frmpayload=frmpayload_command)
            json_nwk_response = received_testscript_msg.create_nwk_response_str(
                phypayload=lw_response,
                delay=lorawan_parameters.TIMING.RECEIVE_DELAY1,
                datr_offset=lorawan_parameters.DR_OFFSET.RX1_DEFAULT)
            logger.info(f"Sending Downlink Data: {str(json_nwk_response)}")
            self.downlink_mq_interface.send(routing_key=routing_keys.fromSchedulerToAgent,
                                            data=json_nwk_response)