wiliot-certificate 4.4.2__py3-none-any.whl → 4.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {brg_certificate → certificate}/ag/wlt_cmd_if.html +10 -4
- {brg_certificate → certificate}/ag/wlt_types_ag.py +1878 -519
- certificate/cert_common.py +1488 -0
- certificate/cert_config.py +480 -0
- {brg_certificate → certificate}/cert_data_sim.py +134 -46
- {brg_certificate → certificate}/cert_defines.py +129 -128
- {brg_certificate → certificate}/cert_gw_sim.py +183 -53
- {brg_certificate → certificate}/cert_mqtt.py +179 -64
- {brg_certificate → certificate}/cert_prints.py +35 -33
- {brg_certificate → certificate}/cert_protobuf.py +15 -6
- {brg_certificate → certificate}/cert_results.py +240 -64
- certificate/cert_utils.py +634 -0
- certificate/certificate.py +205 -0
- certificate/certificate_cli.py +76 -0
- certificate/certificate_eth_test_list.txt +76 -0
- certificate/certificate_sanity_test_list.txt +66 -0
- certificate/certificate_test_list.txt +76 -0
- {brg_certificate → certificate}/tests/calibration/interval_test/interval_test.json +3 -2
- {brg_certificate → certificate}/tests/calibration/interval_test/interval_test.py +7 -6
- certificate/tests/calibration/output_power_test/output_power_test.json +23 -0
- certificate/tests/calibration/output_power_test/output_power_test.py +39 -0
- {brg_certificate → certificate}/tests/calibration/pattern_test/pattern_test.json +2 -1
- {brg_certificate → certificate}/tests/calibration/pattern_test/pattern_test.py +20 -15
- certificate/tests/cloud_connectivity/acl_ext_adv_test/acl_ext_adv_test.json +15 -0
- certificate/tests/cloud_connectivity/acl_ext_adv_test/acl_ext_adv_test.py +140 -0
- certificate/tests/cloud_connectivity/acl_test/acl_test.json +15 -0
- certificate/tests/cloud_connectivity/acl_test/acl_test.py +96 -0
- certificate/tests/cloud_connectivity/brg_ota_test/brg_ota_test.json +19 -0
- certificate/tests/cloud_connectivity/brg_ota_test/brg_ota_test.py +41 -0
- certificate/tests/cloud_connectivity/channel_scan_behaviour_test/channel_scan_behaviour_test.json +19 -0
- certificate/tests/cloud_connectivity/channel_scan_behaviour_test/channel_scan_behaviour_test.py +215 -0
- certificate/tests/cloud_connectivity/connection_test/connection_test.json +18 -0
- certificate/tests/cloud_connectivity/connection_test/connection_test.py +67 -0
- certificate/tests/cloud_connectivity/deduplication_test/deduplication_test.json +15 -0
- certificate/tests/cloud_connectivity/deduplication_test/deduplication_test.py +80 -0
- certificate/tests/cloud_connectivity/downlink_test/downlink_test.json +21 -0
- certificate/tests/cloud_connectivity/downlink_test/downlink_test.py +201 -0
- certificate/tests/cloud_connectivity/ext_adv_stress_test/ext_adv_stress_test.json +17 -0
- certificate/tests/cloud_connectivity/ext_adv_stress_test/ext_adv_stress_test.py +104 -0
- certificate/tests/cloud_connectivity/reboot_test/reboot_test.json +18 -0
- certificate/tests/cloud_connectivity/reboot_test/reboot_test.py +59 -0
- certificate/tests/cloud_connectivity/registration_test/registration_test.json +20 -0
- certificate/tests/cloud_connectivity/registration_test/registration_test.py +384 -0
- certificate/tests/cloud_connectivity/registration_test/registration_test_cli.py +90 -0
- certificate/tests/cloud_connectivity/stress_test/stress_test.json +17 -0
- certificate/tests/cloud_connectivity/stress_test/stress_test.py +101 -0
- certificate/tests/cloud_connectivity/uplink_ext_adv_test/uplink_ext_adv_test.json +25 -0
- certificate/tests/cloud_connectivity/uplink_ext_adv_test/uplink_ext_adv_test.py +92 -0
- certificate/tests/cloud_connectivity/uplink_test/uplink_test.json +20 -0
- certificate/tests/cloud_connectivity/uplink_test/uplink_test.py +169 -0
- {brg_certificate → certificate}/tests/datapath/aging_test/aging_test.json +2 -1
- certificate/tests/datapath/aging_test/aging_test.py +142 -0
- certificate/tests/datapath/event_ble5_test/event_ble5_test.json +17 -0
- certificate/tests/datapath/event_ble5_test/event_ble5_test.py +89 -0
- certificate/tests/datapath/event_test/event_test.json +17 -0
- certificate/tests/datapath/event_test/event_test.py +80 -0
- {brg_certificate → certificate}/tests/datapath/num_of_tags_test/num_of_tags_test.json +4 -3
- {brg_certificate → certificate}/tests/datapath/num_of_tags_test/num_of_tags_test.py +19 -13
- certificate/tests/datapath/output_power_test/output_power_test.json +23 -0
- {brg_certificate → certificate}/tests/datapath/output_power_test/output_power_test.py +17 -6
- {brg_certificate → certificate}/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.json +2 -1
- {brg_certificate → certificate}/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.py +13 -11
- {brg_certificate → certificate}/tests/datapath/pacer_interval_test/pacer_interval_test.json +2 -1
- {brg_certificate → certificate}/tests/datapath/pacer_interval_test/pacer_interval_test.py +9 -7
- {brg_certificate → certificate}/tests/datapath/pattern_test/pattern_test.json +3 -2
- {brg_certificate → certificate}/tests/datapath/pattern_test/pattern_test.py +18 -6
- certificate/tests/datapath/pkt_filter_ble5_chl21_test/pkt_filter_ble5_chl21_test.json +20 -0
- certificate/tests/datapath/pkt_filter_ble5_chl21_test/pkt_filter_ble5_chl21_test.py +61 -0
- {brg_certificate → certificate}/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.json +2 -1
- {brg_certificate → certificate}/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.py +15 -14
- certificate/tests/datapath/pkt_filter_brg2gw_ext_adv_test/pkt_filter_brg2gw_ext_adv_test.json +19 -0
- certificate/tests/datapath/pkt_filter_brg2gw_ext_adv_test/pkt_filter_brg2gw_ext_adv_test.py +85 -0
- {brg_certificate → certificate}/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.json +2 -1
- {brg_certificate → certificate}/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.py +10 -9
- {brg_certificate → certificate}/tests/datapath/pkt_filter_test/pkt_filter_test.json +2 -1
- {brg_certificate → certificate}/tests/datapath/pkt_filter_test/pkt_filter_test.py +10 -9
- {brg_certificate → certificate}/tests/datapath/rssi_threshold_test/rssi_threshold_test.json +3 -2
- {brg_certificate → certificate}/tests/datapath/rssi_threshold_test/rssi_threshold_test.py +9 -8
- brg_certificate/tests/datapath/output_power_test/output_power_test.json → certificate/tests/datapath/rx_channel_hopping_test/rx_channel_hopping_test.json +6 -4
- certificate/tests/datapath/rx_channel_hopping_test/rx_channel_hopping_test.py +77 -0
- {brg_certificate → certificate}/tests/datapath/rx_channel_test/rx_channel_test.json +3 -2
- {brg_certificate → certificate}/tests/datapath/rx_channel_test/rx_channel_test.py +7 -6
- {brg_certificate → certificate}/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.json +8 -7
- {brg_certificate → certificate}/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.py +113 -73
- {brg_certificate → certificate}/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.json +8 -7
- {brg_certificate → certificate}/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.py +112 -72
- {brg_certificate → certificate}/tests/datapath/stress_gen3_test/stress_gen3_test.json +4 -3
- {brg_certificate → certificate}/tests/datapath/stress_gen3_test/stress_gen3_test.py +15 -11
- {brg_certificate → certificate}/tests/datapath/stress_test/stress_test.json +4 -3
- {brg_certificate → certificate}/tests/datapath/stress_test/stress_test.py +15 -11
- {brg_certificate → certificate}/tests/datapath/tx_repetition_test/tx_repetition_test.json +3 -1
- {brg_certificate → certificate}/tests/datapath/tx_repetition_test/tx_repetition_test.py +14 -13
- certificate/tests/edge_mgmt/action_blink_test/action_blink_test.json +15 -0
- certificate/tests/edge_mgmt/action_blink_test/action_blink_test.py +24 -0
- certificate/tests/edge_mgmt/action_get_battery_sensor_test/action_get_battery_sensor_test.json +15 -0
- certificate/tests/edge_mgmt/action_get_battery_sensor_test/action_get_battery_sensor_test.py +43 -0
- certificate/tests/edge_mgmt/action_get_module_test/action_get_module_test.json +15 -0
- certificate/tests/edge_mgmt/action_get_module_test/action_get_module_test.py +42 -0
- certificate/tests/edge_mgmt/action_get_pof_data_test/action_get_pof_data_test.json +15 -0
- certificate/tests/edge_mgmt/action_get_pof_data_test/action_get_pof_data_test.py +44 -0
- certificate/tests/edge_mgmt/action_gw_hb_test/action_gw_hb_test.json +16 -0
- certificate/tests/edge_mgmt/action_gw_hb_test/action_gw_hb_test.py +42 -0
- certificate/tests/edge_mgmt/action_reboot_test/action_reboot_test.json +15 -0
- certificate/tests/edge_mgmt/action_reboot_test/action_reboot_test.py +49 -0
- certificate/tests/edge_mgmt/action_restore_defaults_test/action_restore_defaults_test.json +15 -0
- certificate/tests/edge_mgmt/action_restore_defaults_test/action_restore_defaults_test.py +102 -0
- certificate/tests/edge_mgmt/action_send_hb_test/action_send_hb_test.json +15 -0
- certificate/tests/edge_mgmt/action_send_hb_test/action_send_hb_test.py +45 -0
- {brg_certificate → certificate}/tests/edge_mgmt/periodic_msgs_test/periodic_msgs_test.json +3 -2
- {brg_certificate → certificate}/tests/edge_mgmt/periodic_msgs_test/periodic_msgs_test.py +22 -11
- {brg_certificate → certificate}/tests/energy2400/duty_cycle_test/duty_cycle_test.json +2 -1
- {brg_certificate → certificate}/tests/energy2400/duty_cycle_test/duty_cycle_test.py +7 -6
- certificate/tests/energy2400/output_power_test/output_power_test.json +23 -0
- {brg_certificate → certificate}/tests/energy2400/output_power_test/output_power_test.py +17 -6
- {brg_certificate → certificate}/tests/energy2400/pattern_test/pattern_test.json +2 -1
- {brg_certificate → certificate}/tests/energy2400/pattern_test/pattern_test.py +7 -6
- certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.json +26 -0
- certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.py +379 -0
- certificate/tests/energy2400/signal_indicator_ext_adv_test/signal_indicator_ext_adv_test.json +20 -0
- certificate/tests/energy2400/signal_indicator_ext_adv_test/signal_indicator_ext_adv_test.py +173 -0
- certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.json +24 -0
- certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.py +350 -0
- {brg_certificate → certificate}/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.json +2 -1
- {brg_certificate → certificate}/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.py +7 -6
- {brg_certificate → certificate}/tests/energy_sub1g/pattern_test/pattern_test.json +2 -1
- {brg_certificate → certificate}/tests/energy_sub1g/pattern_test/pattern_test.py +7 -6
- {brg_certificate → certificate}/tests/pwr_mgmt/pwr_mgmt_test/pwr_mgmt_test.json +2 -1
- {brg_certificate → certificate}/tests/pwr_mgmt/pwr_mgmt_test/pwr_mgmt_test.py +10 -10
- {brg_certificate → certificate}/tests/sensors/ext_sensor_test/ext_sensor_test.json +5 -4
- certificate/tests/sensors/ext_sensor_test/ext_sensor_test.py +450 -0
- certificate/wlt_types.py +122 -0
- {gw_certificate → common}/api_if/202/status.json +6 -0
- {gw_certificate → common}/api_if/203/status.json +6 -0
- {gw_certificate → common}/api_if/204/status.json +6 -0
- common/api_if/206/data.json +85 -0
- common/api_if/206/status.json +69 -0
- common/api_if/api_validation.py +91 -0
- common/web/templates/generator.html +210 -0
- common/web/templates/index.html +20 -0
- common/web/templates/menu.html +54 -0
- common/web/templates/parser.html +53 -0
- {brg_certificate/ag → common/web/templates}/wlt_types.html +1216 -191
- common/web/web_utils.py +399 -0
- {brg_certificate → common}/wltPb_pb2.py +14 -12
- {gw_certificate/common → common}/wltPb_pb2.pyi +16 -2
- gui_certificate/gui_certificate_cli.py +14 -0
- gui_certificate/server.py +1267 -0
- gui_certificate/templates/cert_run.html +1273 -0
- wiliot_certificate-4.5.0.dist-info/METADATA +99 -0
- wiliot_certificate-4.5.0.dist-info/RECORD +168 -0
- {wiliot_certificate-4.4.2.dist-info → wiliot_certificate-4.5.0.dist-info}/WHEEL +1 -1
- wiliot_certificate-4.5.0.dist-info/entry_points.txt +5 -0
- wiliot_certificate-4.5.0.dist-info/top_level.txt +3 -0
- brg_certificate/ag/energous_v0_defines.py +0 -925
- brg_certificate/ag/energous_v1_defines.py +0 -931
- brg_certificate/ag/energous_v2_defines.py +0 -925
- brg_certificate/ag/energous_v3_defines.py +0 -925
- brg_certificate/ag/energous_v4_defines.py +0 -925
- brg_certificate/ag/fanstel_lan_v0_defines.py +0 -925
- brg_certificate/ag/fanstel_lte_v0_defines.py +0 -925
- brg_certificate/ag/fanstel_wifi_v0_defines.py +0 -925
- brg_certificate/ag/minew_lte_v0_defines.py +0 -925
- brg_certificate/ag/wlt_types_ag_jsons/brg2brg_ota.json +0 -142
- brg_certificate/ag/wlt_types_ag_jsons/brg2gw_hb.json +0 -785
- brg_certificate/ag/wlt_types_ag_jsons/brg2gw_hb_sleep.json +0 -139
- brg_certificate/ag/wlt_types_ag_jsons/calibration.json +0 -394
- brg_certificate/ag/wlt_types_ag_jsons/custom.json +0 -515
- brg_certificate/ag/wlt_types_ag_jsons/datapath.json +0 -672
- brg_certificate/ag/wlt_types_ag_jsons/energy2400.json +0 -550
- brg_certificate/ag/wlt_types_ag_jsons/energySub1g.json +0 -595
- brg_certificate/ag/wlt_types_ag_jsons/externalSensor.json +0 -598
- brg_certificate/ag/wlt_types_ag_jsons/interface.json +0 -938
- brg_certificate/ag/wlt_types_ag_jsons/powerManagement.json +0 -1234
- brg_certificate/ag/wlt_types_ag_jsons/side_info_sensor.json +0 -105
- brg_certificate/ag/wlt_types_ag_jsons/signal_indicator_data.json +0 -77
- brg_certificate/ag/wlt_types_ag_jsons/unified_echo_ext_pkt.json +0 -61
- brg_certificate/ag/wlt_types_ag_jsons/unified_echo_pkt.json +0 -110
- brg_certificate/brg_certificate.py +0 -225
- brg_certificate/brg_certificate_cli.py +0 -63
- brg_certificate/cert_common.py +0 -923
- brg_certificate/cert_config.py +0 -402
- brg_certificate/cert_utils.py +0 -362
- brg_certificate/certificate_bcc_sanity_test_list.txt +0 -40
- brg_certificate/certificate_bcc_test_list.txt +0 -48
- brg_certificate/certificate_sanity_test_list.txt +0 -43
- brg_certificate/certificate_test_list.txt +0 -53
- brg_certificate/config/eclipse.json +0 -10
- brg_certificate/config/hivemq.json +0 -10
- brg_certificate/config/mosquitto.json +0 -10
- brg_certificate/config/mosquitto.md +0 -95
- brg_certificate/config/wiliot-dev.json +0 -10
- brg_certificate/restore_brg.py +0 -61
- brg_certificate/tests/calibration/output_power_test/output_power_test.json +0 -16
- brg_certificate/tests/calibration/output_power_test/output_power_test.py +0 -28
- brg_certificate/tests/datapath/aging_test/aging_test.py +0 -143
- brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.json +0 -16
- brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.py +0 -73
- brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.json +0 -17
- brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.py +0 -118
- brg_certificate/tests/edge_mgmt/actions_test/actions_test.json +0 -14
- brg_certificate/tests/edge_mgmt/actions_test/actions_test.py +0 -396
- brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.json +0 -20
- brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.py +0 -94
- brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.json +0 -19
- brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.py +0 -87
- brg_certificate/tests/edge_mgmt/leds_test/leds_test.json +0 -17
- brg_certificate/tests/edge_mgmt/leds_test/leds_test.py +0 -223
- brg_certificate/tests/edge_mgmt/ota_test/ota_test.json +0 -17
- brg_certificate/tests/edge_mgmt/ota_test/ota_test.py +0 -128
- brg_certificate/tests/energy2400/output_power_test/output_power_test.json +0 -16
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_250k_test/signal_indicator_ble5_10_250k_test.json +0 -20
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_250k_test/signal_indicator_ble5_10_250k_test.py +0 -321
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_500k_test/signal_indicator_ble5_10_500k_test.json +0 -20
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_500k_test/signal_indicator_ble5_10_500k_test.py +0 -321
- brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.json +0 -20
- brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.py +0 -141
- brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.json +0 -20
- brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.py +0 -276
- brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.json +0 -20
- brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.py +0 -390
- brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.json +0 -16
- brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.py +0 -28
- brg_certificate/tests/sensors/ext_sensor_test/ext_sensor_test.py +0 -305
- brg_certificate/wltPb_pb2.pyi +0 -234
- brg_certificate/wlt_types.py +0 -113
- gw_certificate/ag/ut_defines.py +0 -364
- gw_certificate/ag/wlt_types.py +0 -85
- gw_certificate/ag/wlt_types_ag.py +0 -5310
- gw_certificate/ag/wlt_types_data.py +0 -64
- gw_certificate/api/extended_api.py +0 -23
- gw_certificate/api_if/200/data.json +0 -106
- gw_certificate/api_if/200/status.json +0 -47
- gw_certificate/api_if/201/data.json +0 -98
- gw_certificate/api_if/201/status.json +0 -53
- gw_certificate/api_if/205/logs.json +0 -12
- gw_certificate/api_if/api_validation.py +0 -38
- gw_certificate/api_if/gw_capabilities.py +0 -54
- gw_certificate/cert_results.py +0 -145
- gw_certificate/common/analysis_data_bricks.py +0 -60
- gw_certificate/common/debug.py +0 -42
- gw_certificate/common/serialization_formatter.py +0 -93
- gw_certificate/common/utils.py +0 -8
- gw_certificate/common/utils_defines.py +0 -15
- gw_certificate/common/wltPb_pb2.py +0 -84
- gw_certificate/gw_certificate.py +0 -154
- gw_certificate/gw_certificate_cli.py +0 -87
- gw_certificate/interface/4.4.91_app.zip +0 -0
- gw_certificate/interface/4.4.91_sd_bl_app.zip +0 -0
- gw_certificate/interface/ble_simulator.py +0 -61
- gw_certificate/interface/ble_sniffer.py +0 -189
- gw_certificate/interface/flash_fw.py +0 -90
- gw_certificate/interface/if_defines.py +0 -36
- gw_certificate/interface/mqtt.py +0 -563
- gw_certificate/interface/nrfutil-linux +0 -0
- gw_certificate/interface/nrfutil-mac +0 -0
- gw_certificate/interface/nrfutil.exe +0 -0
- gw_certificate/interface/pkt_generator.py +0 -594
- gw_certificate/interface/uart_if.py +0 -236
- gw_certificate/interface/uart_ports.py +0 -20
- gw_certificate/templates/results.html +0 -241
- gw_certificate/templates/stage.html +0 -22
- gw_certificate/templates/table.html +0 -6
- gw_certificate/templates/test.html +0 -38
- gw_certificate/tests/__init__.py +0 -10
- gw_certificate/tests/actions.py +0 -289
- gw_certificate/tests/bad_crc_to_PER_quantization.csv +0 -51
- gw_certificate/tests/connection.py +0 -188
- gw_certificate/tests/downlink.py +0 -172
- gw_certificate/tests/generic.py +0 -238
- gw_certificate/tests/registration.py +0 -340
- gw_certificate/tests/static/__init__.py +0 -0
- gw_certificate/tests/static/connection_defines.py +0 -9
- gw_certificate/tests/static/downlink_defines.py +0 -9
- gw_certificate/tests/static/generated_packet_table.py +0 -195
- gw_certificate/tests/static/packet_table.csv +0 -10067
- gw_certificate/tests/static/references.py +0 -5
- gw_certificate/tests/static/uplink_defines.py +0 -14
- gw_certificate/tests/throughput.py +0 -240
- gw_certificate/tests/uplink.py +0 -853
- wiliot_certificate-4.4.2.dist-info/METADATA +0 -211
- wiliot_certificate-4.4.2.dist-info/RECORD +0 -210
- wiliot_certificate-4.4.2.dist-info/entry_points.txt +0 -3
- wiliot_certificate-4.4.2.dist-info/top_level.txt +0 -3
- {brg_certificate → certificate}/__init__.py +0 -0
- {gw_certificate → common}/api_if/202/data.json +0 -0
- {gw_certificate/api_if/200 → common/api_if/202}/logs.json +0 -0
- {gw_certificate → common}/api_if/203/data.json +0 -0
- {gw_certificate/api_if/201 → common/api_if/203}/logs.json +0 -0
- {gw_certificate → common}/api_if/204/data.json +0 -0
- {gw_certificate/api_if/202 → common/api_if/204}/logs.json +0 -0
- {gw_certificate → common}/api_if/205/data.json +0 -0
- {gw_certificate/api_if/203 → common/api_if/205}/logs.json +0 -0
- {gw_certificate → common}/api_if/205/status.json +0 -0
- {gw_certificate/api_if/204 → common/api_if/206}/logs.json +0 -0
- {gw_certificate → common/api_if}/__init__.py +0 -0
- {gw_certificate/api_if → gui_certificate}/__init__.py +0 -0
- {wiliot_certificate-4.4.2.dist-info → wiliot_certificate-4.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
|
|
2
|
+
import datetime
|
|
3
|
+
import time
|
|
4
|
+
import os
|
|
5
|
+
import requests
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from typing import Literal
|
|
10
|
+
|
|
11
|
+
from certificate.cert_defines import TEST_FAILED, TEST_PASSED, TEST_SKIPPED
|
|
12
|
+
from certificate.cert_prints import phase_run_print
|
|
13
|
+
|
|
14
|
+
import certificate.cert_utils as cert_utils
|
|
15
|
+
import certificate.cert_common as cert_common
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# HELPER DEFINES
|
|
19
|
+
GW_REGISTER_DOC = "https://community.wiliot.com/customers/s/article/Registering-Third-Party-Gateways"
|
|
20
|
+
GW_MQTT_DOC = "https://community.wiliot.com/customers/s/article/Sending-Wiliot-Packets-to-the-Wiliot-Cloud"
|
|
21
|
+
|
|
22
|
+
REGISTRATION_API_KEY_ENV_VAR = "REGISTRATION_TEST_API_KEY"
|
|
23
|
+
|
|
24
|
+
REG_CERT_OWNER_ID = 'gw-certification-account'
|
|
25
|
+
|
|
26
|
+
STAGES_TIMEOUT_MINUTES = 2
|
|
27
|
+
TOKEN_EXPIRY_MINUTES = 3
|
|
28
|
+
CLOUD_DELAY_SEC = 7
|
|
29
|
+
BUSY_WAIT_DELAY_SEC = 5
|
|
30
|
+
STAGE_START_DELAY_MS = (BUSY_WAIT_DELAY_SEC + CLOUD_DELAY_SEC + 1) * 1000
|
|
31
|
+
|
|
32
|
+
ERROR_NO_REGISTER = 'Gateway did not register itself in time.'
|
|
33
|
+
ERROR_NO_ONLINE = 'Gateway did not connect to MQTT in time.'
|
|
34
|
+
ERROR_NO_ACTIVE = 'Gateway did not upload a status message with its configurations in time.'
|
|
35
|
+
ERROR_NO_REFRESH = 'Gateway did not reconnect to MQTT in time.'
|
|
36
|
+
|
|
37
|
+
HEADERS = {
|
|
38
|
+
"accept": "application/json",
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
"Authorization": None
|
|
41
|
+
}
|
|
42
|
+
BASE_URL = "https://api.us-east-2.prod.wiliot.cloud"
|
|
43
|
+
OWNER_URL = BASE_URL + f"/v1/owner/{REG_CERT_OWNER_ID}"
|
|
44
|
+
API_TOKEN_URL = BASE_URL + '/v1/auth/token/api'
|
|
45
|
+
|
|
46
|
+
# GLOBALS
|
|
47
|
+
api_key = None
|
|
48
|
+
gw_online_ts = None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# HTTP RELATED
|
|
52
|
+
class HttpMethod(str, Enum):
|
|
53
|
+
GET = "GET"
|
|
54
|
+
POST = "POST"
|
|
55
|
+
PUT = "PUT"
|
|
56
|
+
DELETE = "DELETE"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def http_request(path, payload, request_method: HttpMethod):
|
|
60
|
+
headers = HEADERS
|
|
61
|
+
|
|
62
|
+
def get_token():
|
|
63
|
+
headers = {
|
|
64
|
+
'Authorization': api_key
|
|
65
|
+
}
|
|
66
|
+
response = requests.post(API_TOKEN_URL, headers=headers)
|
|
67
|
+
if response.status_code == 200:
|
|
68
|
+
token = response.json()
|
|
69
|
+
return token["access_token"]
|
|
70
|
+
else:
|
|
71
|
+
raise Exception(f"Failed to get token. statuscode: {response.status_code}, {response.text}")
|
|
72
|
+
|
|
73
|
+
headers['Authorization'] = get_token()
|
|
74
|
+
response = requests.request(request_method, (OWNER_URL + path), headers=headers, data=payload)
|
|
75
|
+
try:
|
|
76
|
+
message = response.json()
|
|
77
|
+
except json.JSONDecodeError:
|
|
78
|
+
message = response.text
|
|
79
|
+
if isinstance(message, str):
|
|
80
|
+
message = {"data": message}
|
|
81
|
+
message.update({'status_code': response.status_code})
|
|
82
|
+
return message
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def get_gateway(gateway_id):
|
|
86
|
+
path = f"/gateway/{gateway_id}"
|
|
87
|
+
result = http_request(path, payload=None, request_method=HttpMethod.GET)
|
|
88
|
+
if result['status_code'] != 200:
|
|
89
|
+
raise Exception(f"get_gateway request failed with status_code {result['status_code']}")
|
|
90
|
+
return result["data"]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def register_gateway(gateways: list):
|
|
94
|
+
payload = {
|
|
95
|
+
"gateways": gateways
|
|
96
|
+
}
|
|
97
|
+
path = "/gateway"
|
|
98
|
+
response = http_request(path, payload=json.dumps(payload), request_method=HttpMethod.PUT)
|
|
99
|
+
return (response.get("data", "").lower() == "ok", response)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def delete_gateway(gateway_id):
|
|
103
|
+
path = f"/gateway/{gateway_id}"
|
|
104
|
+
response = http_request(path, payload=None, request_method=HttpMethod.DELETE)
|
|
105
|
+
return response.get('message', "").lower().find("success") != -1
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def kick_gw_from_mqtt(gw_id):
|
|
109
|
+
path = f"/gateway/{gw_id}/kick-mqtt-connection"
|
|
110
|
+
response = http_request(path, payload=None, request_method=HttpMethod.POST)
|
|
111
|
+
return response
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def get_kong_logs(gw_id):
|
|
115
|
+
"""
|
|
116
|
+
Only available under the certificate registration account
|
|
117
|
+
"""
|
|
118
|
+
path = f"/gateway/{gw_id}/auth-logs"
|
|
119
|
+
|
|
120
|
+
return http_request(path, payload=None, request_method=HttpMethod.GET)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# TEST RELATED
|
|
124
|
+
class GetGwField(Enum):
|
|
125
|
+
STATUS = 'status'
|
|
126
|
+
ONLINE = 'online'
|
|
127
|
+
ONLINE_UPDATED_AT = 'onlineUpdatedAt'
|
|
128
|
+
ACTIVATED_AT = 'activatedAt'
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class Status(Enum):
|
|
132
|
+
PRE_REGISTERED = 'pre-registered'
|
|
133
|
+
REGISTERED = 'registered'
|
|
134
|
+
APPROVED = 'approved'
|
|
135
|
+
ACTIVE = 'active'
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class GenericRegistrationStage():
|
|
139
|
+
def __init__(self, dut, **kwargs):
|
|
140
|
+
self.__dict__.update(kwargs)
|
|
141
|
+
self.dut = dut
|
|
142
|
+
self.start_time = None
|
|
143
|
+
self.duration = datetime.timedelta(0)
|
|
144
|
+
self.report = ''
|
|
145
|
+
self.error_summary = ''
|
|
146
|
+
|
|
147
|
+
def calc_run_duration(self):
|
|
148
|
+
self.duration = datetime.datetime.now() - self.start_time
|
|
149
|
+
|
|
150
|
+
def add_report_header(self):
|
|
151
|
+
self.report += f'This phase {(self.stage_tooltip.lower())}.\n'
|
|
152
|
+
self.report += '-' * 50 + '\n'
|
|
153
|
+
|
|
154
|
+
def get_gateway_field(self, field: GetGwField):
|
|
155
|
+
temp = get_gateway(self.dut)
|
|
156
|
+
return temp[field.value]
|
|
157
|
+
|
|
158
|
+
def kick_gw_from_mqtt(self):
|
|
159
|
+
response = kick_gw_from_mqtt(self.dut)
|
|
160
|
+
print(f"Kick response:{response}")
|
|
161
|
+
|
|
162
|
+
def validate_kong_logs(self, endpoint: Literal['device-authorize', 'registry', 'token', 'refresh']):
|
|
163
|
+
message = get_kong_logs(self.dut)
|
|
164
|
+
status_code = message.get('status_code')
|
|
165
|
+
if status_code == 404:
|
|
166
|
+
response_data = message.get('message')
|
|
167
|
+
if 'not found' in response_data:
|
|
168
|
+
print("Could not find gw when requesting for logs.")
|
|
169
|
+
print("Either it is not registered, didn't issue any requests, or is missing the X-Gateway-ID header.")
|
|
170
|
+
return False
|
|
171
|
+
else:
|
|
172
|
+
raise Exception(f'Failed getting kong logs: {response_data}')
|
|
173
|
+
if isinstance(message, dict) and message.get('status_code') != 200:
|
|
174
|
+
print(f"Failed fetching logs, status_code:{message.get('status_code')}")
|
|
175
|
+
return False
|
|
176
|
+
|
|
177
|
+
# Convert datetime.datetime.now() format to epoch in MS
|
|
178
|
+
stage_start_ts = self.start_time.timestamp() * 1000 - STAGE_START_DELAY_MS
|
|
179
|
+
|
|
180
|
+
for log in message['data']:
|
|
181
|
+
if log['timestamp'] > stage_start_ts and endpoint in log['endpoint']:
|
|
182
|
+
response_code = log['responseCode']
|
|
183
|
+
if response_code != 200:
|
|
184
|
+
print(f"An HTTP request to /{endpoint} resulted in an invalid response code:{response_code}")
|
|
185
|
+
else:
|
|
186
|
+
print(f"A valid HTTP request to /{endpoint} was received")
|
|
187
|
+
return True
|
|
188
|
+
|
|
189
|
+
print(f"No valid HTTP request to /{endpoint} was found")
|
|
190
|
+
return False
|
|
191
|
+
|
|
192
|
+
def prepare_stage(self):
|
|
193
|
+
pass
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class Registry(GenericRegistrationStage):
|
|
197
|
+
def __init__(self, **kwargs):
|
|
198
|
+
self.__dict__.update(kwargs)
|
|
199
|
+
self.stage_tooltip = "Validate the gateway's registry step"
|
|
200
|
+
super().__init__(name=type(self).__name__, **self.__dict__)
|
|
201
|
+
|
|
202
|
+
def prepare_stage(self):
|
|
203
|
+
print('Pre-registering the gateway, please make sure it is not registered to any other account '
|
|
204
|
+
'and that your device is ready to run the registration flow')
|
|
205
|
+
|
|
206
|
+
def pre_register_gw_anew(gw_id):
|
|
207
|
+
pre_registered, message = register_gateway([gw_id])
|
|
208
|
+
status_code = message.get('status_code')
|
|
209
|
+
if status_code == 400:
|
|
210
|
+
response_data = message.get('message')
|
|
211
|
+
if 'already exists' in response_data:
|
|
212
|
+
print(f'{gw_id} already exists in Wiliot platform! Deleting and pre-registering from scratch')
|
|
213
|
+
self.kick_gw_from_mqtt()
|
|
214
|
+
delete_gateway(gw_id)
|
|
215
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
216
|
+
pre_registered, message = register_gateway([gw_id])
|
|
217
|
+
if status_code == 403:
|
|
218
|
+
raise Exception(f"The API key within {REGISTRATION_API_KEY_ENV_VAR} seems invalid."
|
|
219
|
+
" It is not authorized to pre-register the gateway")
|
|
220
|
+
return pre_registered, message
|
|
221
|
+
|
|
222
|
+
pre_registered, message = pre_register_gw_anew(self.dut)
|
|
223
|
+
if not pre_registered:
|
|
224
|
+
print(f'Failed pre-registering the gateway. HTTP response:\n{message}')
|
|
225
|
+
raise Exception("Failed pre-registering the gateway. Make sure: Your API key is valid,"
|
|
226
|
+
" and you have a stable internet connection. Otherwise, try again later.")
|
|
227
|
+
print(f"{self.dut} was pre-registered successfully")
|
|
228
|
+
|
|
229
|
+
def run(self):
|
|
230
|
+
self.start_time = datetime.datetime.now()
|
|
231
|
+
print("Waiting for the gateway to finish the Registry step..")
|
|
232
|
+
timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT_MINUTES)
|
|
233
|
+
self.status = self.get_gateway_field(GetGwField.STATUS)
|
|
234
|
+
while datetime.datetime.now() < timeout and not any(self.status == s.value for s in {Status.APPROVED, Status.ACTIVE}):
|
|
235
|
+
time.sleep(BUSY_WAIT_DELAY_SEC)
|
|
236
|
+
self.status = self.get_gateway_field(GetGwField.STATUS)
|
|
237
|
+
|
|
238
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
239
|
+
self.validate_kong_logs('device-authorize')
|
|
240
|
+
self.validate_kong_logs('registry')
|
|
241
|
+
self.calc_run_duration()
|
|
242
|
+
|
|
243
|
+
def generate_stage_report(self):
|
|
244
|
+
self.add_report_header()
|
|
245
|
+
if not any(self.status == s.value for s in {Status.APPROVED, Status.ACTIVE}):
|
|
246
|
+
self.error_summary = ERROR_NO_REGISTER
|
|
247
|
+
self.report += f'{ERROR_NO_REGISTER}\n'
|
|
248
|
+
print(f"The gateway failed to register. Its status is '{self.status}' while it is expected to be '{Status.APPROVED.value}'.")
|
|
249
|
+
self.report += "There was an error in the Device-authorize or Registry steps.\n"
|
|
250
|
+
self.report += f"Please go over the Device-authorize and Registry sections in this document:\n{GW_REGISTER_DOC}\n"
|
|
251
|
+
if self.status == Status.REGISTERED:
|
|
252
|
+
self.report += "Highly likely that the gateway is missing the 'X-Gateway-ID' header in it's HTTP requests.\n"
|
|
253
|
+
return False
|
|
254
|
+
else:
|
|
255
|
+
self.report += "Device-authorize and Registry requests were issued well.\n"
|
|
256
|
+
self.report += "Gateway registered successfully.\n"
|
|
257
|
+
print("Gateway registered successfully")
|
|
258
|
+
return True
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class Online(GenericRegistrationStage):
|
|
262
|
+
def __init__(self, **kwargs):
|
|
263
|
+
self.__dict__.update(kwargs)
|
|
264
|
+
self.stage_tooltip = "Validate the gateway become online on the platform"
|
|
265
|
+
super().__init__(name=type(self).__name__, **self.__dict__)
|
|
266
|
+
|
|
267
|
+
def run(self):
|
|
268
|
+
self.start_time = datetime.datetime.now()
|
|
269
|
+
print("Waiting for the gateway to connect to MQTT..")
|
|
270
|
+
timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT_MINUTES)
|
|
271
|
+
self.online = self.get_gateway_field(GetGwField.ONLINE)
|
|
272
|
+
while datetime.datetime.now() < timeout and self.online is not True:
|
|
273
|
+
time.sleep(BUSY_WAIT_DELAY_SEC)
|
|
274
|
+
self.online = self.get_gateway_field(GetGwField.ONLINE)
|
|
275
|
+
|
|
276
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
277
|
+
self.validate_kong_logs('token')
|
|
278
|
+
if self.online:
|
|
279
|
+
global gw_online_ts
|
|
280
|
+
gw_online_ts = datetime.datetime.now()
|
|
281
|
+
self.calc_run_duration()
|
|
282
|
+
|
|
283
|
+
def generate_stage_report(self):
|
|
284
|
+
self.add_report_header()
|
|
285
|
+
if self.online is not True:
|
|
286
|
+
self.error_summary = ERROR_NO_ONLINE
|
|
287
|
+
self.report += f'{ERROR_NO_ONLINE}\n'
|
|
288
|
+
self.report += "Either it didn't acquire a token or it didn't connect to MQTT in time.\n"
|
|
289
|
+
self.report += f"Please go over the Poll For Token section in:\n{GW_REGISTER_DOC}\n"
|
|
290
|
+
self.report += f"and the MQTT details in:\n{GW_MQTT_DOC}\n"
|
|
291
|
+
print("Gateway did not connect to MQTT within time limit")
|
|
292
|
+
return False
|
|
293
|
+
else:
|
|
294
|
+
self.report += "Token acquisition and MQTT connection were done succesfully.\n"
|
|
295
|
+
self.report += "Gateway is online.\n"
|
|
296
|
+
print("Gateway connected to MQTT successfully, it is online")
|
|
297
|
+
return True
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class Refresh(GenericRegistrationStage):
|
|
301
|
+
def __init__(self, **kwargs):
|
|
302
|
+
self.__dict__.update(kwargs)
|
|
303
|
+
self.stage_tooltip = "Validate the gateway refresh-token step"
|
|
304
|
+
super().__init__(name=type(self).__name__, **self.__dict__)
|
|
305
|
+
|
|
306
|
+
def run(self):
|
|
307
|
+
self.start_time = datetime.datetime.now()
|
|
308
|
+
print("Waiting for the token to expire..")
|
|
309
|
+
timeout = gw_online_ts + datetime.timedelta(minutes=TOKEN_EXPIRY_MINUTES)
|
|
310
|
+
while datetime.datetime.now() < timeout:
|
|
311
|
+
time.sleep(BUSY_WAIT_DELAY_SEC)
|
|
312
|
+
|
|
313
|
+
print("Token expired, kicking gateway")
|
|
314
|
+
self.kick_gw_from_mqtt()
|
|
315
|
+
|
|
316
|
+
# Sleep here since it sometimes take time for the cloud to kick and change the gateway's online status
|
|
317
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
318
|
+
print("Waiting for the gateway to refresh its token and connect to MQTT..")
|
|
319
|
+
timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT_MINUTES)
|
|
320
|
+
self.online = self.get_gateway_field(GetGwField.ONLINE)
|
|
321
|
+
while datetime.datetime.now() < timeout and self.online is not True:
|
|
322
|
+
time.sleep(BUSY_WAIT_DELAY_SEC)
|
|
323
|
+
self.online = self.get_gateway_field(GetGwField.ONLINE)
|
|
324
|
+
|
|
325
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
326
|
+
self.validate_kong_logs('refresh')
|
|
327
|
+
self.calc_run_duration()
|
|
328
|
+
|
|
329
|
+
def generate_stage_report(self):
|
|
330
|
+
self.add_report_header()
|
|
331
|
+
if self.online is not True:
|
|
332
|
+
self.error_summary = ERROR_NO_REFRESH
|
|
333
|
+
self.report += f'{ERROR_NO_REFRESH}\n'
|
|
334
|
+
self.report += "Either it didn't refresh its token or it didn't connect to MQTT in time.\n"
|
|
335
|
+
self.report += f"Please go over the Refresh Token section in:\n{GW_REGISTER_DOC}\n"
|
|
336
|
+
self.report += f"and the MQTT details in:\n{GW_MQTT_DOC}\n"
|
|
337
|
+
print("Gateway did not reconnect MQTT (was the token refreshed?)")
|
|
338
|
+
return False
|
|
339
|
+
else:
|
|
340
|
+
self.report += "Token refresh and MQTT reconnection were done succesfully.\n"
|
|
341
|
+
self.report += "Gateway is online.\n"
|
|
342
|
+
return True
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def end_test(dut):
|
|
346
|
+
print(f'Deleting {dut} from {REG_CERT_OWNER_ID} before exiting')
|
|
347
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
348
|
+
delete_gateway(dut)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def prepare_results(stage, phase_pass, skip_stage):
|
|
352
|
+
stage.rc = TEST_SKIPPED if skip_stage else TEST_PASSED if phase_pass else TEST_FAILED
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def run(test: cert_utils.WltTest):
|
|
356
|
+
test = cert_common.test_prolog(test, flush_mqtt=False)
|
|
357
|
+
if test.rc == TEST_FAILED:
|
|
358
|
+
return cert_common.test_epilog(test, flush_mqtt=False)
|
|
359
|
+
|
|
360
|
+
global api_key
|
|
361
|
+
api_key = os.getenv(REGISTRATION_API_KEY_ENV_VAR)
|
|
362
|
+
if api_key is None:
|
|
363
|
+
raise Exception('Must include an apikey')
|
|
364
|
+
|
|
365
|
+
STAGES = [Registry, Online, Refresh]
|
|
366
|
+
phases = {p.name: stage(dut=test.dut.id_str) for p, stage in zip(test.params, STAGES)}
|
|
367
|
+
|
|
368
|
+
for param in test.params:
|
|
369
|
+
phase_run_print(f" - {param.name}")
|
|
370
|
+
phase = phases[param.name]
|
|
371
|
+
phase.prepare_stage()
|
|
372
|
+
phase.run()
|
|
373
|
+
test.rc = TEST_PASSED if phase.generate_stage_report() else TEST_FAILED
|
|
374
|
+
test.set_phase_rc(param.name, test.rc)
|
|
375
|
+
test.add_phase_reason(param.name, phase.error_summary)
|
|
376
|
+
|
|
377
|
+
if test.rc == TEST_FAILED and test.exit_on_param_failure:
|
|
378
|
+
print(f'\nPhase {param.name} failed: {phase.report}')
|
|
379
|
+
break
|
|
380
|
+
test.reset_result() # reset result and continue to next param
|
|
381
|
+
|
|
382
|
+
end_test(test.dut.id_str)
|
|
383
|
+
|
|
384
|
+
return cert_common.test_epilog(test, flush_mqtt=False)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
|
|
2
|
+
import datetime
|
|
3
|
+
from argparse import ArgumentParser
|
|
4
|
+
import os
|
|
5
|
+
import traceback
|
|
6
|
+
import webbrowser
|
|
7
|
+
import tabulate
|
|
8
|
+
|
|
9
|
+
from certificate.cert_defines import CERT_VERSION, TEST_FAILED, TEST_PASSED, TEST_SKIPPED
|
|
10
|
+
from certificate.cert_prints import *
|
|
11
|
+
import certificate.cert_common as cert_common
|
|
12
|
+
import certificate.cert_utils as cert_utils
|
|
13
|
+
import certificate.cert_results as cert_results
|
|
14
|
+
|
|
15
|
+
import certificate.tests.cloud_connectivity.registration_test.registration_test as registration_test
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# HELPER DEFINES
|
|
19
|
+
TEST_LINE = "cloud_connectivity/registration_test registry online refresh"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RegTestCli:
|
|
23
|
+
"""Registration Test CLI."""
|
|
24
|
+
def __init__(self):
|
|
25
|
+
usage = ("wlt-reg-test [-h] -dut <GWID> -ak <API_KEY>\n")
|
|
26
|
+
|
|
27
|
+
self.parser = ArgumentParser(prog='wlt-reg-test',
|
|
28
|
+
description=f'Registration Test v{CERT_VERSION}', usage=usage)
|
|
29
|
+
|
|
30
|
+
self.required = self.parser.add_argument_group('required arguments')
|
|
31
|
+
self.required.add_argument('--dut', type=str, help="Gateway ID", required=True)
|
|
32
|
+
self.required.add_argument('--apikey', '-ak', type=str, help="API key provided by Wiliot", required=True)
|
|
33
|
+
|
|
34
|
+
def parse_args(self, args=None):
|
|
35
|
+
"""Parse arguments and return them."""
|
|
36
|
+
return self.parser.parse_args(args)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def prepare_results(stage, phase_pass, skip_stage):
|
|
40
|
+
stage.rc = TEST_SKIPPED if skip_stage else TEST_PASSED if phase_pass else TEST_FAILED
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def main():
|
|
44
|
+
cli = RegTestCli()
|
|
45
|
+
args = cli.parse_args()
|
|
46
|
+
|
|
47
|
+
os.environ[registration_test.REGISTRATION_API_KEY_ENV_VAR] = f"{args.apikey}"
|
|
48
|
+
|
|
49
|
+
start_time = datetime.datetime.now()
|
|
50
|
+
dut = cert_utils.Gateway(id_str=args.dut)
|
|
51
|
+
|
|
52
|
+
test = cert_utils.WltTest(TEST_LINE, '', dut, exit_on_param_failure=True)
|
|
53
|
+
tests = [test]
|
|
54
|
+
|
|
55
|
+
# Running the tests
|
|
56
|
+
utPrint(SEP)
|
|
57
|
+
utPrint("\n - ".join([f"\nRunning {len(tests)} tests:"] +
|
|
58
|
+
[t.name if not t.internal_brg else f"{t.name} (internal brg)" for t in tests]))
|
|
59
|
+
|
|
60
|
+
failures, skipped = 0, 0
|
|
61
|
+
i = 0
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
test_module_name = cert_utils.load_module(f'{test.module_name}.py', f'{test.dir}/{test.module_name}.py')
|
|
65
|
+
test = test_module_name.run(test)
|
|
66
|
+
except Exception as e:
|
|
67
|
+
traceback.print_exc()
|
|
68
|
+
test.add_phase_reason(RESTORE_CONFIG, f"Exception occurred: {e!r}")
|
|
69
|
+
test.rc = TEST_FAILED
|
|
70
|
+
finally:
|
|
71
|
+
test.update_overall_rc()
|
|
72
|
+
if test.rc == TEST_FAILED:
|
|
73
|
+
failures += 1
|
|
74
|
+
print(f"Test Duration: {test.duration}")
|
|
75
|
+
print(tabulate.tabulate([[i + 1, i + 1 - (failures + skipped), skipped, failures, len(tests)]],
|
|
76
|
+
headers=["FINISHED", "PASSED", "SKIPPED", "FAILED", "TOTAL"], tablefmt="pretty"))
|
|
77
|
+
cert_common.wait_time_n_print(2)
|
|
78
|
+
|
|
79
|
+
# Print results
|
|
80
|
+
cert_results.generate_results_files(html=True, pdf=True, failures=failures,
|
|
81
|
+
skipped=skipped, start_time=start_time, tests=tests)
|
|
82
|
+
if not pipeline_running():
|
|
83
|
+
webbrowser.open('file://' + os.path.realpath(os.path.join(ARTIFACTS_DIR, UT_RESULT_FILE_PDF)))
|
|
84
|
+
|
|
85
|
+
if failures:
|
|
86
|
+
sys.exit(-1)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
if __name__ == '__main__':
|
|
90
|
+
main()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Gateway Uplink Stress",
|
|
3
|
+
"module": "Cloud Connectivity",
|
|
4
|
+
"purpose": "Test gateway's stress handling capabilities for different rates and durations",
|
|
5
|
+
"documentation": "https://community.wiliot.com/customers/s/article/Sending-Wiliot-Packets-to-the-Wiliot-Cloud",
|
|
6
|
+
"initialCondition": "Gateway configured to defaults, in a BLE-clean environment",
|
|
7
|
+
"procedure": ["Test prolog",
|
|
8
|
+
"For each pps value, advertise packets at that rate, once on each of the three BLE advertising channels, and compare the advertised vs uploaded rate",
|
|
9
|
+
"Test epilog"],
|
|
10
|
+
"expectedOutcome": "Find the maximum PPS supported by the gateway",
|
|
11
|
+
"mandatory": 1,
|
|
12
|
+
"multiBridgeTest": 0,
|
|
13
|
+
"gwOnlyTest": 1,
|
|
14
|
+
"dataSimOnlyTest": 1,
|
|
15
|
+
"SupportedFromApiVersion": 203,
|
|
16
|
+
"allSupportedValues": []
|
|
17
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
|
|
2
|
+
from certificate.cert_prints import *
|
|
3
|
+
from certificate.cert_defines import *
|
|
4
|
+
from certificate.wlt_types import *
|
|
5
|
+
from certificate.ag.wlt_types_ag import OUTPUT_POWER_2_4_MAX
|
|
6
|
+
import certificate.cert_common as cert_common
|
|
7
|
+
import certificate.cert_utils as cert_utils
|
|
8
|
+
import certificate.cert_mqtt as cert_mqtt
|
|
9
|
+
import certificate.cert_config as cert_config
|
|
10
|
+
import certificate.cert_gw_sim as cert_gw_sim
|
|
11
|
+
import math
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# DEFINES
|
|
15
|
+
STRESS_TEST_INDICATOR = get_random_hex_str(6)
|
|
16
|
+
|
|
17
|
+
DUPLICATES = 1
|
|
18
|
+
ADVA_ASCII_LEN = 12
|
|
19
|
+
|
|
20
|
+
LOWEST_PPS = 20
|
|
21
|
+
ADV_DURATION_LOWEST_PPS = 50
|
|
22
|
+
ADV_DURATION_DEFAULT = 30
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# HELPER FUNCTIONS
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def generate_adv_payloads_list(payload, duplicates):
|
|
29
|
+
"""
|
|
30
|
+
Should always stay synced to how cmd_ble_sim generate additional packets with unique_pkts_count
|
|
31
|
+
"""
|
|
32
|
+
payload_start = payload[:-8]
|
|
33
|
+
last_hex = payload[-8:]
|
|
34
|
+
last_int = int.from_bytes(bytes.fromhex(last_hex), byteorder='little', signed=False)
|
|
35
|
+
|
|
36
|
+
pkts_list = []
|
|
37
|
+
for i in range(duplicates):
|
|
38
|
+
value = last_int + i
|
|
39
|
+
# Convert back to 4 bytes in little-endian and then to hex
|
|
40
|
+
new_hex = value.to_bytes(4, byteorder='little', signed=False).hex().upper()
|
|
41
|
+
|
|
42
|
+
pkts_list.append(payload_start + new_hex)
|
|
43
|
+
|
|
44
|
+
return pkts_list
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def run(test):
|
|
48
|
+
test = cert_common.test_prolog(test)
|
|
49
|
+
if test.rc == TEST_FAILED:
|
|
50
|
+
return cert_common.test_epilog(test)
|
|
51
|
+
|
|
52
|
+
cert_config.gw_action(test, f'{cert_gw_sim.BLE_SIM_INIT} 1', TESTER)
|
|
53
|
+
ppses = [20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 222, 250, 285, 333, 500]
|
|
54
|
+
test_pkts_received = []
|
|
55
|
+
data_pkts_received = []
|
|
56
|
+
results = []
|
|
57
|
+
for pps in ppses:
|
|
58
|
+
phase_run_print(f"PPS = {pps}")
|
|
59
|
+
test.flush_all_mqtt_packets()
|
|
60
|
+
# adv_duration is increased only for lowest pps to increase packets sample for reliable results
|
|
61
|
+
adv_duration = ADV_DURATION_LOWEST_PPS if pps == LOWEST_PPS else ADV_DURATION_DEFAULT
|
|
62
|
+
delay = math.floor(1000 / pps)
|
|
63
|
+
upload_wait_time = test.dut.upload_wait_time + 15
|
|
64
|
+
|
|
65
|
+
# Generate pkts and get ready to advertise
|
|
66
|
+
payload = cert_common.generate_adv_payload(STRESS_TEST_INDICATOR)
|
|
67
|
+
generated_payloads = generate_adv_payloads_list(payload, adv_duration * pps)
|
|
68
|
+
|
|
69
|
+
# We provide the tester with the first pkt only. It then advertises in a loop pkts identical
|
|
70
|
+
# to the ones we generated (by incrementing the last bytes).
|
|
71
|
+
cert_config.gw_action(test, f'{cert_gw_sim.BLE_SIM} {generated_payloads[0]} {DUPLICATES} {OUTPUT_POWER_2_4_MAX} '
|
|
72
|
+
f'{BLE_SIM_ADV_37_38_39} {delay} {BLE_SIM_RADIO_1MBPS} {adv_duration * pps}', TESTER)
|
|
73
|
+
mqtt_scan_wait(test, adv_duration + upload_wait_time)
|
|
74
|
+
|
|
75
|
+
cert_mqtt.dump_pkts(test, log=str(pps))
|
|
76
|
+
phase_pkts_received = cert_mqtt.get_all_data_pkts(test.get_mqttc_by_target(DUT), indicator=STRESS_TEST_INDICATOR)
|
|
77
|
+
test.add_phase(cert_utils.Phase(pps))
|
|
78
|
+
valid, reason = cert_common.validate_received_packets(phase_pkts_received)
|
|
79
|
+
if valid is False:
|
|
80
|
+
test.set_phase_rc(str(pps), TEST_FAILED)
|
|
81
|
+
test.add_phase_reason(str(pps), reason)
|
|
82
|
+
utPrint(f"Phase {pps} failed validation: {reason}", "RED")
|
|
83
|
+
continue
|
|
84
|
+
phase_pkts_received = [p[PAYLOAD] for p in phase_pkts_received]
|
|
85
|
+
test, received_pps = cert_common.stress_analysis(test, pps, generated_payloads, phase_pkts_received)
|
|
86
|
+
results.extend([pps, received_pps])
|
|
87
|
+
cert_mqtt.generate_log_file(test, str(pps))
|
|
88
|
+
|
|
89
|
+
if test.rc == TEST_FAILED and test.exit_on_param_failure:
|
|
90
|
+
break # break the whole for loop and keep the test as failed
|
|
91
|
+
test.reset_result() # reset result and continue to next param
|
|
92
|
+
data_pkts_received.extend(cert_mqtt.get_all_data_pkts(test.get_mqttc_by_target(DUT)))
|
|
93
|
+
test_pkts_received.extend(test.get_mqttc_by_target(DUT)._userdata[PKTS].data)
|
|
94
|
+
cert_config.gw_action(test, f'{cert_gw_sim.BLE_SIM_INIT} 0', TESTER)
|
|
95
|
+
|
|
96
|
+
if len(data_pkts_received) > 0:
|
|
97
|
+
cert_common.generate_graph_stress_test(test, results, data_pkts_received)
|
|
98
|
+
else:
|
|
99
|
+
utPrint("No data packets received - skipping graph generation", "RED")
|
|
100
|
+
|
|
101
|
+
return cert_common.test_epilog(test)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Gateway Uplink Extended Advertising",
|
|
3
|
+
"module": "Cloud Connectivity",
|
|
4
|
+
"purpose": "Verify gateway BLE scans and MQTT uplinks in Extended Advertising mode",
|
|
5
|
+
"documentation": "https://community.wiliot.com/customers/s/article/Wiliot-Network---Gateway-Extended-Advertising-Implementation",
|
|
6
|
+
"initialCondition": "Gateway configured to defaults",
|
|
7
|
+
"procedure": [
|
|
8
|
+
"Test prolog",
|
|
9
|
+
"Enable GW CERT TESTER to allow TESTER transmit extended advertising packets",
|
|
10
|
+
"Configure TESTER datapath pattern to Extended Advertising (DATAPATH_PATTERN_EXTENDED_ADV)",
|
|
11
|
+
"Flush MQTT packets; generate pixel packets with 31-byte payload and send via GenericSimThread (single cycle)",
|
|
12
|
+
"Wait for MQTT scan (≈20s)",
|
|
13
|
+
"Analyze: each 31-byte payload must be expanded to aggregated 217 bytes (31×7) and repeated 7 times; validate ≥80% of expected payloads received",
|
|
14
|
+
"Restore TESTER datapath defaults and disable GW CERT TESTER",
|
|
15
|
+
"Generate log and pass/fail summary",
|
|
16
|
+
"Test epilog"
|
|
17
|
+
],
|
|
18
|
+
"expectedOutcome": "Received amount of aggregated packets matches the expected amount and all additional validations pass as expected",
|
|
19
|
+
"mandatory": 0,
|
|
20
|
+
"multiBridgeTest": 0,
|
|
21
|
+
"gwOnlyTest": 1,
|
|
22
|
+
"dataSimOnlyTest": 1,
|
|
23
|
+
"SupportedFromApiVersion": 206,
|
|
24
|
+
"allSupportedValues": []
|
|
25
|
+
}
|