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.
- brg_certificate/__init__.py +0 -0
- brg_certificate/ag/energous_v0_defines.py +925 -0
- brg_certificate/ag/energous_v1_defines.py +931 -0
- brg_certificate/ag/energous_v2_defines.py +925 -0
- brg_certificate/ag/energous_v3_defines.py +925 -0
- brg_certificate/ag/energous_v4_defines.py +925 -0
- brg_certificate/ag/fanstel_lan_v0_defines.py +925 -0
- brg_certificate/ag/fanstel_lte_v0_defines.py +925 -0
- brg_certificate/ag/fanstel_wifi_v0_defines.py +925 -0
- brg_certificate/ag/minew_lte_v0_defines.py +925 -0
- brg_certificate/ag/wlt_cmd_if.html +102 -0
- brg_certificate/ag/wlt_types.html +6114 -0
- brg_certificate/ag/wlt_types_ag.py +7840 -0
- brg_certificate/ag/wlt_types_ag_jsons/brg2brg_ota.json +142 -0
- brg_certificate/ag/wlt_types_ag_jsons/brg2gw_hb.json +785 -0
- brg_certificate/ag/wlt_types_ag_jsons/brg2gw_hb_sleep.json +139 -0
- brg_certificate/ag/wlt_types_ag_jsons/calibration.json +394 -0
- brg_certificate/ag/wlt_types_ag_jsons/custom.json +515 -0
- brg_certificate/ag/wlt_types_ag_jsons/datapath.json +672 -0
- brg_certificate/ag/wlt_types_ag_jsons/energy2400.json +550 -0
- brg_certificate/ag/wlt_types_ag_jsons/energySub1g.json +595 -0
- brg_certificate/ag/wlt_types_ag_jsons/externalSensor.json +598 -0
- brg_certificate/ag/wlt_types_ag_jsons/interface.json +938 -0
- brg_certificate/ag/wlt_types_ag_jsons/powerManagement.json +1234 -0
- brg_certificate/ag/wlt_types_ag_jsons/side_info_sensor.json +105 -0
- brg_certificate/ag/wlt_types_ag_jsons/signal_indicator_data.json +77 -0
- brg_certificate/ag/wlt_types_ag_jsons/unified_echo_ext_pkt.json +61 -0
- brg_certificate/ag/wlt_types_ag_jsons/unified_echo_pkt.json +110 -0
- brg_certificate/brg_certificate.py +191 -0
- brg_certificate/brg_certificate_cli.py +47 -0
- brg_certificate/cert_common.py +828 -0
- brg_certificate/cert_config.py +395 -0
- brg_certificate/cert_data_sim.py +188 -0
- brg_certificate/cert_defines.py +337 -0
- brg_certificate/cert_gw_sim.py +285 -0
- brg_certificate/cert_mqtt.py +373 -0
- brg_certificate/cert_prints.py +181 -0
- brg_certificate/cert_protobuf.py +88 -0
- brg_certificate/cert_results.py +300 -0
- brg_certificate/cert_utils.py +358 -0
- brg_certificate/certificate_sanity_test_list.txt +36 -0
- brg_certificate/certificate_test_list.txt +43 -0
- brg_certificate/config/eclipse.json +10 -0
- brg_certificate/config/hivemq.json +10 -0
- brg_certificate/config/mosquitto.json +10 -0
- brg_certificate/config/mosquitto.md +95 -0
- brg_certificate/config/wiliot-dev.json +10 -0
- brg_certificate/restore_brg.py +59 -0
- brg_certificate/tests/calibration/interval_test/interval_test.json +13 -0
- brg_certificate/tests/calibration/interval_test/interval_test.py +28 -0
- brg_certificate/tests/calibration/output_power_test/output_power_test.json +13 -0
- brg_certificate/tests/calibration/output_power_test/output_power_test.py +28 -0
- brg_certificate/tests/calibration/pattern_test/pattern_test.json +13 -0
- brg_certificate/tests/calibration/pattern_test/pattern_test.py +70 -0
- brg_certificate/tests/datapath/adaptive_pacer_algo_test/adaptive_pacer_algo_test.json +13 -0
- brg_certificate/tests/datapath/adaptive_pacer_algo_test/adaptive_pacer_algo_test.py +76 -0
- brg_certificate/tests/datapath/num_of_tags_test/num_of_tags_test.json +13 -0
- brg_certificate/tests/datapath/num_of_tags_test/num_of_tags_test.py +83 -0
- brg_certificate/tests/datapath/output_power_test/output_power_test.json +13 -0
- brg_certificate/tests/datapath/output_power_test/output_power_test.py +27 -0
- brg_certificate/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.json +13 -0
- brg_certificate/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.py +43 -0
- brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.json +13 -0
- brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.py +63 -0
- brg_certificate/tests/datapath/pacer_interval_test/pacer_interval_test.json +13 -0
- brg_certificate/tests/datapath/pacer_interval_test/pacer_interval_test.py +50 -0
- brg_certificate/tests/datapath/pattern_test/pattern_test.json +13 -0
- brg_certificate/tests/datapath/pattern_test/pattern_test.py +28 -0
- brg_certificate/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.json +13 -0
- brg_certificate/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.py +51 -0
- brg_certificate/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.json +13 -0
- brg_certificate/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.py +54 -0
- brg_certificate/tests/datapath/pkt_filter_test/pkt_filter_test.json +13 -0
- brg_certificate/tests/datapath/pkt_filter_test/pkt_filter_test.py +55 -0
- brg_certificate/tests/datapath/rssi_threshold_test/rssi_threshold_test.json +13 -0
- brg_certificate/tests/datapath/rssi_threshold_test/rssi_threshold_test.py +73 -0
- brg_certificate/tests/datapath/rx_channel_test/rx_channel_test.json +13 -0
- brg_certificate/tests/datapath/rx_channel_test/rx_channel_test.py +41 -0
- brg_certificate/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.json +21 -0
- brg_certificate/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.py +184 -0
- brg_certificate/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.json +21 -0
- brg_certificate/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.py +210 -0
- brg_certificate/tests/datapath/stress_gen3_test/stress_gen3_test.json +30 -0
- brg_certificate/tests/datapath/stress_gen3_test/stress_gen3_test.py +203 -0
- brg_certificate/tests/datapath/stress_test/stress_test.json +30 -0
- brg_certificate/tests/datapath/stress_test/stress_test.py +210 -0
- brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.json +13 -0
- brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.py +113 -0
- brg_certificate/tests/datapath/tx_repetition_test/tx_repetition_test.json +13 -0
- brg_certificate/tests/datapath/tx_repetition_test/tx_repetition_test.py +79 -0
- brg_certificate/tests/edge_mgmt/actions_test/actions_test.json +13 -0
- brg_certificate/tests/edge_mgmt/actions_test/actions_test.py +432 -0
- brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.json +13 -0
- brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.py +94 -0
- brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.json +13 -0
- brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.py +87 -0
- brg_certificate/tests/edge_mgmt/leds_test/leds_test.json +13 -0
- brg_certificate/tests/edge_mgmt/leds_test/leds_test.py +210 -0
- brg_certificate/tests/edge_mgmt/ota_test/ota_test.json +13 -0
- brg_certificate/tests/edge_mgmt/ota_test/ota_test.py +83 -0
- brg_certificate/tests/edge_mgmt/stat_test/stat_test.json +13 -0
- brg_certificate/tests/edge_mgmt/stat_test/stat_test.py +48 -0
- brg_certificate/tests/energy2400/duty_cycle_test/duty_cycle_test.json +13 -0
- brg_certificate/tests/energy2400/duty_cycle_test/duty_cycle_test.py +26 -0
- brg_certificate/tests/energy2400/output_power_test/output_power_test.json +13 -0
- brg_certificate/tests/energy2400/output_power_test/output_power_test.py +27 -0
- brg_certificate/tests/energy2400/pattern_test/pattern_test.json +13 -0
- brg_certificate/tests/energy2400/pattern_test/pattern_test.py +28 -0
- brg_certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.json +13 -0
- brg_certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.py +398 -0
- brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.json +13 -0
- brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.py +153 -0
- brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.json +13 -0
- brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.py +264 -0
- brg_certificate/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.json +13 -0
- brg_certificate/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.py +27 -0
- brg_certificate/tests/energy_sub1g/pattern_test/pattern_test.json +13 -0
- brg_certificate/tests/energy_sub1g/pattern_test/pattern_test.py +26 -0
- brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.json +13 -0
- brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.py +397 -0
- brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.json +13 -0
- brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.py +27 -0
- brg_certificate/wltPb_pb2.py +72 -0
- brg_certificate/wltPb_pb2.pyi +227 -0
- brg_certificate/wlt_types.py +114 -0
- gw_certificate/api/extended_api.py +7 -1531
- gw_certificate/api_if/200/data.json +106 -0
- gw_certificate/api_if/200/logs.json +12 -0
- gw_certificate/api_if/200/status.json +47 -0
- gw_certificate/api_if/201/data.json +98 -0
- gw_certificate/api_if/201/logs.json +12 -0
- gw_certificate/api_if/201/status.json +53 -0
- gw_certificate/api_if/202/data.json +83 -0
- gw_certificate/api_if/202/logs.json +12 -0
- gw_certificate/api_if/202/status.json +60 -0
- gw_certificate/api_if/203/data.json +85 -0
- gw_certificate/api_if/203/logs.json +12 -0
- gw_certificate/api_if/203/status.json +63 -0
- gw_certificate/api_if/204/data.json +85 -0
- gw_certificate/api_if/204/logs.json +12 -0
- gw_certificate/api_if/204/status.json +63 -0
- gw_certificate/api_if/205/data.json +85 -0
- gw_certificate/api_if/205/logs.json +12 -0
- gw_certificate/api_if/205/status.json +63 -0
- gw_certificate/api_if/api_validation.py +0 -2
- gw_certificate/common/analysis_data_bricks.py +18 -1413
- gw_certificate/common/debug.py +0 -21
- gw_certificate/common/utils.py +1 -212
- gw_certificate/common/utils_defines.py +0 -87
- gw_certificate/gw_certificate.py +9 -7
- gw_certificate/gw_certificate_cli.py +39 -23
- gw_certificate/interface/4.4.52_app.zip +0 -0
- gw_certificate/interface/4.4.52_sd_bl_app.zip +0 -0
- gw_certificate/interface/ble_simulator.py +0 -32
- gw_certificate/interface/if_defines.py +1 -0
- gw_certificate/interface/mqtt.py +96 -19
- 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 -82
- gw_certificate/interface/uart_if.py +73 -43
- gw_certificate/templates/results.html +1 -1
- gw_certificate/tests/__init__.py +1 -2
- gw_certificate/tests/actions.py +134 -9
- gw_certificate/tests/connection.py +10 -5
- gw_certificate/tests/downlink.py +2 -4
- gw_certificate/tests/generic.py +62 -12
- gw_certificate/tests/registration.py +78 -27
- gw_certificate/tests/static/generated_packet_table.py +12 -48
- gw_certificate/tests/static/packet_table.csv +10048 -10048
- gw_certificate/tests/static/references.py +2 -1
- gw_certificate/tests/static/uplink_defines.py +0 -7
- gw_certificate/tests/throughput.py +7 -12
- gw_certificate/tests/uplink.py +83 -43
- {wiliot_certificate-1.3.0a1.dist-info → wiliot_certificate-1.4.0a2.dist-info}/METADATA +59 -8
- wiliot_certificate-1.4.0a2.dist-info/RECORD +198 -0
- {wiliot_certificate-1.3.0a1.dist-info → wiliot_certificate-1.4.0a2.dist-info}/WHEEL +1 -1
- wiliot_certificate-1.4.0a2.dist-info/entry_points.txt +3 -0
- wiliot_certificate-1.4.0a2.dist-info/top_level.txt +2 -0
- gw_certificate/interface/packet_error.py +0 -22
- wiliot_certificate-1.3.0a1.dist-info/RECORD +0 -51
- wiliot_certificate-1.3.0a1.dist-info/entry_points.txt +0 -2
- wiliot_certificate-1.3.0a1.dist-info/top_level.txt +0 -1
- {wiliot_certificate-1.3.0a1.dist-info → wiliot_certificate-1.4.0a2.dist-info}/LICENSE +0 -0
gw_certificate/interface/mqtt.py
CHANGED
|
@@ -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
|
|
288
|
-
self.
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
LATEST_VERSION_FILE = f'{LATEST_VERSION}
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
87
|
-
|
|
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
|
-
|
|
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
|
|
149
|
-
|
|
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.
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
|
183
|
-
|
|
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 |
|
|
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
|
gw_certificate/tests/__init__.py
CHANGED
|
@@ -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
|
-
|
|
11
|
-
TESTS_NO_UART = [RegistrationTest, ActionsTest]
|
|
10
|
+
TESTS_NO_UART = [RegistrationTest]
|