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
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
# from http import client
|
|
2
|
+
import paho.mqtt.client as mqtt
|
|
3
|
+
import ssl
|
|
4
|
+
import time
|
|
5
|
+
import os
|
|
6
|
+
import json
|
|
7
|
+
import datetime
|
|
8
|
+
import base64
|
|
9
|
+
import copy
|
|
10
|
+
import traceback
|
|
11
|
+
import brg_certificate.wltPb_pb2 as wpb
|
|
12
|
+
from google.protobuf.message import DecodeError
|
|
13
|
+
from google.protobuf.json_format import MessageToDict
|
|
14
|
+
|
|
15
|
+
# Local imports
|
|
16
|
+
from brg_certificate.wlt_types import *
|
|
17
|
+
from brg_certificate.cert_data_sim import PIXEL_SIM_INDICATOR, TAG_ID_OFFSET
|
|
18
|
+
from brg_certificate.cert_prints import *
|
|
19
|
+
from brg_certificate.cert_defines import *
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
SENSORS_DATA_SI_DUP = 6
|
|
23
|
+
|
|
24
|
+
class WltMqttPkt:
|
|
25
|
+
def __init__(self, body, topic, userdata):
|
|
26
|
+
self.body = body
|
|
27
|
+
self.mqtt_topic = topic
|
|
28
|
+
self.mqtt_timestamp = datetime.datetime.now()
|
|
29
|
+
self.body_ex = {}
|
|
30
|
+
if "data" in self.mqtt_topic:
|
|
31
|
+
self.body_ex = copy.deepcopy(body)
|
|
32
|
+
self.body_ex['undecrypted'] = 0
|
|
33
|
+
for pkt in self.body_ex[PACKETS]:
|
|
34
|
+
# if packet is not a mgmt packet or a side info packet it is a data packet
|
|
35
|
+
wlt_pkt = WltPkt(pkt[PAYLOAD])
|
|
36
|
+
if wlt_pkt.pkt != None:
|
|
37
|
+
if wlt_pkt.hdr.group_id == ag.GROUP_ID_BRG2GW:
|
|
38
|
+
pkt[MGMT_PKT] = copy.deepcopy(wlt_pkt)
|
|
39
|
+
elif wlt_pkt.data_hdr.group_id_major in ag.UNIFIED_GROUP_ID_LIST:
|
|
40
|
+
pkt[UNIFIED_PKT] = copy.deepcopy(wlt_pkt)
|
|
41
|
+
if PIXEL_SIM_INDICATOR in pkt[PAYLOAD]:
|
|
42
|
+
pkt[DECODED_DATA] = {TAG_ID: pkt[PAYLOAD][TAG_ID_OFFSET:TAG_ID_OFFSET+8], PACKET_TYPE: wlt_pkt.data_hdr.pkt_type, PACKET_CNTR: 0}
|
|
43
|
+
elif userdata["data"] != DATA_SIMULATION:
|
|
44
|
+
pkt[DECODED_DATA] = self.handle_data_pkt(wlt_pkt.dump())
|
|
45
|
+
elif wlt_pkt.hdr.group_id == ag.GROUP_ID_SIDE_INFO_SENSOR:
|
|
46
|
+
pkt[SIDE_INFO_SENSOR_PKT] = copy.deepcopy(wlt_pkt)
|
|
47
|
+
elif wlt_pkt.hdr.uuid_lsb == ag.HDR_DEFAULT_BRG_SENSOR_UUID_LSB and wlt_pkt.hdr.uuid_msb == ag.HDR_DEFAULT_BRG_SENSOR_UUID_MSB:
|
|
48
|
+
pkt[SENSOR_PKT] = copy.deepcopy(wlt_pkt)
|
|
49
|
+
pkt[DECODED_DATA] = {TAG_ID: None, PACKET_CNTR: None, PACKET_TYPE: None}
|
|
50
|
+
else:
|
|
51
|
+
if userdata["data"] != DATA_SIMULATION:
|
|
52
|
+
pkt[DECODED_DATA] = self.handle_data_pkt(pkt)
|
|
53
|
+
|
|
54
|
+
def handle_data_pkt(self, pkt):
|
|
55
|
+
p, dec_data = "", {TAG_ID: None, PACKET_CNTR: None, PACKET_TYPE: None}
|
|
56
|
+
if type(pkt) == str:
|
|
57
|
+
p = pkt
|
|
58
|
+
else:
|
|
59
|
+
p = pkt[PAYLOAD]
|
|
60
|
+
resolve = local_resolve(p) if p else None
|
|
61
|
+
if resolve:
|
|
62
|
+
for key in dec_data:
|
|
63
|
+
if key in resolve[DECODED_DATA]:
|
|
64
|
+
dec_data[key] = resolve[DECODED_DATA][key]
|
|
65
|
+
else:
|
|
66
|
+
self.body_ex['undecrypted'] += 1
|
|
67
|
+
return dec_data
|
|
68
|
+
|
|
69
|
+
class WltMqttPkts:
|
|
70
|
+
def __init__(self):
|
|
71
|
+
self.data = []
|
|
72
|
+
self.status = []
|
|
73
|
+
self.update = []
|
|
74
|
+
self.all = []
|
|
75
|
+
def insert(self, pkt):
|
|
76
|
+
self.all.append(pkt)
|
|
77
|
+
if "data" in pkt.mqtt_topic:
|
|
78
|
+
self.data.append(pkt)
|
|
79
|
+
elif "status" in pkt.mqtt_topic:
|
|
80
|
+
self.status.append(pkt)
|
|
81
|
+
elif "update" in pkt.mqtt_topic:
|
|
82
|
+
self.update.append(pkt)
|
|
83
|
+
def flush(self):
|
|
84
|
+
self.all = []
|
|
85
|
+
self.data = []
|
|
86
|
+
self.status = []
|
|
87
|
+
self.update = []
|
|
88
|
+
def flush_data(self):
|
|
89
|
+
self.data = []
|
|
90
|
+
def flush_status(self):
|
|
91
|
+
self.status = []
|
|
92
|
+
|
|
93
|
+
def local_resolve(p):
|
|
94
|
+
import brg_certificate.ut.ut_resolve as ut_resolve
|
|
95
|
+
irresolvable_payloads = ["1E16C6FC0000EE", "1E16AFFD0000EC", "1E16C6FC0000EC"]
|
|
96
|
+
try:
|
|
97
|
+
if any(substring in p for substring in irresolvable_payloads):
|
|
98
|
+
# brg2gw mgmt pkt - skip
|
|
99
|
+
return None
|
|
100
|
+
elif p.startswith("1E16"):
|
|
101
|
+
payload = p
|
|
102
|
+
elif p.startswith("2916"):
|
|
103
|
+
payload = '26' + p[2:-6] # change 29 to 26 and remove side info
|
|
104
|
+
else:
|
|
105
|
+
payload = "1E16" + p
|
|
106
|
+
group_id_minor = int(p[8:10], 16)
|
|
107
|
+
if group_id_minor == 0x05 or group_id_minor == 0xFE: # BLE5 group id minor
|
|
108
|
+
version=3.0
|
|
109
|
+
else:
|
|
110
|
+
version=2.4
|
|
111
|
+
resolve = ut_resolve.DecryptedPacket(ut_resolve.convert_cloud_to_packet(payload), packet_version_by_user=version)
|
|
112
|
+
return {PACKET_DATA:resolve.packet_data, DECODED_DATA:resolve.decoded_data, GW_DATA:resolve.gw_data}
|
|
113
|
+
except Exception as e:
|
|
114
|
+
print(traceback.format_exc())
|
|
115
|
+
print(e)
|
|
116
|
+
print(f"Failed in local_resolve with packet: {p}\n")
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
def is_json(msg):
|
|
120
|
+
is_utf = True
|
|
121
|
+
try:
|
|
122
|
+
json.loads(msg.decode("utf-8"))
|
|
123
|
+
except:
|
|
124
|
+
is_utf = False
|
|
125
|
+
return is_utf
|
|
126
|
+
|
|
127
|
+
def on_connect(mqttc, userdata, flags, rc):
|
|
128
|
+
print("python_mqtt_connect, rc: " + str(rc))
|
|
129
|
+
|
|
130
|
+
def on_disconnect(mqttc, userdata, rc):
|
|
131
|
+
txt = f"ERROR: python_mqtt_disconnect, rc: {rc} {mqtt.error_string(rc)}"
|
|
132
|
+
print(txt)
|
|
133
|
+
write_to_mqtt_log_file(txt)
|
|
134
|
+
|
|
135
|
+
def on_subscribe(mqttc, userdata, mid, granted_qos):
|
|
136
|
+
print("python_mqtt_subscribe, " + str(mid) + " " + str(granted_qos))
|
|
137
|
+
|
|
138
|
+
def on_unsubscribe(mqttc, userdata, mid):
|
|
139
|
+
print("ERROR: python_mqtt_unsubscribe, " + str(mid))
|
|
140
|
+
|
|
141
|
+
def on_message(mqttc, userdata, message):
|
|
142
|
+
if is_json(message.payload):
|
|
143
|
+
on_message_json(mqttc, userdata, message)
|
|
144
|
+
else:
|
|
145
|
+
on_message_protobuf(mqttc, userdata, message)
|
|
146
|
+
|
|
147
|
+
def on_message_json(mqttc, userdata, message):
|
|
148
|
+
wlt_mqtt_pkts = userdata[PKTS]
|
|
149
|
+
data = json.loads(message.payload.decode("utf-8"))
|
|
150
|
+
wlt_mqtt_pkts.insert(WltMqttPkt(data, message.topic, userdata))
|
|
151
|
+
write_to_mqtt_log_file("// JSON message received at {}, topic={}:\n{}\n".format(datetime.datetime.now().strftime("%d/%m/%Y, %H:%M:%S"), message.topic, str(message.payload.decode("utf-8"))))
|
|
152
|
+
|
|
153
|
+
def on_message_protobuf(mqttc, userdata, message):
|
|
154
|
+
pb_msg = None
|
|
155
|
+
pb_decoded = False
|
|
156
|
+
|
|
157
|
+
# Decode message according to the schema used on each topic
|
|
158
|
+
if 'status' in message.topic:
|
|
159
|
+
pb_msg = wpb.UplinkMessage()
|
|
160
|
+
elif 'data' in message.topic:
|
|
161
|
+
pb_msg = wpb.GatewayData()
|
|
162
|
+
elif 'update' in message.topic:
|
|
163
|
+
pb_msg = wpb.DownlinkMessage()
|
|
164
|
+
try:
|
|
165
|
+
pb_msg.ParseFromString(message.payload)
|
|
166
|
+
pb_decoded = True
|
|
167
|
+
except DecodeError as e:
|
|
168
|
+
print(f'ERROR: failed decoding {message.topic} message: \n{e}\n')
|
|
169
|
+
|
|
170
|
+
if pb_decoded is True:
|
|
171
|
+
pb_msg_dict = MessageToDict(pb_msg)
|
|
172
|
+
# Align formats with JSON (bytes to hex strings)
|
|
173
|
+
if 'data' in message.topic and PACKETS in pb_msg_dict.keys():
|
|
174
|
+
for idx, pkt in enumerate(pb_msg_dict[PACKETS]):
|
|
175
|
+
pb_msg_dict[PACKETS][idx][PAYLOAD] = base64.b64decode(pkt[PAYLOAD]).hex().upper()
|
|
176
|
+
pb_msg_dict[PACKETS][idx][TIMESTAMP] = int(pkt[TIMESTAMP])
|
|
177
|
+
if 'update' in message.topic:
|
|
178
|
+
if TX_PKT in pb_msg_dict.keys():
|
|
179
|
+
pb_msg_dict[TX_PKT][PAYLOAD] = base64.b64decode(pb_msg_dict[TX_PKT][PAYLOAD]).hex().upper()
|
|
180
|
+
elif BRG_UPGRADE in pb_msg_dict.keys():
|
|
181
|
+
pb_msg_dict[BRG_UPGRADE][REBOOT_PKT] = base64.b64decode(pb_msg_dict[BRG_UPGRADE][REBOOT_PKT]).hex().upper()
|
|
182
|
+
|
|
183
|
+
# Push & log
|
|
184
|
+
wlt_mqtt_pkts = userdata[PKTS]
|
|
185
|
+
wlt_mqtt_pkts.insert(WltMqttPkt(pb_msg_dict, message.topic, userdata))
|
|
186
|
+
write_to_mqtt_log_file("// Protobuf message {} at {}, topic={}:\n{}\n".format('published' if 'update' in message.topic else 'received',
|
|
187
|
+
datetime.datetime.now().strftime("%d/%m/%Y, %H:%M:%S"), message.topic, json.dumps(pb_msg_dict, indent=4)))
|
|
188
|
+
|
|
189
|
+
def pkts_to_log(pkts):
|
|
190
|
+
text = ""
|
|
191
|
+
for p in pkts:
|
|
192
|
+
text += "// {} topic={}".format(p.mqtt_timestamp.strftime("%d/%m/%Y, %H:%M:%S"), p.mqtt_topic)
|
|
193
|
+
text += "\n"+json.dumps(p.body, indent=4)+"\n"
|
|
194
|
+
return text
|
|
195
|
+
|
|
196
|
+
def write_to_log_file(file_name, pkts):
|
|
197
|
+
f = open(os.path.join(BASE_DIR, file_name), "w")
|
|
198
|
+
f.write(pkts_to_log(pkts))
|
|
199
|
+
f.close()
|
|
200
|
+
|
|
201
|
+
def write_to_mqtt_log_file(txt):
|
|
202
|
+
f = open(os.path.join(BASE_DIR, CERT_MQTT_LOG_FILE), "a")
|
|
203
|
+
f.write(txt)
|
|
204
|
+
f.close()
|
|
205
|
+
|
|
206
|
+
def load_custom_broker(gw, rel_path="."):
|
|
207
|
+
f = open(os.path.join(BASE_DIR, rel_path, "config", "eclipse.json"))
|
|
208
|
+
# f = open(os.path.join(BASE_DIR, rel_path, "config", "hivemq.json"))
|
|
209
|
+
# f = open(os.path.join(BASE_DIR, rel_path, "config", "mosquitto.json"))
|
|
210
|
+
# f = open(os.path.join(BASE_DIR, rel_path, "config", "wiliot-dev.json"))
|
|
211
|
+
data = json.load(f)
|
|
212
|
+
data[CUSTOM_BROKER_UPDATE_TOPIC] += gw
|
|
213
|
+
data[CUSTOM_BROKER_STATUS_TOPIC] += gw
|
|
214
|
+
data[CUSTOM_BROKER_DATA_TOPIC] += gw
|
|
215
|
+
return data
|
|
216
|
+
|
|
217
|
+
def mqttc_init(gw_id, userdata={PKTS: WltMqttPkts()}, rel_path=".", data=DATA_REAL_TAGS):
|
|
218
|
+
|
|
219
|
+
custom_broker = load_custom_broker(gw=gw_id, rel_path=rel_path)
|
|
220
|
+
client_id = '{}-republish'.format(gw_id)
|
|
221
|
+
userdata["data"] = data
|
|
222
|
+
mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, client_id, userdata=userdata)
|
|
223
|
+
mqttc.username_pw_set(custom_broker[CUSTOM_BROKER_USERNAME], custom_broker[CUSTOM_BROKER_PASSWORD])
|
|
224
|
+
mqttc.on_message = on_message
|
|
225
|
+
mqttc.on_connect = on_connect
|
|
226
|
+
mqttc.on_disconnect = on_disconnect
|
|
227
|
+
mqttc.on_subscribe = on_subscribe
|
|
228
|
+
mqttc.on_unsubscribe = on_unsubscribe
|
|
229
|
+
if not 1883 == custom_broker[CUSTOM_BROKER_PORT]:
|
|
230
|
+
mqttc.tls_set(tls_version=ssl.PROTOCOL_TLSv1_2)
|
|
231
|
+
mqttc.connect(custom_broker[CUSTOM_BROKER_BROKER_URL].replace("mqtts://", ""), port=custom_broker[CUSTOM_BROKER_PORT], keepalive=60)
|
|
232
|
+
mqttc.loop_start()
|
|
233
|
+
|
|
234
|
+
mqttc.update_topic = custom_broker[CUSTOM_BROKER_UPDATE_TOPIC]
|
|
235
|
+
mqttc.subscribe(mqttc.update_topic)
|
|
236
|
+
mqttc.data_topic = custom_broker[CUSTOM_BROKER_DATA_TOPIC]
|
|
237
|
+
mqttc.subscribe(mqttc.data_topic)
|
|
238
|
+
mqttc.status_topic = custom_broker[CUSTOM_BROKER_STATUS_TOPIC]
|
|
239
|
+
mqttc.subscribe(mqttc.status_topic)
|
|
240
|
+
|
|
241
|
+
mqttc.flush_pkts = mqttc._userdata[PKTS].flush
|
|
242
|
+
mqttc.flush_data_pkts = mqttc._userdata[PKTS].flush_data
|
|
243
|
+
mqttc.flush_status_pkts = mqttc._userdata[PKTS].flush_status
|
|
244
|
+
time.sleep(2)
|
|
245
|
+
|
|
246
|
+
return mqttc
|
|
247
|
+
|
|
248
|
+
def dump_pkts(test, log):
|
|
249
|
+
write_to_log_file(os.path.join(test.dir, MQTT_LOG_PRE_STR+log+"_all.json"), test.mqttc._userdata[PKTS].all)
|
|
250
|
+
write_to_log_file(os.path.join(test.dir, MQTT_LOG_PRE_STR+log+"_data.json"), test.mqttc._userdata[PKTS].data)
|
|
251
|
+
write_to_log_file(os.path.join(test.dir, MQTT_LOG_PRE_STR+log+"_status.json"), test.mqttc._userdata[PKTS].status)
|
|
252
|
+
write_to_log_file(os.path.join(test.dir, MQTT_LOG_PRE_STR+log+"_update.json"), test.mqttc._userdata[PKTS].update)
|
|
253
|
+
|
|
254
|
+
# Get data/tags functions
|
|
255
|
+
def get_all_data_pkts(mqttc):
|
|
256
|
+
data_pkts = []
|
|
257
|
+
for p in mqttc._userdata[PKTS].data:
|
|
258
|
+
gw_id = p.body_ex[GW_ID] if GW_ID in p.body_ex else ""
|
|
259
|
+
if PACKETS in p.body_ex:
|
|
260
|
+
for pkt in p.body_ex[PACKETS]:
|
|
261
|
+
pkt[GW_ID] = gw_id
|
|
262
|
+
data_pkts += [pkt]
|
|
263
|
+
return data_pkts
|
|
264
|
+
|
|
265
|
+
def get_all_sim_data_pkts(mqttc):
|
|
266
|
+
data_pkts = []
|
|
267
|
+
for p in mqttc._userdata[PKTS].data:
|
|
268
|
+
gw_id = p.body_ex[GW_ID] if GW_ID in p.body_ex else ""
|
|
269
|
+
if PACKETS in p.body_ex:
|
|
270
|
+
for pkt in p.body_ex[PACKETS]:
|
|
271
|
+
if PIXEL_SIM_INDICATOR in pkt[PAYLOAD]:
|
|
272
|
+
pkt[GW_ID] = gw_id
|
|
273
|
+
data_pkts += [pkt]
|
|
274
|
+
return data_pkts
|
|
275
|
+
|
|
276
|
+
def get_undecrypted_data_pkts_count(mqttc):
|
|
277
|
+
undecrypted = 0
|
|
278
|
+
for p in mqttc._userdata[PKTS].data:
|
|
279
|
+
if 'undecrypted' in p.body_ex:
|
|
280
|
+
undecrypted += p.body_ex['undecrypted']
|
|
281
|
+
return undecrypted
|
|
282
|
+
|
|
283
|
+
def get_all_sensor_pkts(mqttc, test, is_embedded=False):
|
|
284
|
+
all_sensor_pkts = couple_sensor_data_si_coupling(test)
|
|
285
|
+
all_sensor_pkts = [p for p in all_sensor_pkts if test.active_brg.id_str == p[BRIDGE_ID] and (p[IS_EMBEDDED] == is_embedded)]
|
|
286
|
+
return all_sensor_pkts
|
|
287
|
+
|
|
288
|
+
def couple_sensor_data_si_coupling(test):
|
|
289
|
+
all_pkts = get_all_data_pkts(test.mqttc)
|
|
290
|
+
all_sensor_data_pkts = [p for p in all_pkts if SENSOR_PKT in p]
|
|
291
|
+
all_sensor_side_info_pkts = [p for p in all_pkts if SIDE_INFO_SENSOR_PKT in p]
|
|
292
|
+
# Couple data and side info
|
|
293
|
+
coupled_sensor_pkts = []
|
|
294
|
+
for p_data in all_sensor_data_pkts:
|
|
295
|
+
for p_si in all_sensor_side_info_pkts:
|
|
296
|
+
data_pkt = p_data[SENSOR_PKT].pkt
|
|
297
|
+
si_pkt = p_si[SIDE_INFO_SENSOR_PKT].pkt
|
|
298
|
+
# Packet not coupled yet and (same pkt id & timestamp diff < 1 sec)
|
|
299
|
+
if (not coupled_pkt_exists(coupled_sensor_pkts, p_si) and
|
|
300
|
+
data_pkt.pkt_id == si_pkt.pkt_id and abs(p_data[TIMESTAMP] - p_si[TIMESTAMP]) < 1000):
|
|
301
|
+
p_coupled = {
|
|
302
|
+
TIMESTAMP : p_data[TIMESTAMP],
|
|
303
|
+
SEQUENCE_ID : str(p_data[SEQUENCE_ID]),
|
|
304
|
+
NFPKT : si_pkt.nfpkt,
|
|
305
|
+
RSSI : si_pkt.rssi,
|
|
306
|
+
IS_SENSOR : si_pkt.is_sensor,
|
|
307
|
+
IS_EMBEDDED : si_pkt.is_sensor_embedded,
|
|
308
|
+
IS_SCRAMBLED : si_pkt.is_scrambled,
|
|
309
|
+
SENSOR_ID : hex(si_pkt.sensor_mac)[2:].upper(),
|
|
310
|
+
SENSOR_UUID : "{:02X}{:02X}{:02X}".format(si_pkt.sensor_ad_type, si_pkt.sensor_uuid_msb, si_pkt.sensor_uuid_lsb),
|
|
311
|
+
BRIDGE_ID: "{:012X}".format(si_pkt.brg_mac),
|
|
312
|
+
PAYLOAD: p_data[PAYLOAD],
|
|
313
|
+
SENSOR_PKT: p_data[SENSOR_PKT],
|
|
314
|
+
}
|
|
315
|
+
coupled_sensor_pkts += [p_coupled]
|
|
316
|
+
# Count the number of packet duplications:
|
|
317
|
+
count_pkt_id_duplications(test, all_sensor_data_pkts, all_sensor_side_info_pkts, coupled_sensor_pkts)
|
|
318
|
+
return coupled_sensor_pkts
|
|
319
|
+
|
|
320
|
+
def coupled_pkt_exists(coupled_list, pkt):
|
|
321
|
+
for coupled_pkt in coupled_list:
|
|
322
|
+
if ((abs(coupled_pkt[TIMESTAMP] - pkt[TIMESTAMP]) < 1000) and
|
|
323
|
+
coupled_pkt[SENSOR_PKT].pkt.pkt_id == pkt[SIDE_INFO_SENSOR_PKT].pkt.pkt_id):
|
|
324
|
+
return True
|
|
325
|
+
return False
|
|
326
|
+
|
|
327
|
+
def count_pkt_id_duplications(test, all_sensor_data_pkts, all_sensor_side_info_pkts, all_coupled_pkts):
|
|
328
|
+
pkt_ids = [p_data[SENSOR_PKT].pkt.pkt_id for p_data in all_sensor_data_pkts]
|
|
329
|
+
pkt_ids += [p_si[SIDE_INFO_SENSOR_PKT].pkt.pkt_id for p_si in all_sensor_side_info_pkts]
|
|
330
|
+
for coupled_pkt in all_coupled_pkts:
|
|
331
|
+
_pkt_id = coupled_pkt[SENSOR_PKT].pkt.pkt_id
|
|
332
|
+
coupled_pkt[PKT_ID_CTR] = pkt_ids.count(_pkt_id)
|
|
333
|
+
if coupled_pkt[PKT_ID_CTR] > SENSORS_DATA_SI_DUP:
|
|
334
|
+
print(f"pkt_id {_pkt_id:08X}: {coupled_pkt[PKT_ID_CTR]} occurrences")
|
|
335
|
+
test.reason = f'Warning: {coupled_pkt[PKT_ID_CTR]} sensor data and si with pkt id 0x{_pkt_id:08X}'
|
|
336
|
+
|
|
337
|
+
def get_all_brg1_ext_sensor_pkts(mqttc, test=None):
|
|
338
|
+
test.active_brg = test.brg1
|
|
339
|
+
pkts = get_all_sensor_pkts(mqttc, test)
|
|
340
|
+
test.active_brg = test.brg0
|
|
341
|
+
return pkts
|
|
342
|
+
|
|
343
|
+
def get_all_custom_pkts(mqttc, test=None):
|
|
344
|
+
return get_all_sensor_pkts(mqttc, test, is_embedded=True)
|
|
345
|
+
|
|
346
|
+
def get_all_mgmt_pkts(mqttc):
|
|
347
|
+
all_data_pkts = get_all_data_pkts(mqttc)
|
|
348
|
+
return [p for p in all_data_pkts if MGMT_PKT in p]
|
|
349
|
+
|
|
350
|
+
def get_brg2gw_mgmt_pkts(mqttc, test=None, mgmt_types=[]):
|
|
351
|
+
brg2gw_mgmt_pkts = [p for p in get_all_mgmt_pkts(mqttc) if ((p[MGMT_PKT].hdr.group_id == ag.GROUP_ID_BRG2GW) and
|
|
352
|
+
(not mgmt_types or type(p[MGMT_PKT].pkt) in mgmt_types))]
|
|
353
|
+
pkts = [p for p in brg2gw_mgmt_pkts if test.active_brg.id_str in p[PAYLOAD]]
|
|
354
|
+
return pkts
|
|
355
|
+
|
|
356
|
+
def get_unified_data_pkts(test):
|
|
357
|
+
all_unified_pkts, pkts = [], get_all_sim_data_pkts(test.mqttc) if test.data == DATA_SIMULATION else get_all_data_pkts(test.mqttc)
|
|
358
|
+
for p in pkts:
|
|
359
|
+
if UNIFIED_PKT in p:
|
|
360
|
+
all_unified_pkts += [p]
|
|
361
|
+
pkts = all_unified_pkts
|
|
362
|
+
pkts = [p for p in all_unified_pkts if p[ALIAS_BRIDGE_ID] == test.active_brg.id_alias]
|
|
363
|
+
print(f"\nCollected {len(pkts)} unified data pkts")
|
|
364
|
+
return pkts
|
|
365
|
+
|
|
366
|
+
def get_internal_brg_unified_data_pkts(test):
|
|
367
|
+
all_unified_pkts, pkts = [], get_all_sim_data_pkts(test.mqttc) if test.data == DATA_SIMULATION else get_all_data_pkts(test.mqttc)
|
|
368
|
+
for p in pkts:
|
|
369
|
+
if UNIFIED_PKT in p:
|
|
370
|
+
all_unified_pkts += [p]
|
|
371
|
+
pkts = [p for p in all_unified_pkts if p[ALIAS_BRIDGE_ID] == test.internal_id_alias()]
|
|
372
|
+
print(f"\nCollected {len(pkts)} unified gw_tag_pkts")
|
|
373
|
+
return pkts
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
from brg_certificate.cert_defines import *
|
|
2
|
+
import time, datetime
|
|
3
|
+
import sys
|
|
4
|
+
import json
|
|
5
|
+
import brg_certificate.cert_mqtt as cert_mqtt
|
|
6
|
+
import brg_certificate.cert_data_sim as cert_data_sim
|
|
7
|
+
import os
|
|
8
|
+
import re
|
|
9
|
+
|
|
10
|
+
COLORS = {
|
|
11
|
+
"HEADER" : '\033[95m',
|
|
12
|
+
"BLUE" : '\033[94m',
|
|
13
|
+
"CYAN" : '\033[96m',
|
|
14
|
+
"GREEN" : '\033[92m',
|
|
15
|
+
"WARNING" : '\033[93m',
|
|
16
|
+
"RED" : '\033[91m',
|
|
17
|
+
"ENDC" : '\033[0m',
|
|
18
|
+
"BOLD" : '\033[1m',
|
|
19
|
+
"UNDERLINE" : '\033[4m',
|
|
20
|
+
}
|
|
21
|
+
color = lambda c, t : COLORS["BOLD"]+COLORS[c]+t+COLORS["ENDC"]
|
|
22
|
+
pipeline_running = lambda : True if 'BITBUCKET_BUILD_NUMBER' in os.environ else False
|
|
23
|
+
camelcase_to_title = lambda s: ' '.join(word.capitalize() for word in re.split('(?=[A-Z])', s))
|
|
24
|
+
SEP = '\n' + '#'*100 + '\n'
|
|
25
|
+
WIL_UT_TEXT = r'''
|
|
26
|
+
__ _____ _ ___ ___ _____ _ _ _____
|
|
27
|
+
\ \ / /_ _| | |_ _/ _ \_ _| | | | |_ _|
|
|
28
|
+
\ \/\/ / | || |__ | | (_) || | | |_| | | |
|
|
29
|
+
\_/\_/ |___|____|___\___/ |_| \___/ |_|
|
|
30
|
+
'''
|
|
31
|
+
|
|
32
|
+
hex_str2int = lambda s : int(s, 16)
|
|
33
|
+
print_brg = lambda brg: brg.__dict__ if brg else None
|
|
34
|
+
|
|
35
|
+
def print_pkt(p):
|
|
36
|
+
print(datetime.datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))
|
|
37
|
+
print(json.dumps(p, indent=4, default=lambda o: o.__dict__, sort_keys=True))
|
|
38
|
+
|
|
39
|
+
def print_warn(txt):
|
|
40
|
+
if txt:
|
|
41
|
+
utPrint(f"WARNING: {txt}","WARNING")
|
|
42
|
+
|
|
43
|
+
def mqtt_scan_start(test, duration):
|
|
44
|
+
utPrint("Scanning mqtt packets on {} for {} seconds...".format(test.gw, duration), "WARNING")
|
|
45
|
+
sys.stdout.flush()
|
|
46
|
+
|
|
47
|
+
def mqtt_scan_wait(test, duration):
|
|
48
|
+
utPrint("Scanning mqtt packets on {} for {} seconds...".format(test.gw, duration), "WARNING")
|
|
49
|
+
sys.stdout.flush()
|
|
50
|
+
chars = ["|", "/", "-", "\\"]
|
|
51
|
+
start_time = datetime.datetime.now()
|
|
52
|
+
i = 0
|
|
53
|
+
while True:
|
|
54
|
+
cur_duration = (datetime.datetime.now() - start_time).seconds
|
|
55
|
+
if cur_duration >= duration:
|
|
56
|
+
break
|
|
57
|
+
if pipeline_running():
|
|
58
|
+
sys.stdout.write(".")
|
|
59
|
+
else:
|
|
60
|
+
sys.stdout.write("\r"+chars[i%4]*20+" "+str(cur_duration)+" "+chars[i%4]*20+" {} pkts captured".format(len(test.mqttc._userdata["pkts"].data)))
|
|
61
|
+
sys.stdout.flush()
|
|
62
|
+
time.sleep(0.25)
|
|
63
|
+
i += 1
|
|
64
|
+
print("\n")
|
|
65
|
+
|
|
66
|
+
def print_update_wait(secs=1):
|
|
67
|
+
sys.stdout.write(".")
|
|
68
|
+
sys.stdout.flush()
|
|
69
|
+
time.sleep(secs)
|
|
70
|
+
|
|
71
|
+
def field_functionality_pass_fail_print(test, field, value=""):
|
|
72
|
+
print_string = "{}={}".format(field, value)
|
|
73
|
+
if value == "":
|
|
74
|
+
print_string = str(field)
|
|
75
|
+
if test.rc == TEST_FAILED:
|
|
76
|
+
utPrint(print_string + " functionality failed!", "RED")
|
|
77
|
+
elif test.rc == TEST_SKIPPED:
|
|
78
|
+
utPrint(print_string + " functionality skipped!", "WARNING")
|
|
79
|
+
else:
|
|
80
|
+
utPrint(print_string + " functionality passed!", "GREEN")
|
|
81
|
+
|
|
82
|
+
def test_run_print(test):
|
|
83
|
+
brg_txt = ""
|
|
84
|
+
if test.params:
|
|
85
|
+
params = " (params: {})".format(test.params)
|
|
86
|
+
else:
|
|
87
|
+
params = " (without params)"
|
|
88
|
+
if test.active_brg:
|
|
89
|
+
brg_txt = " ({}: {}".format("INTERNAL BRG" if test.internal_brg else "BRG", test.active_brg.id_str)
|
|
90
|
+
if test.brg1 and test.multi_brg:
|
|
91
|
+
brg_txt += " & " + test.brg1.id_str
|
|
92
|
+
brg_txt += ")"
|
|
93
|
+
log_txt = f"{SEP}==>> Running {test.module_name}{params}{brg_txt}{SEP}"
|
|
94
|
+
utPrint(log_txt, "BLUE")
|
|
95
|
+
utPrint("Test Information:\n", "HEADER")
|
|
96
|
+
test_json_print(test)
|
|
97
|
+
utPrint("Test Configuration:", "HEADER")
|
|
98
|
+
params = [{'name':p.name, 'value':p.value} for p in test.params]
|
|
99
|
+
utPrint(f""" - internal_brg={test.internal_brg}\n - brg0={print_brg(test.brg0)}
|
|
100
|
+
- brg1={print_brg(test.brg1)}\n - active_brg={print_brg(test.active_brg)}
|
|
101
|
+
- params={params}\n""")
|
|
102
|
+
cert_mqtt.write_to_mqtt_log_file(log_txt)
|
|
103
|
+
cert_data_sim.write_to_data_sim_log_file(log_txt)
|
|
104
|
+
|
|
105
|
+
def test_json_print(test):
|
|
106
|
+
for key, value in test.test_json.items():
|
|
107
|
+
if key == 'procedure':
|
|
108
|
+
print(f" {camelcase_to_title(key)}:")
|
|
109
|
+
for i in range(len(value)):
|
|
110
|
+
print(f" ({i}) {value[i]}")
|
|
111
|
+
else:
|
|
112
|
+
print(f" {camelcase_to_title(key)}: {value}")
|
|
113
|
+
|
|
114
|
+
def test_epilog_print(test):
|
|
115
|
+
if any([phase.rc == TEST_FAILED for phase in test.phases]):
|
|
116
|
+
utPrint(test.reason, "RED")
|
|
117
|
+
utPrint("==>> Test {} failed!".format(test.module_name), "RED")
|
|
118
|
+
else:
|
|
119
|
+
utPrint(test.reason, "GREEN")
|
|
120
|
+
utPrint("==>> Test {} passed!".format(test.module_name), "GREEN")
|
|
121
|
+
|
|
122
|
+
def functionality_run_print(func):
|
|
123
|
+
txt = "{0}==>> Running {1}\n".format(SEP, func)
|
|
124
|
+
utPrint(txt, "CYAN")
|
|
125
|
+
cert_mqtt.write_to_mqtt_log_file(txt)
|
|
126
|
+
cert_data_sim.write_to_data_sim_log_file(txt)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def generate_print_string(fields_and_values):
|
|
130
|
+
list_to_print = []
|
|
131
|
+
for f in fields_and_values:
|
|
132
|
+
list_to_print.append(str(f) + "=" + str(fields_and_values[f]))
|
|
133
|
+
return " & ".join(list_to_print)
|
|
134
|
+
|
|
135
|
+
def generate_log_file(test, val):
|
|
136
|
+
if type(val) == int or type(val) == str:
|
|
137
|
+
log_string = str(val)
|
|
138
|
+
else:
|
|
139
|
+
log_string = str(val[0])
|
|
140
|
+
for i in range(1,len(val)):
|
|
141
|
+
log_string += ","+ str(val[i])
|
|
142
|
+
if test.internal_brg:
|
|
143
|
+
log_string += "_internal_brg"
|
|
144
|
+
|
|
145
|
+
cert_mqtt.dump_pkts(test, log=log_string)
|
|
146
|
+
|
|
147
|
+
ENERGY_GRAPH_HTML = """
|
|
148
|
+
<h1 style="color:blue;text-align:center;">{}</h1>
|
|
149
|
+
<div style="width:80%;margin:auto;"><canvas id="myChart"></canvas></div>
|
|
150
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
151
|
+
<script>
|
|
152
|
+
const labels = {};
|
|
153
|
+
const data = {{labels: labels, datasets: [{}]}};
|
|
154
|
+
const config = {{type: 'line', data: data, options: {{}}}};
|
|
155
|
+
const myChart = new Chart(document.getElementById('myChart'), config);
|
|
156
|
+
</script>\n"""
|
|
157
|
+
|
|
158
|
+
def print_pass_or_fail(rc, text):
|
|
159
|
+
if rc:
|
|
160
|
+
utPrint(text+" PASSED!", "GREEN")
|
|
161
|
+
else:
|
|
162
|
+
utPrint(text+" FAILED!", "RED")
|
|
163
|
+
|
|
164
|
+
def utPrint(text, chosenColor="none"):
|
|
165
|
+
if chosenColor == "none":
|
|
166
|
+
print("\n"+text)
|
|
167
|
+
else:
|
|
168
|
+
print("\n"+(color(chosenColor.upper(), text)))
|
|
169
|
+
|
|
170
|
+
def format_for_table(string, width):
|
|
171
|
+
while len(string) < width:
|
|
172
|
+
if len(string) == width-1:
|
|
173
|
+
string+="_"
|
|
174
|
+
else:
|
|
175
|
+
string="_"+string+"_"
|
|
176
|
+
return string
|
|
177
|
+
|
|
178
|
+
def print_duration(test):
|
|
179
|
+
duration = str(datetime.datetime.now() - test.start_time).split(".")[0]
|
|
180
|
+
print(f"## Duration of the test until now is {duration}")
|
|
181
|
+
return test
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
|
|
2
|
+
from brg_certificate.cert_defines import *
|
|
3
|
+
|
|
4
|
+
import brg_certificate.wltPb_pb2 as wpb
|
|
5
|
+
|
|
6
|
+
def action_pb(msg: dict):
|
|
7
|
+
pb_msg = wpb.DownlinkMessage()
|
|
8
|
+
pb_msg.gatewayAction.action = msg[ACTION]
|
|
9
|
+
return pb_msg.SerializeToString()
|
|
10
|
+
|
|
11
|
+
def tx_pkt_pb(msg: dict):
|
|
12
|
+
pb_msg = wpb.DownlinkMessage()
|
|
13
|
+
pb_msg.txPacket.payload = bytes.fromhex(msg[TX_PKT])
|
|
14
|
+
pb_msg.txPacket.maxDurationMs = msg[TX_MAX_DURATION_MS]
|
|
15
|
+
pb_msg.txPacket.maxRetries = int(msg[TX_MAX_RETRIES])
|
|
16
|
+
return pb_msg.SerializeToString()
|
|
17
|
+
|
|
18
|
+
def brg_ota_pb(msg: dict):
|
|
19
|
+
pb_msg = wpb.DownlinkMessage()
|
|
20
|
+
pb_msg.bridgeUpgrade.bridgeId = msg[BRIDGE_ID]
|
|
21
|
+
pb_msg.bridgeUpgrade.imageDirUrl = msg[IMG_DIR_URL]
|
|
22
|
+
pb_msg.bridgeUpgrade.versionUuid = msg[VER_UUID_STR]
|
|
23
|
+
pb_msg.bridgeUpgrade.upgradeBlSd = msg[UPGRADE_BLSD]
|
|
24
|
+
pb_msg.bridgeUpgrade.rebootPacket = bytes.fromhex(msg[TX_PKT])
|
|
25
|
+
pb_msg.bridgeUpgrade.txMaxDurationMs = msg[TX_MAX_DURATION_MS]
|
|
26
|
+
pb_msg.bridgeUpgrade.txMaxRetries = msg[TX_MAX_RETRIES]
|
|
27
|
+
return pb_msg.SerializeToString()
|
|
28
|
+
|
|
29
|
+
def gw_cfg_pb(msg: dict):
|
|
30
|
+
pb_msg = wpb.DownlinkMessage()
|
|
31
|
+
pb_msg.gatewayConfig.location.lat = msg[LAT]
|
|
32
|
+
pb_msg.gatewayConfig.location.lng = msg[LNG]
|
|
33
|
+
if WIFI_VERSION in msg.keys():
|
|
34
|
+
pb_msg.gatewayConfig.interfaceSwVersion = msg[WIFI_VERSION]
|
|
35
|
+
if BLE_VERSION in msg.keys():
|
|
36
|
+
pb_msg.gatewayConfig.bleSwVersion = msg[BLE_VERSION]
|
|
37
|
+
|
|
38
|
+
for key, val in msg[ADDITIONAL].items():
|
|
39
|
+
# Skip GW_MODE since it doesn't exist today and harm the parsing in PB
|
|
40
|
+
if GW_MODE == key:
|
|
41
|
+
continue
|
|
42
|
+
pb_value = wpb.Value()
|
|
43
|
+
if isinstance(val, int):
|
|
44
|
+
pb_value.integerValue = val
|
|
45
|
+
elif isinstance(val, float):
|
|
46
|
+
pb_value.numberValue = val
|
|
47
|
+
elif isinstance(val, str):
|
|
48
|
+
pb_value.stringValue = val
|
|
49
|
+
elif isinstance(val, bool):
|
|
50
|
+
pb_value.boolValue = val
|
|
51
|
+
else:
|
|
52
|
+
raise ValueError(f"Unsupported value type for key '{key}': {type(val)}")
|
|
53
|
+
pb_msg.gatewayConfig.config[key].CopyFrom(pb_value)
|
|
54
|
+
|
|
55
|
+
return pb_msg.SerializeToString()
|
|
56
|
+
|
|
57
|
+
def custom_message_pb(msg: dict):
|
|
58
|
+
pb_msg = wpb.DownlinkMessage()
|
|
59
|
+
|
|
60
|
+
for key, val in msg.items():
|
|
61
|
+
pb_value = wpb.Value()
|
|
62
|
+
if isinstance(val, int):
|
|
63
|
+
pb_value.integerValue = val
|
|
64
|
+
elif isinstance(val, float):
|
|
65
|
+
pb_value.numberValue = val
|
|
66
|
+
elif isinstance(val, str):
|
|
67
|
+
pb_value.stringValue = val
|
|
68
|
+
elif isinstance(val, bool):
|
|
69
|
+
pb_value.boolValue = val
|
|
70
|
+
else:
|
|
71
|
+
raise ValueError(f"Unsupported value type for key '{key}': {type(val)}")
|
|
72
|
+
pb_msg.customMessage.entries[key].CopyFrom(pb_value)
|
|
73
|
+
|
|
74
|
+
return pb_msg.SerializeToString()
|
|
75
|
+
|
|
76
|
+
def downlink_to_pb(msg: dict):
|
|
77
|
+
if ACTION in msg.keys():
|
|
78
|
+
if msg[ACTION] == 0:
|
|
79
|
+
return tx_pkt_pb(msg)
|
|
80
|
+
elif msg[ACTION] == 1:
|
|
81
|
+
return brg_ota_pb(msg)
|
|
82
|
+
else:
|
|
83
|
+
return action_pb(msg)
|
|
84
|
+
elif GW_CONF in msg.keys():
|
|
85
|
+
return gw_cfg_pb(msg[GW_CONF])
|
|
86
|
+
else:
|
|
87
|
+
print("Can't find the message type to convert to protobuf. Using customMessage..")
|
|
88
|
+
return custom_message_pb(msg)
|