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.
Files changed (297) hide show
  1. {brg_certificate → certificate}/ag/wlt_cmd_if.html +10 -4
  2. {brg_certificate → certificate}/ag/wlt_types_ag.py +1878 -519
  3. certificate/cert_common.py +1488 -0
  4. certificate/cert_config.py +480 -0
  5. {brg_certificate → certificate}/cert_data_sim.py +134 -46
  6. {brg_certificate → certificate}/cert_defines.py +129 -128
  7. {brg_certificate → certificate}/cert_gw_sim.py +183 -53
  8. {brg_certificate → certificate}/cert_mqtt.py +179 -64
  9. {brg_certificate → certificate}/cert_prints.py +35 -33
  10. {brg_certificate → certificate}/cert_protobuf.py +15 -6
  11. {brg_certificate → certificate}/cert_results.py +240 -64
  12. certificate/cert_utils.py +634 -0
  13. certificate/certificate.py +205 -0
  14. certificate/certificate_cli.py +76 -0
  15. certificate/certificate_eth_test_list.txt +76 -0
  16. certificate/certificate_sanity_test_list.txt +66 -0
  17. certificate/certificate_test_list.txt +76 -0
  18. {brg_certificate → certificate}/tests/calibration/interval_test/interval_test.json +3 -2
  19. {brg_certificate → certificate}/tests/calibration/interval_test/interval_test.py +7 -6
  20. certificate/tests/calibration/output_power_test/output_power_test.json +23 -0
  21. certificate/tests/calibration/output_power_test/output_power_test.py +39 -0
  22. {brg_certificate → certificate}/tests/calibration/pattern_test/pattern_test.json +2 -1
  23. {brg_certificate → certificate}/tests/calibration/pattern_test/pattern_test.py +20 -15
  24. certificate/tests/cloud_connectivity/acl_ext_adv_test/acl_ext_adv_test.json +15 -0
  25. certificate/tests/cloud_connectivity/acl_ext_adv_test/acl_ext_adv_test.py +140 -0
  26. certificate/tests/cloud_connectivity/acl_test/acl_test.json +15 -0
  27. certificate/tests/cloud_connectivity/acl_test/acl_test.py +96 -0
  28. certificate/tests/cloud_connectivity/brg_ota_test/brg_ota_test.json +19 -0
  29. certificate/tests/cloud_connectivity/brg_ota_test/brg_ota_test.py +41 -0
  30. certificate/tests/cloud_connectivity/channel_scan_behaviour_test/channel_scan_behaviour_test.json +19 -0
  31. certificate/tests/cloud_connectivity/channel_scan_behaviour_test/channel_scan_behaviour_test.py +215 -0
  32. certificate/tests/cloud_connectivity/connection_test/connection_test.json +18 -0
  33. certificate/tests/cloud_connectivity/connection_test/connection_test.py +67 -0
  34. certificate/tests/cloud_connectivity/deduplication_test/deduplication_test.json +15 -0
  35. certificate/tests/cloud_connectivity/deduplication_test/deduplication_test.py +80 -0
  36. certificate/tests/cloud_connectivity/downlink_test/downlink_test.json +21 -0
  37. certificate/tests/cloud_connectivity/downlink_test/downlink_test.py +201 -0
  38. certificate/tests/cloud_connectivity/ext_adv_stress_test/ext_adv_stress_test.json +17 -0
  39. certificate/tests/cloud_connectivity/ext_adv_stress_test/ext_adv_stress_test.py +104 -0
  40. certificate/tests/cloud_connectivity/reboot_test/reboot_test.json +18 -0
  41. certificate/tests/cloud_connectivity/reboot_test/reboot_test.py +59 -0
  42. certificate/tests/cloud_connectivity/registration_test/registration_test.json +20 -0
  43. certificate/tests/cloud_connectivity/registration_test/registration_test.py +384 -0
  44. certificate/tests/cloud_connectivity/registration_test/registration_test_cli.py +90 -0
  45. certificate/tests/cloud_connectivity/stress_test/stress_test.json +17 -0
  46. certificate/tests/cloud_connectivity/stress_test/stress_test.py +101 -0
  47. certificate/tests/cloud_connectivity/uplink_ext_adv_test/uplink_ext_adv_test.json +25 -0
  48. certificate/tests/cloud_connectivity/uplink_ext_adv_test/uplink_ext_adv_test.py +92 -0
  49. certificate/tests/cloud_connectivity/uplink_test/uplink_test.json +20 -0
  50. certificate/tests/cloud_connectivity/uplink_test/uplink_test.py +169 -0
  51. {brg_certificate → certificate}/tests/datapath/aging_test/aging_test.json +2 -1
  52. certificate/tests/datapath/aging_test/aging_test.py +142 -0
  53. certificate/tests/datapath/event_ble5_test/event_ble5_test.json +17 -0
  54. certificate/tests/datapath/event_ble5_test/event_ble5_test.py +89 -0
  55. certificate/tests/datapath/event_test/event_test.json +17 -0
  56. certificate/tests/datapath/event_test/event_test.py +80 -0
  57. {brg_certificate → certificate}/tests/datapath/num_of_tags_test/num_of_tags_test.json +4 -3
  58. {brg_certificate → certificate}/tests/datapath/num_of_tags_test/num_of_tags_test.py +19 -13
  59. certificate/tests/datapath/output_power_test/output_power_test.json +23 -0
  60. {brg_certificate → certificate}/tests/datapath/output_power_test/output_power_test.py +17 -6
  61. {brg_certificate → certificate}/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.json +2 -1
  62. {brg_certificate → certificate}/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.py +13 -11
  63. {brg_certificate → certificate}/tests/datapath/pacer_interval_test/pacer_interval_test.json +2 -1
  64. {brg_certificate → certificate}/tests/datapath/pacer_interval_test/pacer_interval_test.py +9 -7
  65. {brg_certificate → certificate}/tests/datapath/pattern_test/pattern_test.json +3 -2
  66. {brg_certificate → certificate}/tests/datapath/pattern_test/pattern_test.py +18 -6
  67. certificate/tests/datapath/pkt_filter_ble5_chl21_test/pkt_filter_ble5_chl21_test.json +20 -0
  68. certificate/tests/datapath/pkt_filter_ble5_chl21_test/pkt_filter_ble5_chl21_test.py +61 -0
  69. {brg_certificate → certificate}/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.json +2 -1
  70. {brg_certificate → certificate}/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.py +15 -14
  71. certificate/tests/datapath/pkt_filter_brg2gw_ext_adv_test/pkt_filter_brg2gw_ext_adv_test.json +19 -0
  72. certificate/tests/datapath/pkt_filter_brg2gw_ext_adv_test/pkt_filter_brg2gw_ext_adv_test.py +85 -0
  73. {brg_certificate → certificate}/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.json +2 -1
  74. {brg_certificate → certificate}/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.py +10 -9
  75. {brg_certificate → certificate}/tests/datapath/pkt_filter_test/pkt_filter_test.json +2 -1
  76. {brg_certificate → certificate}/tests/datapath/pkt_filter_test/pkt_filter_test.py +10 -9
  77. {brg_certificate → certificate}/tests/datapath/rssi_threshold_test/rssi_threshold_test.json +3 -2
  78. {brg_certificate → certificate}/tests/datapath/rssi_threshold_test/rssi_threshold_test.py +9 -8
  79. 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
  80. certificate/tests/datapath/rx_channel_hopping_test/rx_channel_hopping_test.py +77 -0
  81. {brg_certificate → certificate}/tests/datapath/rx_channel_test/rx_channel_test.json +3 -2
  82. {brg_certificate → certificate}/tests/datapath/rx_channel_test/rx_channel_test.py +7 -6
  83. {brg_certificate → certificate}/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.json +8 -7
  84. {brg_certificate → certificate}/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.py +113 -73
  85. {brg_certificate → certificate}/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.json +8 -7
  86. {brg_certificate → certificate}/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.py +112 -72
  87. {brg_certificate → certificate}/tests/datapath/stress_gen3_test/stress_gen3_test.json +4 -3
  88. {brg_certificate → certificate}/tests/datapath/stress_gen3_test/stress_gen3_test.py +15 -11
  89. {brg_certificate → certificate}/tests/datapath/stress_test/stress_test.json +4 -3
  90. {brg_certificate → certificate}/tests/datapath/stress_test/stress_test.py +15 -11
  91. {brg_certificate → certificate}/tests/datapath/tx_repetition_test/tx_repetition_test.json +3 -1
  92. {brg_certificate → certificate}/tests/datapath/tx_repetition_test/tx_repetition_test.py +14 -13
  93. certificate/tests/edge_mgmt/action_blink_test/action_blink_test.json +15 -0
  94. certificate/tests/edge_mgmt/action_blink_test/action_blink_test.py +24 -0
  95. certificate/tests/edge_mgmt/action_get_battery_sensor_test/action_get_battery_sensor_test.json +15 -0
  96. certificate/tests/edge_mgmt/action_get_battery_sensor_test/action_get_battery_sensor_test.py +43 -0
  97. certificate/tests/edge_mgmt/action_get_module_test/action_get_module_test.json +15 -0
  98. certificate/tests/edge_mgmt/action_get_module_test/action_get_module_test.py +42 -0
  99. certificate/tests/edge_mgmt/action_get_pof_data_test/action_get_pof_data_test.json +15 -0
  100. certificate/tests/edge_mgmt/action_get_pof_data_test/action_get_pof_data_test.py +44 -0
  101. certificate/tests/edge_mgmt/action_gw_hb_test/action_gw_hb_test.json +16 -0
  102. certificate/tests/edge_mgmt/action_gw_hb_test/action_gw_hb_test.py +42 -0
  103. certificate/tests/edge_mgmt/action_reboot_test/action_reboot_test.json +15 -0
  104. certificate/tests/edge_mgmt/action_reboot_test/action_reboot_test.py +49 -0
  105. certificate/tests/edge_mgmt/action_restore_defaults_test/action_restore_defaults_test.json +15 -0
  106. certificate/tests/edge_mgmt/action_restore_defaults_test/action_restore_defaults_test.py +102 -0
  107. certificate/tests/edge_mgmt/action_send_hb_test/action_send_hb_test.json +15 -0
  108. certificate/tests/edge_mgmt/action_send_hb_test/action_send_hb_test.py +45 -0
  109. {brg_certificate → certificate}/tests/edge_mgmt/periodic_msgs_test/periodic_msgs_test.json +3 -2
  110. {brg_certificate → certificate}/tests/edge_mgmt/periodic_msgs_test/periodic_msgs_test.py +22 -11
  111. {brg_certificate → certificate}/tests/energy2400/duty_cycle_test/duty_cycle_test.json +2 -1
  112. {brg_certificate → certificate}/tests/energy2400/duty_cycle_test/duty_cycle_test.py +7 -6
  113. certificate/tests/energy2400/output_power_test/output_power_test.json +23 -0
  114. {brg_certificate → certificate}/tests/energy2400/output_power_test/output_power_test.py +17 -6
  115. {brg_certificate → certificate}/tests/energy2400/pattern_test/pattern_test.json +2 -1
  116. {brg_certificate → certificate}/tests/energy2400/pattern_test/pattern_test.py +7 -6
  117. certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.json +26 -0
  118. certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.py +379 -0
  119. certificate/tests/energy2400/signal_indicator_ext_adv_test/signal_indicator_ext_adv_test.json +20 -0
  120. certificate/tests/energy2400/signal_indicator_ext_adv_test/signal_indicator_ext_adv_test.py +173 -0
  121. certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.json +24 -0
  122. certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.py +350 -0
  123. {brg_certificate → certificate}/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.json +2 -1
  124. {brg_certificate → certificate}/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.py +7 -6
  125. {brg_certificate → certificate}/tests/energy_sub1g/pattern_test/pattern_test.json +2 -1
  126. {brg_certificate → certificate}/tests/energy_sub1g/pattern_test/pattern_test.py +7 -6
  127. {brg_certificate → certificate}/tests/pwr_mgmt/pwr_mgmt_test/pwr_mgmt_test.json +2 -1
  128. {brg_certificate → certificate}/tests/pwr_mgmt/pwr_mgmt_test/pwr_mgmt_test.py +10 -10
  129. {brg_certificate → certificate}/tests/sensors/ext_sensor_test/ext_sensor_test.json +5 -4
  130. certificate/tests/sensors/ext_sensor_test/ext_sensor_test.py +450 -0
  131. certificate/wlt_types.py +122 -0
  132. {gw_certificate → common}/api_if/202/status.json +6 -0
  133. {gw_certificate → common}/api_if/203/status.json +6 -0
  134. {gw_certificate → common}/api_if/204/status.json +6 -0
  135. common/api_if/206/data.json +85 -0
  136. common/api_if/206/status.json +69 -0
  137. common/api_if/api_validation.py +91 -0
  138. common/web/templates/generator.html +210 -0
  139. common/web/templates/index.html +20 -0
  140. common/web/templates/menu.html +54 -0
  141. common/web/templates/parser.html +53 -0
  142. {brg_certificate/ag → common/web/templates}/wlt_types.html +1216 -191
  143. common/web/web_utils.py +399 -0
  144. {brg_certificate → common}/wltPb_pb2.py +14 -12
  145. {gw_certificate/common → common}/wltPb_pb2.pyi +16 -2
  146. gui_certificate/gui_certificate_cli.py +14 -0
  147. gui_certificate/server.py +1267 -0
  148. gui_certificate/templates/cert_run.html +1273 -0
  149. wiliot_certificate-4.5.0.dist-info/METADATA +99 -0
  150. wiliot_certificate-4.5.0.dist-info/RECORD +168 -0
  151. {wiliot_certificate-4.4.2.dist-info → wiliot_certificate-4.5.0.dist-info}/WHEEL +1 -1
  152. wiliot_certificate-4.5.0.dist-info/entry_points.txt +5 -0
  153. wiliot_certificate-4.5.0.dist-info/top_level.txt +3 -0
  154. brg_certificate/ag/energous_v0_defines.py +0 -925
  155. brg_certificate/ag/energous_v1_defines.py +0 -931
  156. brg_certificate/ag/energous_v2_defines.py +0 -925
  157. brg_certificate/ag/energous_v3_defines.py +0 -925
  158. brg_certificate/ag/energous_v4_defines.py +0 -925
  159. brg_certificate/ag/fanstel_lan_v0_defines.py +0 -925
  160. brg_certificate/ag/fanstel_lte_v0_defines.py +0 -925
  161. brg_certificate/ag/fanstel_wifi_v0_defines.py +0 -925
  162. brg_certificate/ag/minew_lte_v0_defines.py +0 -925
  163. brg_certificate/ag/wlt_types_ag_jsons/brg2brg_ota.json +0 -142
  164. brg_certificate/ag/wlt_types_ag_jsons/brg2gw_hb.json +0 -785
  165. brg_certificate/ag/wlt_types_ag_jsons/brg2gw_hb_sleep.json +0 -139
  166. brg_certificate/ag/wlt_types_ag_jsons/calibration.json +0 -394
  167. brg_certificate/ag/wlt_types_ag_jsons/custom.json +0 -515
  168. brg_certificate/ag/wlt_types_ag_jsons/datapath.json +0 -672
  169. brg_certificate/ag/wlt_types_ag_jsons/energy2400.json +0 -550
  170. brg_certificate/ag/wlt_types_ag_jsons/energySub1g.json +0 -595
  171. brg_certificate/ag/wlt_types_ag_jsons/externalSensor.json +0 -598
  172. brg_certificate/ag/wlt_types_ag_jsons/interface.json +0 -938
  173. brg_certificate/ag/wlt_types_ag_jsons/powerManagement.json +0 -1234
  174. brg_certificate/ag/wlt_types_ag_jsons/side_info_sensor.json +0 -105
  175. brg_certificate/ag/wlt_types_ag_jsons/signal_indicator_data.json +0 -77
  176. brg_certificate/ag/wlt_types_ag_jsons/unified_echo_ext_pkt.json +0 -61
  177. brg_certificate/ag/wlt_types_ag_jsons/unified_echo_pkt.json +0 -110
  178. brg_certificate/brg_certificate.py +0 -225
  179. brg_certificate/brg_certificate_cli.py +0 -63
  180. brg_certificate/cert_common.py +0 -923
  181. brg_certificate/cert_config.py +0 -402
  182. brg_certificate/cert_utils.py +0 -362
  183. brg_certificate/certificate_bcc_sanity_test_list.txt +0 -40
  184. brg_certificate/certificate_bcc_test_list.txt +0 -48
  185. brg_certificate/certificate_sanity_test_list.txt +0 -43
  186. brg_certificate/certificate_test_list.txt +0 -53
  187. brg_certificate/config/eclipse.json +0 -10
  188. brg_certificate/config/hivemq.json +0 -10
  189. brg_certificate/config/mosquitto.json +0 -10
  190. brg_certificate/config/mosquitto.md +0 -95
  191. brg_certificate/config/wiliot-dev.json +0 -10
  192. brg_certificate/restore_brg.py +0 -61
  193. brg_certificate/tests/calibration/output_power_test/output_power_test.json +0 -16
  194. brg_certificate/tests/calibration/output_power_test/output_power_test.py +0 -28
  195. brg_certificate/tests/datapath/aging_test/aging_test.py +0 -143
  196. brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.json +0 -16
  197. brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.py +0 -73
  198. brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.json +0 -17
  199. brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.py +0 -118
  200. brg_certificate/tests/edge_mgmt/actions_test/actions_test.json +0 -14
  201. brg_certificate/tests/edge_mgmt/actions_test/actions_test.py +0 -396
  202. brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.json +0 -20
  203. brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.py +0 -94
  204. brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.json +0 -19
  205. brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.py +0 -87
  206. brg_certificate/tests/edge_mgmt/leds_test/leds_test.json +0 -17
  207. brg_certificate/tests/edge_mgmt/leds_test/leds_test.py +0 -223
  208. brg_certificate/tests/edge_mgmt/ota_test/ota_test.json +0 -17
  209. brg_certificate/tests/edge_mgmt/ota_test/ota_test.py +0 -128
  210. brg_certificate/tests/energy2400/output_power_test/output_power_test.json +0 -16
  211. brg_certificate/tests/energy2400/signal_indicator_ble5_10_250k_test/signal_indicator_ble5_10_250k_test.json +0 -20
  212. brg_certificate/tests/energy2400/signal_indicator_ble5_10_250k_test/signal_indicator_ble5_10_250k_test.py +0 -321
  213. brg_certificate/tests/energy2400/signal_indicator_ble5_10_500k_test/signal_indicator_ble5_10_500k_test.json +0 -20
  214. brg_certificate/tests/energy2400/signal_indicator_ble5_10_500k_test/signal_indicator_ble5_10_500k_test.py +0 -321
  215. brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.json +0 -20
  216. brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.py +0 -141
  217. brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.json +0 -20
  218. brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.py +0 -276
  219. brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.json +0 -20
  220. brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.py +0 -390
  221. brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.json +0 -16
  222. brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.py +0 -28
  223. brg_certificate/tests/sensors/ext_sensor_test/ext_sensor_test.py +0 -305
  224. brg_certificate/wltPb_pb2.pyi +0 -234
  225. brg_certificate/wlt_types.py +0 -113
  226. gw_certificate/ag/ut_defines.py +0 -364
  227. gw_certificate/ag/wlt_types.py +0 -85
  228. gw_certificate/ag/wlt_types_ag.py +0 -5310
  229. gw_certificate/ag/wlt_types_data.py +0 -64
  230. gw_certificate/api/extended_api.py +0 -23
  231. gw_certificate/api_if/200/data.json +0 -106
  232. gw_certificate/api_if/200/status.json +0 -47
  233. gw_certificate/api_if/201/data.json +0 -98
  234. gw_certificate/api_if/201/status.json +0 -53
  235. gw_certificate/api_if/205/logs.json +0 -12
  236. gw_certificate/api_if/api_validation.py +0 -38
  237. gw_certificate/api_if/gw_capabilities.py +0 -54
  238. gw_certificate/cert_results.py +0 -145
  239. gw_certificate/common/analysis_data_bricks.py +0 -60
  240. gw_certificate/common/debug.py +0 -42
  241. gw_certificate/common/serialization_formatter.py +0 -93
  242. gw_certificate/common/utils.py +0 -8
  243. gw_certificate/common/utils_defines.py +0 -15
  244. gw_certificate/common/wltPb_pb2.py +0 -84
  245. gw_certificate/gw_certificate.py +0 -154
  246. gw_certificate/gw_certificate_cli.py +0 -87
  247. gw_certificate/interface/4.4.91_app.zip +0 -0
  248. gw_certificate/interface/4.4.91_sd_bl_app.zip +0 -0
  249. gw_certificate/interface/ble_simulator.py +0 -61
  250. gw_certificate/interface/ble_sniffer.py +0 -189
  251. gw_certificate/interface/flash_fw.py +0 -90
  252. gw_certificate/interface/if_defines.py +0 -36
  253. gw_certificate/interface/mqtt.py +0 -563
  254. gw_certificate/interface/nrfutil-linux +0 -0
  255. gw_certificate/interface/nrfutil-mac +0 -0
  256. gw_certificate/interface/nrfutil.exe +0 -0
  257. gw_certificate/interface/pkt_generator.py +0 -594
  258. gw_certificate/interface/uart_if.py +0 -236
  259. gw_certificate/interface/uart_ports.py +0 -20
  260. gw_certificate/templates/results.html +0 -241
  261. gw_certificate/templates/stage.html +0 -22
  262. gw_certificate/templates/table.html +0 -6
  263. gw_certificate/templates/test.html +0 -38
  264. gw_certificate/tests/__init__.py +0 -10
  265. gw_certificate/tests/actions.py +0 -289
  266. gw_certificate/tests/bad_crc_to_PER_quantization.csv +0 -51
  267. gw_certificate/tests/connection.py +0 -188
  268. gw_certificate/tests/downlink.py +0 -172
  269. gw_certificate/tests/generic.py +0 -238
  270. gw_certificate/tests/registration.py +0 -340
  271. gw_certificate/tests/static/__init__.py +0 -0
  272. gw_certificate/tests/static/connection_defines.py +0 -9
  273. gw_certificate/tests/static/downlink_defines.py +0 -9
  274. gw_certificate/tests/static/generated_packet_table.py +0 -195
  275. gw_certificate/tests/static/packet_table.csv +0 -10067
  276. gw_certificate/tests/static/references.py +0 -5
  277. gw_certificate/tests/static/uplink_defines.py +0 -14
  278. gw_certificate/tests/throughput.py +0 -240
  279. gw_certificate/tests/uplink.py +0 -853
  280. wiliot_certificate-4.4.2.dist-info/METADATA +0 -211
  281. wiliot_certificate-4.4.2.dist-info/RECORD +0 -210
  282. wiliot_certificate-4.4.2.dist-info/entry_points.txt +0 -3
  283. wiliot_certificate-4.4.2.dist-info/top_level.txt +0 -3
  284. {brg_certificate → certificate}/__init__.py +0 -0
  285. {gw_certificate → common}/api_if/202/data.json +0 -0
  286. {gw_certificate/api_if/200 → common/api_if/202}/logs.json +0 -0
  287. {gw_certificate → common}/api_if/203/data.json +0 -0
  288. {gw_certificate/api_if/201 → common/api_if/203}/logs.json +0 -0
  289. {gw_certificate → common}/api_if/204/data.json +0 -0
  290. {gw_certificate/api_if/202 → common/api_if/204}/logs.json +0 -0
  291. {gw_certificate → common}/api_if/205/data.json +0 -0
  292. {gw_certificate/api_if/203 → common/api_if/205}/logs.json +0 -0
  293. {gw_certificate → common}/api_if/205/status.json +0 -0
  294. {gw_certificate/api_if/204 → common/api_if/206}/logs.json +0 -0
  295. {gw_certificate → common/api_if}/__init__.py +0 -0
  296. {gw_certificate/api_if → gui_certificate}/__init__.py +0 -0
  297. {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
+ }