wiliot-certificate 1.3.0a1__py3-none-any.whl → 1.4.0a2__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 (184) hide show
  1. brg_certificate/__init__.py +0 -0
  2. brg_certificate/ag/energous_v0_defines.py +925 -0
  3. brg_certificate/ag/energous_v1_defines.py +931 -0
  4. brg_certificate/ag/energous_v2_defines.py +925 -0
  5. brg_certificate/ag/energous_v3_defines.py +925 -0
  6. brg_certificate/ag/energous_v4_defines.py +925 -0
  7. brg_certificate/ag/fanstel_lan_v0_defines.py +925 -0
  8. brg_certificate/ag/fanstel_lte_v0_defines.py +925 -0
  9. brg_certificate/ag/fanstel_wifi_v0_defines.py +925 -0
  10. brg_certificate/ag/minew_lte_v0_defines.py +925 -0
  11. brg_certificate/ag/wlt_cmd_if.html +102 -0
  12. brg_certificate/ag/wlt_types.html +6114 -0
  13. brg_certificate/ag/wlt_types_ag.py +7840 -0
  14. brg_certificate/ag/wlt_types_ag_jsons/brg2brg_ota.json +142 -0
  15. brg_certificate/ag/wlt_types_ag_jsons/brg2gw_hb.json +785 -0
  16. brg_certificate/ag/wlt_types_ag_jsons/brg2gw_hb_sleep.json +139 -0
  17. brg_certificate/ag/wlt_types_ag_jsons/calibration.json +394 -0
  18. brg_certificate/ag/wlt_types_ag_jsons/custom.json +515 -0
  19. brg_certificate/ag/wlt_types_ag_jsons/datapath.json +672 -0
  20. brg_certificate/ag/wlt_types_ag_jsons/energy2400.json +550 -0
  21. brg_certificate/ag/wlt_types_ag_jsons/energySub1g.json +595 -0
  22. brg_certificate/ag/wlt_types_ag_jsons/externalSensor.json +598 -0
  23. brg_certificate/ag/wlt_types_ag_jsons/interface.json +938 -0
  24. brg_certificate/ag/wlt_types_ag_jsons/powerManagement.json +1234 -0
  25. brg_certificate/ag/wlt_types_ag_jsons/side_info_sensor.json +105 -0
  26. brg_certificate/ag/wlt_types_ag_jsons/signal_indicator_data.json +77 -0
  27. brg_certificate/ag/wlt_types_ag_jsons/unified_echo_ext_pkt.json +61 -0
  28. brg_certificate/ag/wlt_types_ag_jsons/unified_echo_pkt.json +110 -0
  29. brg_certificate/brg_certificate.py +191 -0
  30. brg_certificate/brg_certificate_cli.py +47 -0
  31. brg_certificate/cert_common.py +828 -0
  32. brg_certificate/cert_config.py +395 -0
  33. brg_certificate/cert_data_sim.py +188 -0
  34. brg_certificate/cert_defines.py +337 -0
  35. brg_certificate/cert_gw_sim.py +285 -0
  36. brg_certificate/cert_mqtt.py +373 -0
  37. brg_certificate/cert_prints.py +181 -0
  38. brg_certificate/cert_protobuf.py +88 -0
  39. brg_certificate/cert_results.py +300 -0
  40. brg_certificate/cert_utils.py +358 -0
  41. brg_certificate/certificate_sanity_test_list.txt +36 -0
  42. brg_certificate/certificate_test_list.txt +43 -0
  43. brg_certificate/config/eclipse.json +10 -0
  44. brg_certificate/config/hivemq.json +10 -0
  45. brg_certificate/config/mosquitto.json +10 -0
  46. brg_certificate/config/mosquitto.md +95 -0
  47. brg_certificate/config/wiliot-dev.json +10 -0
  48. brg_certificate/restore_brg.py +59 -0
  49. brg_certificate/tests/calibration/interval_test/interval_test.json +13 -0
  50. brg_certificate/tests/calibration/interval_test/interval_test.py +28 -0
  51. brg_certificate/tests/calibration/output_power_test/output_power_test.json +13 -0
  52. brg_certificate/tests/calibration/output_power_test/output_power_test.py +28 -0
  53. brg_certificate/tests/calibration/pattern_test/pattern_test.json +13 -0
  54. brg_certificate/tests/calibration/pattern_test/pattern_test.py +70 -0
  55. brg_certificate/tests/datapath/adaptive_pacer_algo_test/adaptive_pacer_algo_test.json +13 -0
  56. brg_certificate/tests/datapath/adaptive_pacer_algo_test/adaptive_pacer_algo_test.py +76 -0
  57. brg_certificate/tests/datapath/num_of_tags_test/num_of_tags_test.json +13 -0
  58. brg_certificate/tests/datapath/num_of_tags_test/num_of_tags_test.py +83 -0
  59. brg_certificate/tests/datapath/output_power_test/output_power_test.json +13 -0
  60. brg_certificate/tests/datapath/output_power_test/output_power_test.py +27 -0
  61. brg_certificate/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.json +13 -0
  62. brg_certificate/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.py +43 -0
  63. brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.json +13 -0
  64. brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.py +63 -0
  65. brg_certificate/tests/datapath/pacer_interval_test/pacer_interval_test.json +13 -0
  66. brg_certificate/tests/datapath/pacer_interval_test/pacer_interval_test.py +50 -0
  67. brg_certificate/tests/datapath/pattern_test/pattern_test.json +13 -0
  68. brg_certificate/tests/datapath/pattern_test/pattern_test.py +28 -0
  69. brg_certificate/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.json +13 -0
  70. brg_certificate/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.py +51 -0
  71. brg_certificate/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.json +13 -0
  72. brg_certificate/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.py +54 -0
  73. brg_certificate/tests/datapath/pkt_filter_test/pkt_filter_test.json +13 -0
  74. brg_certificate/tests/datapath/pkt_filter_test/pkt_filter_test.py +55 -0
  75. brg_certificate/tests/datapath/rssi_threshold_test/rssi_threshold_test.json +13 -0
  76. brg_certificate/tests/datapath/rssi_threshold_test/rssi_threshold_test.py +73 -0
  77. brg_certificate/tests/datapath/rx_channel_test/rx_channel_test.json +13 -0
  78. brg_certificate/tests/datapath/rx_channel_test/rx_channel_test.py +41 -0
  79. brg_certificate/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.json +21 -0
  80. brg_certificate/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.py +184 -0
  81. brg_certificate/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.json +21 -0
  82. brg_certificate/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.py +210 -0
  83. brg_certificate/tests/datapath/stress_gen3_test/stress_gen3_test.json +30 -0
  84. brg_certificate/tests/datapath/stress_gen3_test/stress_gen3_test.py +203 -0
  85. brg_certificate/tests/datapath/stress_test/stress_test.json +30 -0
  86. brg_certificate/tests/datapath/stress_test/stress_test.py +210 -0
  87. brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.json +13 -0
  88. brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.py +113 -0
  89. brg_certificate/tests/datapath/tx_repetition_test/tx_repetition_test.json +13 -0
  90. brg_certificate/tests/datapath/tx_repetition_test/tx_repetition_test.py +79 -0
  91. brg_certificate/tests/edge_mgmt/actions_test/actions_test.json +13 -0
  92. brg_certificate/tests/edge_mgmt/actions_test/actions_test.py +432 -0
  93. brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.json +13 -0
  94. brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.py +94 -0
  95. brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.json +13 -0
  96. brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.py +87 -0
  97. brg_certificate/tests/edge_mgmt/leds_test/leds_test.json +13 -0
  98. brg_certificate/tests/edge_mgmt/leds_test/leds_test.py +210 -0
  99. brg_certificate/tests/edge_mgmt/ota_test/ota_test.json +13 -0
  100. brg_certificate/tests/edge_mgmt/ota_test/ota_test.py +83 -0
  101. brg_certificate/tests/edge_mgmt/stat_test/stat_test.json +13 -0
  102. brg_certificate/tests/edge_mgmt/stat_test/stat_test.py +48 -0
  103. brg_certificate/tests/energy2400/duty_cycle_test/duty_cycle_test.json +13 -0
  104. brg_certificate/tests/energy2400/duty_cycle_test/duty_cycle_test.py +26 -0
  105. brg_certificate/tests/energy2400/output_power_test/output_power_test.json +13 -0
  106. brg_certificate/tests/energy2400/output_power_test/output_power_test.py +27 -0
  107. brg_certificate/tests/energy2400/pattern_test/pattern_test.json +13 -0
  108. brg_certificate/tests/energy2400/pattern_test/pattern_test.py +28 -0
  109. brg_certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.json +13 -0
  110. brg_certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.py +398 -0
  111. brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.json +13 -0
  112. brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.py +153 -0
  113. brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.json +13 -0
  114. brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.py +264 -0
  115. brg_certificate/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.json +13 -0
  116. brg_certificate/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.py +27 -0
  117. brg_certificate/tests/energy_sub1g/pattern_test/pattern_test.json +13 -0
  118. brg_certificate/tests/energy_sub1g/pattern_test/pattern_test.py +26 -0
  119. brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.json +13 -0
  120. brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.py +397 -0
  121. brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.json +13 -0
  122. brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.py +27 -0
  123. brg_certificate/wltPb_pb2.py +72 -0
  124. brg_certificate/wltPb_pb2.pyi +227 -0
  125. brg_certificate/wlt_types.py +114 -0
  126. gw_certificate/api/extended_api.py +7 -1531
  127. gw_certificate/api_if/200/data.json +106 -0
  128. gw_certificate/api_if/200/logs.json +12 -0
  129. gw_certificate/api_if/200/status.json +47 -0
  130. gw_certificate/api_if/201/data.json +98 -0
  131. gw_certificate/api_if/201/logs.json +12 -0
  132. gw_certificate/api_if/201/status.json +53 -0
  133. gw_certificate/api_if/202/data.json +83 -0
  134. gw_certificate/api_if/202/logs.json +12 -0
  135. gw_certificate/api_if/202/status.json +60 -0
  136. gw_certificate/api_if/203/data.json +85 -0
  137. gw_certificate/api_if/203/logs.json +12 -0
  138. gw_certificate/api_if/203/status.json +63 -0
  139. gw_certificate/api_if/204/data.json +85 -0
  140. gw_certificate/api_if/204/logs.json +12 -0
  141. gw_certificate/api_if/204/status.json +63 -0
  142. gw_certificate/api_if/205/data.json +85 -0
  143. gw_certificate/api_if/205/logs.json +12 -0
  144. gw_certificate/api_if/205/status.json +63 -0
  145. gw_certificate/api_if/api_validation.py +0 -2
  146. gw_certificate/common/analysis_data_bricks.py +18 -1413
  147. gw_certificate/common/debug.py +0 -21
  148. gw_certificate/common/utils.py +1 -212
  149. gw_certificate/common/utils_defines.py +0 -87
  150. gw_certificate/gw_certificate.py +9 -7
  151. gw_certificate/gw_certificate_cli.py +39 -23
  152. gw_certificate/interface/4.4.52_app.zip +0 -0
  153. gw_certificate/interface/4.4.52_sd_bl_app.zip +0 -0
  154. gw_certificate/interface/ble_simulator.py +0 -32
  155. gw_certificate/interface/if_defines.py +1 -0
  156. gw_certificate/interface/mqtt.py +96 -19
  157. gw_certificate/interface/nrfutil-linux +0 -0
  158. gw_certificate/interface/nrfutil-mac +0 -0
  159. gw_certificate/interface/nrfutil.exe +0 -0
  160. gw_certificate/interface/pkt_generator.py +0 -82
  161. gw_certificate/interface/uart_if.py +73 -43
  162. gw_certificate/templates/results.html +1 -1
  163. gw_certificate/tests/__init__.py +1 -2
  164. gw_certificate/tests/actions.py +134 -9
  165. gw_certificate/tests/connection.py +10 -5
  166. gw_certificate/tests/downlink.py +2 -4
  167. gw_certificate/tests/generic.py +62 -12
  168. gw_certificate/tests/registration.py +78 -27
  169. gw_certificate/tests/static/generated_packet_table.py +12 -48
  170. gw_certificate/tests/static/packet_table.csv +10048 -10048
  171. gw_certificate/tests/static/references.py +2 -1
  172. gw_certificate/tests/static/uplink_defines.py +0 -7
  173. gw_certificate/tests/throughput.py +7 -12
  174. gw_certificate/tests/uplink.py +83 -43
  175. {wiliot_certificate-1.3.0a1.dist-info → wiliot_certificate-1.4.0a2.dist-info}/METADATA +59 -8
  176. wiliot_certificate-1.4.0a2.dist-info/RECORD +198 -0
  177. {wiliot_certificate-1.3.0a1.dist-info → wiliot_certificate-1.4.0a2.dist-info}/WHEEL +1 -1
  178. wiliot_certificate-1.4.0a2.dist-info/entry_points.txt +3 -0
  179. wiliot_certificate-1.4.0a2.dist-info/top_level.txt +2 -0
  180. gw_certificate/interface/packet_error.py +0 -22
  181. wiliot_certificate-1.3.0a1.dist-info/RECORD +0 -51
  182. wiliot_certificate-1.3.0a1.dist-info/entry_points.txt +0 -2
  183. wiliot_certificate-1.3.0a1.dist-info/top_level.txt +0 -1
  184. {wiliot_certificate-1.3.0a1.dist-info → wiliot_certificate-1.4.0a2.dist-info}/LICENSE +0 -0
@@ -11,16 +11,21 @@ import ssl
11
11
  import base64
12
12
  from google.protobuf.message import DecodeError
13
13
  from google.protobuf.json_format import MessageToDict, Parse, ParseError, ParseDict
14
+ import random
15
+ import re
14
16
 
15
- from gw_certificate.ag.ut_defines import PACKETS, PAYLOAD, MGMT_PKT, SIDE_INFO_PKT, GW_ID, NFPKT, GW_LOGS, UNIFIED_PKT
17
+ from gw_certificate.ag.ut_defines import PACKETS, PAYLOAD, MGMT_PKT, SIDE_INFO_PKT, GW_ID, NFPKT, GW_LOGS, UNIFIED_PKT, STATUS_CODE_STR
16
18
  from gw_certificate.ag.wlt_types_ag import GROUP_ID_BRG2GW, GROUP_ID_SIDE_INFO, GROUP_ID_UNIFIED_PKT
17
19
  from gw_certificate.ag.wlt_types_data import DATA_DEFAULT_GROUP_ID, DataPacket
18
20
  from gw_certificate.common.debug import debug_print
19
21
  from gw_certificate.common import wltPb_pb2
20
22
 
21
23
 
22
-
23
24
  DATA_PKT = 'data_pkt'
25
+ ACTIONSTATUS = 'actionStatus'
26
+ GATEWAYSTATUS = 'gatewayStatus'
27
+
28
+ TOPIC_SUFFIX_PB = '-v2'
24
29
 
25
30
  class CustomBrokers(Enum):
26
31
  HIVE = 'broker.hivemq.com'
@@ -144,6 +149,14 @@ class MqttClient:
144
149
  self.status_topic = f"status{topic_suffix}/{owner_id}/{gw_id}"
145
150
  debug_print(f'Subscribe to {self.status_topic}...')
146
151
  self.client.subscribe(self.status_topic)
152
+
153
+ self.data_topic_pb = f"data{TOPIC_SUFFIX_PB}{topic_suffix}/{owner_id}/{gw_id}"
154
+ debug_print(f'Subscribe to {self.data_topic_pb}...')
155
+ self.client.subscribe(self.data_topic_pb)
156
+ self.status_topic_pb = f"status{TOPIC_SUFFIX_PB}{topic_suffix}/{owner_id}/{gw_id}"
157
+ debug_print(f'Subscribe to {self.status_topic_pb}...')
158
+ self.client.subscribe(self.status_topic_pb)
159
+
147
160
  self.client.loop_start()
148
161
  while(not self.client.is_connected()):
149
162
  debug_print(f'Waiting for MQTT connection...')
@@ -168,7 +181,6 @@ class MqttClient:
168
181
  raw_payload = json.dumps({"action": action.value})
169
182
  self.userdata['published'].append(raw_payload.encode('utf-8'))
170
183
  message_info = self.client.publish(self.update_topic, payload=raw_payload)
171
- print('PublishJSON')
172
184
  # PB
173
185
  if self.get_serialization() in {Serialization.UNKNOWN, Serialization.PB}:
174
186
  payload = wltPb_pb2.DownlinkMessage()
@@ -176,10 +188,51 @@ class MqttClient:
176
188
  raw_payload = payload.SerializeToString()
177
189
  self.userdata['published'].append(raw_payload)
178
190
  message_info = self.client.publish(self.update_topic, payload=raw_payload)
179
- print('PublishPB')
180
191
  message_info.wait_for_publish()
181
192
  return message_info
182
193
 
194
+ def send_bridge_ota_action(self, target_bridge, version, tx_max_duration, upgrade_bl_sd,
195
+ gw_id, cloud="aws", env='prod'):
196
+ """
197
+ VersionUUID generated here - Consistent per (version + upgrade_bl_sd) combination.
198
+ ImageDirUrl generated here - Consistent per (cloud + env + version) combination. Bridge type remain the same.
199
+ RebootPacket generated here - using given targer_bridge and random seq_id.
200
+ """
201
+ CLOUD_MAP = {"aws": f"https://api.us-east-2.{env}.wiliot.cloud",
202
+ "gcp": f"https://api.us-central1.{env}.gcp.wiliot.cloud"}
203
+ GW_TYPE_UNKNOWN = 254
204
+
205
+ image_dir_url = f"{CLOUD_MAP[cloud]}/v1/bridge/type/{GW_TYPE_UNKNOWN}/version/{version}/binary/"
206
+ version_uuid = f"{version}1337{upgrade_bl_sd}"
207
+ seq_id = f"{random.randint(0, 255):02X}"
208
+ debug_print(f"Bridge file URL: {image_dir_url}")
209
+
210
+ reboot_packet = f"1E16C6FC0000ED070C{seq_id}{target_bridge}01"
211
+ reboot_packet = reboot_packet.ljust(62, '0')
212
+
213
+ if self.get_serialization() in {Serialization.UNKNOWN, Serialization.JSON}:
214
+ message = {
215
+ "action": 1,
216
+ "gatewayId": gw_id,
217
+ "imageDirUrl": image_dir_url,
218
+ "versionUUID": version_uuid,
219
+ "txPacket": reboot_packet,
220
+ "txMaxRetries": tx_max_duration // 100,
221
+ "txMaxDurationMs": tx_max_duration,
222
+ "bridgeId": target_bridge
223
+ }
224
+ self.send_payload(message, topic='update')
225
+ if self.get_serialization() in {Serialization.UNKNOWN, Serialization.PB}:
226
+ message = wltPb_pb2.DownlinkMessage()
227
+ message.bridgeUpgrade.rebootPacket = bytes.fromhex(reboot_packet)
228
+ message.bridgeUpgrade.txMaxDurationMs = tx_max_duration
229
+ message.bridgeUpgrade.txMaxRetries = tx_max_duration // 100
230
+ message.bridgeUpgrade.bridgeId = target_bridge
231
+ message.bridgeUpgrade.versionUuid = version_uuid
232
+ message.bridgeUpgrade.upgradeBlSd = upgrade_bl_sd
233
+ message.bridgeUpgrade.imageDirUrl = image_dir_url
234
+ self.send_payload(message, topic='update')
235
+
183
236
  def send_payload(self, payload, topic:Literal['update', 'data', 'status']='update'):
184
237
  """
185
238
  Send a payload to the gateway
@@ -284,20 +337,13 @@ class MqttClient:
284
337
  def check_gw_seen(self):
285
338
  return self.userdata['gw_seen']
286
339
 
287
- def get_gw_info(self):
288
- self.flush_messages()
289
- self.send_action(GwAction.GET_GW_INFO)
290
- time.sleep(5)
291
- debug_print('---GW INFO---')
292
- try:
293
- gw_info = self.userdata['messages'].status[0]
294
- debug_print(gw_info)
295
- self.flush_messages()
296
- return gw_info
297
- except IndexError:
298
- debug_print('No GW INFO')
299
- self.flush_messages()
300
- return False
340
+ def get_gw_info_message(self):
341
+ messages = self.get_all_messages_from_topic('status')
342
+ for message in messages:
343
+ if GW_LOGS not in message.body_ex.keys():
344
+ if 'gatewayInfo' in message.body_ex.keys():
345
+ return message.body_ex
346
+ return None
301
347
 
302
348
  def get_gw_configuration(self):
303
349
  self.flush_messages()
@@ -354,7 +400,23 @@ class MqttClient:
354
400
  messages = self.get_all_messages_from_topic('status')
355
401
  for message in messages:
356
402
  if GW_LOGS not in message.body_ex.keys():
357
- return message.body_ex
403
+ if 'gatewayConf' in message.body_ex.keys():
404
+ return message.body_ex
405
+ elif GATEWAYSTATUS in message.body_ex.keys():
406
+ return message.body_ex[GATEWAYSTATUS]
407
+ return None
408
+
409
+ def get_action_status_message(self):
410
+ messages = self.get_all_messages_from_topic('status')
411
+ for message in messages:
412
+ if GW_LOGS not in message.body_ex.keys():
413
+ if STATUS_CODE_STR in message.body_ex.keys():
414
+ return message.body_ex
415
+ elif ACTIONSTATUS in message.body_ex.keys():
416
+ if 'status' not in message.body_ex[ACTIONSTATUS].keys():
417
+ # Default values are omitted in protobuf, set 0 for explicitness
418
+ message.body_ex[ACTIONSTATUS]['status'] = 0
419
+ return message.body_ex[ACTIONSTATUS]
358
420
  return None
359
421
 
360
422
  def get_coupled_tags_pkts(self):
@@ -365,6 +427,21 @@ class MqttClient:
365
427
 
366
428
  def get_all_tags_pkts(self):
367
429
  return [p for p in self.get_all_pkts_from_topic('data')]
430
+
431
+ # Validate topic
432
+ def validate_serialization_topic(self, topic:Literal['status', 'data', 'update']):
433
+ messages = self.get_all_messages_from_topic(topic)
434
+
435
+ if self.get_serialization() == Serialization.JSON:
436
+ for message in messages:
437
+ if TOPIC_SUFFIX_PB in message.mqtt_topic:
438
+ return (False, message.body_ex, message.mqtt_topic)
439
+ elif self.get_serialization() == Serialization.PB:
440
+ for message in messages:
441
+ if TOPIC_SUFFIX_PB not in message.mqtt_topic:
442
+ return (False, message.body_ex, message.mqtt_topic)
443
+ return (True, None, None)
444
+
368
445
 
369
446
  # MQTT Client callbacks
370
447
 
Binary file
Binary file
Binary file
@@ -1,7 +1,6 @@
1
1
  import binascii
2
2
  import datetime
3
3
  from typing import Literal, List
4
- import numpy as np
5
4
  import random
6
5
  import os
7
6
 
@@ -17,13 +16,11 @@ from gw_certificate.ag.wlt_types import *
17
16
  from gw_certificate.ag.wlt_types_ag import (
18
17
  GROUP_ID_SIDE_INFO,
19
18
  GROUP_ID_BRG2GW,
20
- GROUP_ID_GW2BRG,
21
19
  Hdr,
22
20
  SideInfo,
23
21
  )
24
22
  from gw_certificate.ag.wlt_types_data import DataPacket
25
23
 
26
- # TODO Find a relevant place for this define that is not auto-generated.
27
24
  BRG_LATENCY = "brg_latency"
28
25
 
29
26
  # Shared Functions
@@ -623,23 +620,6 @@ class BrgPktGeneratorNetwork:
623
620
  for brg in self.secondary_brgs:
624
621
  brg.set_tag_list(self.primary_brg.tag_list)
625
622
 
626
- def get_new_pkt_pairs(self) -> list:
627
- """Get data/si pairs for all bridges in bridge network
628
-
629
- :return: List of dictionaries containing {bridge_id, data_packet, si_packet} key:value pairs
630
- :rtype: list[dict]
631
- """
632
- pkts = []
633
- new_pkt_primary = self.primary_brg.get_new_data_si()
634
- pkts.append(new_pkt_primary)
635
- for brg in self.secondary_brgs:
636
- brg.update_si_list()
637
- brg.randomize_si_rssi_nfpkt()
638
- pkts.append(brg.get_existing_data_si())
639
- for idx, pkt in enumerate(pkts):
640
- pkt.update({'bridge_id': self.brg_list[idx].bridge_id})
641
- return pkts
642
-
643
623
  def get_new_pkt_unified(self) -> list:
644
624
  """Get new unified pkt for all bridges in bridge network
645
625
 
@@ -656,65 +636,3 @@ class BrgPktGeneratorNetwork:
656
636
  for idx, pkt in enumerate(pkts):
657
637
  pkt.update({'bridge_id': self.brg_list[idx].bridge_id})
658
638
  return pkts
659
-
660
- def get_scattered_pkt_pairs(self, delay):
661
- """Get data/si pairs with scattered time delays
662
-
663
- :param delay: bridges rxTxPeriod equivalent (millisecond)
664
- :type delay: int
665
- """
666
- assert delay / len(self.brg_list) >= 10, 'Cannot get scattered PKT pairs for parameters! decrease num of brgs or increase delay'
667
- start_times = sorted(random.sample(list(np.arange(0, delay-10+1, 10)), k=len(self.brg_list)))
668
- start_times.append((start_times[0] + delay))
669
- pkts = self.get_new_pkt_pairs()
670
-
671
- for idx, pkt in enumerate(pkts):
672
- # minimum time between UART packet commands = 10ms
673
- pkt['time_delay'] = max(start_times[idx+1] - start_times[idx], 10)
674
- return pkts
675
-
676
- class CloudPktGenerator:
677
- """Cloud Packet Generator - Represents """
678
- def __init__(self):
679
- self.bridge_id, self.bridge_id_int = generate_random_bridge_id()
680
- pass
681
-
682
- def generate_config_pkt(self, seq_id=None, bridge_id=None):
683
- if seq_id == None:
684
- seq_id = int.from_bytes(os.urandom(1), 'big')
685
- if bridge_id is not None:
686
- bridge_id_int = int.from_bytes(binascii.unhexlify(bridge_id), "big")
687
-
688
- pkt = WltPkt(Hdr(group_id=GROUP_ID_GW2BRG), generic=Gw2BrgCfgV7(
689
- msg_type=BRG_MGMT_MSG_TYPE_CFG_SET,
690
- global_pacing_group=random.getrandbits(4),
691
- output_power_sub_1_ghz=random.getrandbits(4),
692
- seq_id=random.getrandbits(8),
693
- brg_mac=bridge_id_int,
694
- unused0=0,
695
- pkt_types_mask=random.getrandbits(5),
696
- unused1=0,
697
- rxtx_period=random.getrandbits(8),
698
- tx_period=random.getrandbits(8),
699
- energy_pattern_idx=random.getrandbits(8),
700
- output_power_2_4=random.getrandbits(8),
701
- pacer_interval=random.getrandbits(16),
702
- unused2=0,
703
- tx_prob=random.getrandbits(3),
704
- tx_repetition=random.getrandbits(4),
705
- transmit_time_sub_1_ghz=random.getrandbits(4),
706
- sub1g_freq_profile=random.getrandbits(4),
707
- ))
708
- return pkt.dump()
709
-
710
- # def generate_action_pkt(self, action: Literal["blink", "reboot"], seq_id=None, bridge_id=None):
711
- # if seq_id == None:
712
- # seq_id = int.from_bytes(os.urandom(1), 'big')
713
- # if bridge_id is not None:
714
- # bridge_id_int = int.from_bytes(binascii.unhexlify(bridge_id), "big")
715
-
716
- # pkt = WltPkt(Hdr(group_id=GROUP_ID_GW2BRG), generic=ActionV7(
717
- # msg_type=BRG_MGMT_MSG_TYPE_ACTION,
718
- # seq_id=seq_id,
719
- # action_id=
720
- # )
@@ -3,7 +3,8 @@ import subprocess
3
3
  import serial
4
4
  import serial.tools.list_ports
5
5
  import time
6
- import os.path
6
+ import os
7
+ import stat
7
8
  import platform
8
9
  from packaging import version
9
10
  import pkg_resources
@@ -11,24 +12,31 @@ import pkg_resources
11
12
  from gw_certificate.common.debug import debug_print
12
13
  from gw_certificate.interface.if_defines import *
13
14
 
14
- LATEST_VERSION = '4.4.15'
15
- LATEST_VERSION_FILE = f'{LATEST_VERSION}_app.zip'
15
+ LATEST_VERSION = '4.4.52'
16
+ LATEST_VERSION_FILE = f'{LATEST_VERSION}_sd_bl_app.zip'
16
17
  LATEST_VERSION_PATH = pkg_resources.resource_filename(__name__, LATEST_VERSION_FILE)
18
+ LATEST_VERSION_FILE_APP = f'{LATEST_VERSION}_app.zip'
19
+ LATEST_VERSION_PATH_APP = pkg_resources.resource_filename(__name__, LATEST_VERSION_FILE_APP)
17
20
 
18
- LATEST_VERSION_SNIFFING_KIT = '4.1.19'
19
- LATEST_VERSION_FILE_SNIFFING_KIT = f'{LATEST_VERSION_SNIFFING_KIT}_app.zip'
20
- LATEST_VERSION_PATH_SNIFFING_KIT = pkg_resources.resource_filename(__name__, LATEST_VERSION_FILE_SNIFFING_KIT)
21
+ FIRST_UNIFIED_BL_VERSION = version.parse('4.4.44')
22
+
23
+ NRFUTIL_FW_TOO_LOW_ERROR = 'Error 0x05: The firmware version is too low'
21
24
 
22
25
  class UARTError(Exception):
23
26
  pass
24
27
 
25
28
  class UARTInterface:
26
- def __init__(self, comport, update_fw=True, sniffing_kit_flag=False):
29
+ def __init__(self, comport, update_fw=True):
27
30
  self.comport = comport
28
31
  self.serial = serial.Serial(port=comport, baudrate=921600, timeout=SERIAL_TIMEOUT)
29
32
  self.serial.flushInput()
30
33
  self.gw_app_rx = None
31
- self.sniffing_kit_flag = sniffing_kit_flag
34
+ self.fw_version, self.mac = self.get_version_mac()
35
+
36
+ if self.fw_version is None:
37
+ raise UARTError("Cannot initialize board! Please try disconnecting and connecting USB cable")
38
+ self.fw_version = version.parse(self.fw_version)
39
+
32
40
  version_supported = self.check_fw_supported()
33
41
  if not version_supported and update_fw:
34
42
  update_status = self.update_firmware()
@@ -73,28 +81,26 @@ class UARTInterface:
73
81
 
74
82
  def flush(self):
75
83
  self.serial.close()
84
+ time.sleep(2)
76
85
  self.serial.open()
77
86
  self.serial.flushInput()
78
87
  self.serial.flush()
79
88
  self.serial.reset_output_buffer()
80
89
 
81
- def reset_gw(self):
90
+ def reset_gw(self, stop_advertising=True):
82
91
  self.flush()
83
92
  self.write_ble_command(RESET_GW)
84
93
  self.gw_app_rx = None
85
94
  time.sleep(3)
86
- self.write_ble_command(STOP_ADVERTISING)
87
- time.sleep(3)
88
-
95
+ if stop_advertising:
96
+ self.write_ble_command(STOP_ADVERTISING)
97
+ time.sleep(3)
89
98
 
90
99
  def cancel(self):
91
100
  self.write_ble_command(CANCEL)
92
101
 
93
102
  def set_rx(self, rx_channel):
94
- if self.sniffing_kit_flag:
95
- assert rx_channel in RX_CHANNELS_SNIFFING_KIT
96
- else:
97
- assert rx_channel in RX_CHANNELS
103
+ assert rx_channel in RX_CHANNELS
98
104
  if self.gw_app_rx is None:
99
105
  self.reset_gw()
100
106
 
@@ -102,9 +108,6 @@ class UARTInterface:
102
108
  # from 3.17.0, only full_cfg can be used to configure channels. sending it with:
103
109
  # Data coupling(DC) off, wifi(NW) and mqtt(MQ) on.
104
110
  rx_ch_to_fw_enums = {37: 2, 38: 3, 39: 4}
105
- if self.sniffing_kit_flag:
106
- my_dict = {i: 5 + i for i in range(37)}
107
- rx_ch_to_fw_enums.update(my_dict)
108
111
  cmd = f'!full_cfg DM {rx_ch_to_fw_enums[rx_channel]} DC 0 NW 1 MQ 1 CH {rx_channel}'
109
112
  # cmd = '!gateway_app'
110
113
  else:
@@ -128,6 +131,17 @@ class UARTInterface:
128
131
  self.write_ble_command(CANCEL_SNIFFER)
129
132
  self.flush()
130
133
 
134
+ def get_version_mac(self):
135
+ self.reset_gw()
136
+ self.flush()
137
+ timeout = datetime.datetime.now() + datetime.timedelta(seconds=15)
138
+ while datetime.datetime.now() < timeout:
139
+ raw_version = self.write_ble_command(VERSION, read=True)
140
+ if raw_version is not None:
141
+ if GW_APP_VERSION_HEADER in raw_version:
142
+ return (raw_version.split(' ')[0].split('=')[1], raw_version.split(' ')[1].split('=')[1])
143
+ return None, None
144
+
131
145
  def get_version(self):
132
146
  self.reset_gw()
133
147
  self.flush()
@@ -139,36 +153,57 @@ class UARTInterface:
139
153
  return raw_version.split(' ')[0].split('=')[1]
140
154
  return None
141
155
 
156
+ def get_mac(self):
157
+ self.reset_gw()
158
+ self.flush()
159
+ timeout = datetime.datetime.now() + datetime.timedelta(seconds=15)
160
+ while datetime.datetime.now() < timeout:
161
+ reply = self.write_ble_command(VERSION, read=True)
162
+ if reply is not None:
163
+ if GW_MAC_ADDRESS_HEADER in reply:
164
+ return reply.split(' ')[1].split('=')[1]
165
+ return None
166
+
142
167
  def check_fw_supported(self):
143
- current_version = self.get_version()
144
- if current_version is None:
145
- raise UARTError("Cannot initialize board! Please try disconnecting and connecting USB cable")
146
- current_version = version.parse(current_version)
147
168
  hex_version = version.parse(os.path.splitext(os.path.basename(LATEST_VERSION_PATH))[0].split('_')[0])
148
- self.fw_version = current_version
149
- if current_version >= hex_version:
150
- debug_print(f'GW Running version {current_version}')
151
- self.fw_version = current_version
169
+ if self.fw_version >= hex_version:
170
+ debug_print(f'GW Running version {self.fw_version}')
152
171
  return True
153
172
  return False
173
+
174
+ def make_executable(self, file_path):
175
+ """Set execute permissions for a file (chmod +x).
176
+ For windows, having the file suffix as .exe is enough. """
177
+ # Get current file permissions
178
+ current_permissions = os.stat(file_path).st_mode
179
+ # Add execute permissions for the user, group, and others
180
+ os.chmod(file_path, current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
154
181
 
155
182
  def update_firmware(self):
156
183
  NRFUTIL_MAP = {"Linux": "nrfutil-linux", "Darwin": "nrfutil-mac", "Windows": "nrfutil.exe"}
157
184
  nrfutil_file = pkg_resources.resource_filename(__name__, NRFUTIL_MAP[platform.system()])
185
+ if platform.system() != "Windows":
186
+ self.make_executable(nrfutil_file)
158
187
  # In order to support NRF UART FW update with protobuf > 3.20.0
159
188
  os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'
160
189
 
161
- self.write_ble_command('!reset', read=True)
190
+ self.reset_gw()
162
191
  self.write_ble_command('!move_to_bootloader', read=True)
163
192
  self.serial.close()
164
193
  p = None
165
- if self.sniffing_kit_flag:
166
- p = subprocess.Popen(f'{nrfutil_file} dfu serial --package "{LATEST_VERSION_PATH_SNIFFING_KIT}" -p {self.comport} -fc 0 -b 115200 -t 10', shell=True)
167
- else:
168
- p = subprocess.Popen(f'{nrfutil_file} dfu serial --package "{LATEST_VERSION_PATH}" -p {self.comport} -fc 0 -b 115200 -t 10', shell=True)
169
- p.wait()
170
- return_code = p.returncode
171
- debug_print('Waiting for device to update...')
194
+ dfu_full_process = subprocess.Popen(f'{nrfutil_file} dfu serial --package "{LATEST_VERSION_PATH}" -p {self.comport} -fc 0 -b 115200 -t 10',
195
+ stderr=subprocess.PIPE, shell=True, text=True)
196
+ dfu_full_process.wait()
197
+ return_code = dfu_full_process.returncode
198
+ for line in dfu_full_process.stderr:
199
+ if NRFUTIL_FW_TOO_LOW_ERROR in line:
200
+ debug_print(f"DFU failed due to firmware (bootloader/application) version being too low.")
201
+ debug_print(f"Probably since bootloader is already upgraded. Attempting to upgrade application only..")
202
+ dfu_app_process = subprocess.Popen(f'{nrfutil_file} dfu serial --package "{LATEST_VERSION_PATH_APP}" -p {self.comport} -fc 0 -b 115200 -t 10',
203
+ stderr=subprocess.PIPE, shell=True, text=True)
204
+ dfu_app_process.wait()
205
+ return_code = dfu_app_process.returncode
206
+ debug_print('Waiting for the certificate kit to apply the update and boot...')
172
207
  timeout = datetime.datetime.now() + datetime.timedelta(minutes=2)
173
208
  current_ver = ''
174
209
  time.sleep(15)
@@ -179,15 +214,10 @@ class UARTInterface:
179
214
  if current_ver is None:
180
215
  current_ver = ''
181
216
  time.sleep(1)
182
- if self.sniffing_kit_flag:
183
- if current_ver.split(' ')[0].split('=')[1] != LATEST_VERSION_SNIFFING_KIT:
184
- return False
185
- else:
186
- if current_ver.split(' ')[0].split('=')[1] != LATEST_VERSION:
187
- return False
217
+ if current_ver.split(' ')[0].split('=')[1] != LATEST_VERSION:
218
+ return False
188
219
  if return_code == 0:
189
220
  self.fw_version = version.parse(current_ver.split(' ')[0].split('=')[1])
221
+ debug_print(f"Certification kit upgraded to {LATEST_VERSION} successfully")
190
222
  return True
191
223
  return False
192
-
193
- ### TODO: Sequence List
@@ -39,7 +39,7 @@
39
39
  </div>
40
40
  <br>
41
41
  <div class="container">
42
- <h1> GW Certificate | version {{version}} | {{ gw_id }} | {{ datetime }}</h1>
42
+ <h1> GW Certificate | Version {{version}} | {{ gw_id }} | {{ datetime }}</h1>
43
43
  <div class="card">
44
44
  <div class="card-header">
45
45
  Tests Summary
@@ -7,5 +7,4 @@ from gw_certificate.tests.throughput import StressTest
7
7
 
8
8
  TESTS = [RegistrationTest, ConnectionTest, UplinkTest, DownlinkTest, ActionsTest, StressTest]
9
9
 
10
- TESTS_DEFAULT = [ConnectionTest, UplinkTest, DownlinkTest, ActionsTest, StressTest]
11
- TESTS_NO_UART = [RegistrationTest, ActionsTest]
10
+ TESTS_NO_UART = [RegistrationTest]