wiliot-certificate 1.3.0a1__py3-none-any.whl → 1.4.0a1__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.0a1.dist-info}/METADATA +59 -8
- wiliot_certificate-1.4.0a1.dist-info/RECORD +198 -0
- {wiliot_certificate-1.3.0a1.dist-info → wiliot_certificate-1.4.0a1.dist-info}/WHEEL +1 -1
- wiliot_certificate-1.4.0a1.dist-info/entry_points.txt +3 -0
- wiliot_certificate-1.4.0a1.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.0a1.dist-info}/LICENSE +0 -0
gw_certificate/tests/actions.py
CHANGED
|
@@ -3,10 +3,17 @@ import os
|
|
|
3
3
|
import time
|
|
4
4
|
import pandas as pd
|
|
5
5
|
|
|
6
|
+
from packaging import version
|
|
7
|
+
|
|
6
8
|
from gw_certificate.common.debug import debug_print
|
|
7
9
|
from gw_certificate.interface.mqtt import MqttClient, GwAction
|
|
8
10
|
from gw_certificate.tests.generic import PassCriteria, PERFECT_SCORE, MINIMUM_SCORE, INCONCLUSIVE_MINIMUM, GenericTest, GenericStage, OPTIONAL
|
|
9
|
-
from gw_certificate.tests.static.references import GW_ACTIONS_DOC
|
|
11
|
+
from gw_certificate.tests.static.references import GW_ACTIONS_DOC, GW_BRIDGE_OTA_DOC
|
|
12
|
+
from gw_certificate.ag.ut_defines import STATUS_CODE_STR
|
|
13
|
+
from gw_certificate.interface.uart_if import FIRST_UNIFIED_BL_VERSION, UARTError
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
BL_INACTIVITY_TIMEOUT_SEC = 120
|
|
10
17
|
|
|
11
18
|
|
|
12
19
|
class GenericActionsStage(GenericStage):
|
|
@@ -41,13 +48,21 @@ class GatewayInfoStage(GenericActionsStage):
|
|
|
41
48
|
|
|
42
49
|
def run(self):
|
|
43
50
|
super().run()
|
|
44
|
-
|
|
51
|
+
timeout = datetime.datetime.now() + datetime.timedelta(seconds=20)
|
|
52
|
+
self.gw_info = None
|
|
53
|
+
self.mqttc.flush_messages()
|
|
54
|
+
|
|
55
|
+
self.mqttc.send_action(GwAction.GET_GW_INFO)
|
|
56
|
+
while datetime.datetime.now() < timeout and self.gw_info is None:
|
|
57
|
+
self.gw_info = self.mqttc.get_gw_info_message()
|
|
58
|
+
time.sleep(5)
|
|
59
|
+
|
|
45
60
|
|
|
46
61
|
def generate_stage_report(self):
|
|
47
62
|
super().generate_stage_report()
|
|
48
63
|
|
|
49
64
|
# Calculate whether stage pass/failed
|
|
50
|
-
if
|
|
65
|
+
if self.gw_info == None:
|
|
51
66
|
self.stage_pass = MINIMUM_SCORE
|
|
52
67
|
self.add_to_stage_report(f'Did not receive a response to the Gateway Info action. For more info visit:')
|
|
53
68
|
self.add_to_stage_report(f'{GW_ACTIONS_DOC}')
|
|
@@ -81,6 +96,7 @@ class RebootStage(GenericActionsStage):
|
|
|
81
96
|
timeout = datetime.datetime.now() + datetime.timedelta(minutes=3)
|
|
82
97
|
self.status_message = None
|
|
83
98
|
|
|
99
|
+
debug_print("Sending a reboot action to the gateway and awaiting reboot.. (timeout = 3)")
|
|
84
100
|
self.mqttc.send_action(GwAction.REBOOT_GW)
|
|
85
101
|
while datetime.datetime.now() < timeout and self.status_message is None:
|
|
86
102
|
self.status_message = self.mqttc.get_status_message()
|
|
@@ -90,9 +106,7 @@ class RebootStage(GenericActionsStage):
|
|
|
90
106
|
super().generate_stage_report()
|
|
91
107
|
|
|
92
108
|
# Calculate whether stage pass/failed
|
|
93
|
-
if
|
|
94
|
-
(not any('gatewayconf' == key.lower() for key in self.status_message.keys()) and
|
|
95
|
-
not any('gatewaystatus' == key.lower() for key in self.status_message.keys()))):
|
|
109
|
+
if self.status_message is None:
|
|
96
110
|
self.stage_pass = MINIMUM_SCORE
|
|
97
111
|
self.add_to_stage_report(f"The gateway did not validly reboot")
|
|
98
112
|
self.add_to_stage_report(f"Gateways are expected to upload a status(configuration) message upon establishing MQTT connection, which wasn't received.")
|
|
@@ -110,8 +124,113 @@ class RebootStage(GenericActionsStage):
|
|
|
110
124
|
stage_report=self.report.split('\n'))
|
|
111
125
|
return self.report
|
|
112
126
|
|
|
127
|
+
class BridgeOTAStage(GenericActionsStage):
|
|
128
|
+
def __init__(self, **kwargs):
|
|
129
|
+
super().__init__(**kwargs, stage_name=type(self).__name__)
|
|
130
|
+
self.stage_tooltip = "Issues a bridge OTA action to the gateway. Expects it to upgrade the bridge"
|
|
131
|
+
self.error_summary = "The target bridge was not upgraded"
|
|
132
|
+
self.action = "Bridge Upgrade"
|
|
133
|
+
|
|
134
|
+
OTA_VERSIONS_TO_USE = ("4.4.52", "4.4.53")
|
|
135
|
+
if version.parse(OTA_VERSIONS_TO_USE[0]) != self.uart.fw_version:
|
|
136
|
+
self.desired_version = version.parse(OTA_VERSIONS_TO_USE[0])
|
|
137
|
+
else:
|
|
138
|
+
self.desired_version = version.parse(OTA_VERSIONS_TO_USE[1])
|
|
139
|
+
|
|
140
|
+
def prepare_stage(self):
|
|
141
|
+
super().prepare_stage()
|
|
142
|
+
debug_print(f"Important: For the gateway to be able to download the file, it must use a valid token in the HTTP GET request.")
|
|
143
|
+
debug_print(f"Meaning It must be registered under an owner, and the certificate '-env' should correspond to that owner.")
|
|
144
|
+
debug_print(f"BridgeOTAStage attempt: {str(self.uart.fw_version)} -> {str(self.desired_version)}")
|
|
145
|
+
# Reset to remove any log/cert mode we had in the kit so it behaves as a bridge
|
|
146
|
+
self.uart.reset_gw()
|
|
147
|
+
|
|
148
|
+
def run(self):
|
|
149
|
+
super().run()
|
|
150
|
+
timeout = datetime.datetime.now() + datetime.timedelta(minutes=10)
|
|
151
|
+
self.action_status = None
|
|
152
|
+
self.status_code = None
|
|
153
|
+
self.reboot_packet_ts = None
|
|
154
|
+
self.action_status_ts = None
|
|
155
|
+
|
|
156
|
+
self.mqttc.send_bridge_ota_action(self.uart.mac, str(self.desired_version), 200, False, self.gw_id, "aws", self.env)
|
|
157
|
+
debug_print("Sent a BridgeOTA action to the gateway")
|
|
158
|
+
debug_print("Waiting for an actionStatus message from the gateway... (timeout=10)")
|
|
159
|
+
while datetime.datetime.now() < timeout and self.action_status is None:
|
|
160
|
+
line = self.uart.read_line()
|
|
161
|
+
if line != None and 'reset' in line:
|
|
162
|
+
self.uart.reset_gw(stop_advertising=False)
|
|
163
|
+
self.reboot_packet_ts = datetime.datetime.now()
|
|
164
|
+
debug_print("A reboot packet was received by the bridge")
|
|
165
|
+
self.action_status = self.mqttc.get_action_status_message()
|
|
166
|
+
time.sleep(2)
|
|
167
|
+
|
|
168
|
+
if self.action_status != None:
|
|
169
|
+
debug_print("actionStatus was received from the gateway")
|
|
170
|
+
self.action_status_ts = datetime.datetime.now()
|
|
171
|
+
self.status_code = self.action_status.get(STATUS_CODE_STR)
|
|
172
|
+
if self.status_code == None:
|
|
173
|
+
self.status_code = self.action_status.get('status')
|
|
174
|
+
|
|
175
|
+
if self.status_code != 0 and self.reboot_packet_ts != None:
|
|
176
|
+
debug_print(f"Reported status {self.status_code} indicates failure, waiting for the bridge bootloader inactivity timer (2 minutes)..")
|
|
177
|
+
time.sleep(BL_INACTIVITY_TIMEOUT_SEC)
|
|
178
|
+
|
|
179
|
+
debug_print('Waiting for the bridge to boot...')
|
|
180
|
+
time.sleep(40)
|
|
113
181
|
|
|
114
|
-
|
|
182
|
+
cur_ver = self.uart.get_version()
|
|
183
|
+
if cur_ver == None:
|
|
184
|
+
debug_print("ERROR: The certificate kit, acting as bridge in this stage, is not responding!")
|
|
185
|
+
self.uart.flush()
|
|
186
|
+
cur_ver = self.uart.get_version()
|
|
187
|
+
if cur_ver == None:
|
|
188
|
+
raise UARTError("Communication to the certificate kit halted! "
|
|
189
|
+
"Please unplug and replug its power source, wait for 5 minutes and retry. "
|
|
190
|
+
"If the error persist, contact Wiliot Support and attach your results directory.")
|
|
191
|
+
self.current_version = version.parse(cur_ver)
|
|
192
|
+
|
|
193
|
+
def generate_stage_report(self):
|
|
194
|
+
super().generate_stage_report()
|
|
195
|
+
|
|
196
|
+
# Calculate whether stage pass/failed
|
|
197
|
+
if self.action_status is None or self.status_code != 0:
|
|
198
|
+
self.stage_pass = MINIMUM_SCORE
|
|
199
|
+
self.add_to_stage_report(f"The bridge OTA test failed")
|
|
200
|
+
if self.action_status is None:
|
|
201
|
+
self.add_to_stage_report(f"Gateways are expected to upload an actionStatus message upon establishing MQTT connection, which wasn't received.")
|
|
202
|
+
elif self.status_code is None:
|
|
203
|
+
self.add_to_stage_report(f"Uploaded actionStatus messages should contain the status field, which wasn't detected.")
|
|
204
|
+
elif self.status_code != 0:
|
|
205
|
+
self.add_to_stage_report(f"Uploaded actionStatus status value received is {self.status_code}.")
|
|
206
|
+
if self.current_version == self.desired_version:
|
|
207
|
+
self.add_to_stage_report(f"Note that the bridge was actually upgraded successfully.")
|
|
208
|
+
self.add_to_stage_report(f"{GW_BRIDGE_OTA_DOC}")
|
|
209
|
+
else:
|
|
210
|
+
if self.current_version == self.desired_version:
|
|
211
|
+
self.stage_pass = PERFECT_SCORE
|
|
212
|
+
self.add_to_stage_report(f"Bridge was upgraded and an actionStatus message was received from the gateway.")
|
|
213
|
+
self.add_to_stage_report(f"Action status received {(self.action_status_ts - self.start_time).total_seconds():.1f}s after start.")
|
|
214
|
+
self.add_to_stage_report(f"Reboot packet received {(self.reboot_packet_ts - self.start_time).total_seconds():.1f}s after start.")
|
|
215
|
+
self.add_to_stage_report(f"Action status received {(self.action_status_ts - self.reboot_packet_ts).total_seconds():.1f}s after reboot.")
|
|
216
|
+
else:
|
|
217
|
+
self.stage_pass = MINIMUM_SCORE
|
|
218
|
+
self.add_to_stage_report(f"The bridge OTA test failed")
|
|
219
|
+
self.add_to_stage_report(f"Uploaded actionStatus message indicated success although the bridge was not upgraded.")
|
|
220
|
+
|
|
221
|
+
# Export all stage data
|
|
222
|
+
csv_data = {'Action': [self.action], 'Pass': [self.stage_pass > self.pass_min]}
|
|
223
|
+
if self.stage_pass == PERFECT_SCORE:
|
|
224
|
+
csv_data.update({'start_ts': self.start_time, 'reboot_packet_ts': self.reboot_packet_ts, 'action_status_ts': self.action_status_ts})
|
|
225
|
+
pd.DataFrame(csv_data).to_csv(self.summary_csv_path)
|
|
226
|
+
self.add_to_stage_report(f'\nStage summary saved - {self.summary_csv_path}')
|
|
227
|
+
|
|
228
|
+
# Generate HTML
|
|
229
|
+
self.report_html = self.template_engine.render_template('stage.html', stage=self,
|
|
230
|
+
stage_report=self.report.split('\n'))
|
|
231
|
+
return self.report
|
|
232
|
+
|
|
233
|
+
ACTIONS_STAGES = [GatewayInfoStage, RebootStage, BridgeOTAStage]
|
|
115
234
|
|
|
116
235
|
class ActionsTest(GenericTest):
|
|
117
236
|
def __init__(self, **kwargs):
|
|
@@ -119,7 +238,13 @@ class ActionsTest(GenericTest):
|
|
|
119
238
|
super().__init__(**self.__dict__, test_name=type(self).__name__)
|
|
120
239
|
self.test_tooltip = "Stages publishing different actions (via the 'update' topic). Optional"
|
|
121
240
|
self.result_indication = OPTIONAL
|
|
122
|
-
|
|
241
|
+
# Actions stages are determined by the CLI argument
|
|
242
|
+
stages = self.actions
|
|
243
|
+
|
|
244
|
+
if BridgeOTAStage in stages and self.uart.fw_version < FIRST_UNIFIED_BL_VERSION:
|
|
245
|
+
debug_print("Certificate kit's firmware should be upgraded with the '-update' flag to run the BridgeOTAStage")
|
|
246
|
+
stages.remove(BridgeOTAStage)
|
|
247
|
+
self.stages = [stage(**self.__dict__) for stage in stages]
|
|
123
248
|
|
|
124
249
|
def run(self):
|
|
125
250
|
super().run()
|
|
@@ -128,4 +253,4 @@ class ActionsTest(GenericTest):
|
|
|
128
253
|
stage.prepare_stage()
|
|
129
254
|
stage.run()
|
|
130
255
|
self.add_to_test_report(stage.generate_stage_report())
|
|
131
|
-
self.test_pass = PassCriteria.calc_for_test(self
|
|
256
|
+
self.test_pass = PassCriteria.calc_for_test(self, stage)
|
|
@@ -12,7 +12,9 @@ from gw_certificate.tests.generic import INCONCLUSIVE_MINIMUM, PassCriteria, MIN
|
|
|
12
12
|
from gw_certificate.api_if.api_validation import validate_message, MESSAGE_TYPES
|
|
13
13
|
from gw_certificate.interface.mqtt import MqttClient, Serialization
|
|
14
14
|
from gw_certificate.interface.ble_sniffer import BLESniffer, BLESnifferContext
|
|
15
|
+
from gw_certificate.tests.static.references import GW_MQTT_DOC
|
|
15
16
|
|
|
17
|
+
STATUS_MSG_TIMEOUT = 5
|
|
16
18
|
|
|
17
19
|
class ConnectionStage(GenericStage):
|
|
18
20
|
def __init__(self, mqttc:MqttClient, **kwargs):
|
|
@@ -28,8 +30,8 @@ class ConnectionStage(GenericStage):
|
|
|
28
30
|
'Please unplug GW from power. Press enter when unplugged')
|
|
29
31
|
self.mqttc.flush_messages()
|
|
30
32
|
input('Please plug GW back to power. Press enter when plugged')
|
|
31
|
-
debug_print('Waiting for GW to connect... (Timeout
|
|
32
|
-
timeout = datetime.datetime.now() + datetime.timedelta(minutes=
|
|
33
|
+
debug_print(f'Waiting for GW to connect... (Timeout {STATUS_MSG_TIMEOUT} minutes)')
|
|
34
|
+
timeout = datetime.datetime.now() + datetime.timedelta(minutes=STATUS_MSG_TIMEOUT)
|
|
33
35
|
self.status_message = None
|
|
34
36
|
|
|
35
37
|
while datetime.datetime.now() < timeout and self.status_message is None:
|
|
@@ -67,6 +69,9 @@ class ConnectionStage(GenericStage):
|
|
|
67
69
|
self.add_to_stage_report(f'\n{len(self.validation[1])} validation errors:')
|
|
68
70
|
for error in self.validation[1]:
|
|
69
71
|
self.add_to_stage_report(error.message)
|
|
72
|
+
self.add_to_stage_report(f"Please look into the Status section in:\n{GW_MQTT_DOC}")
|
|
73
|
+
|
|
74
|
+
self.add_report_topic_validation('status')
|
|
70
75
|
else:
|
|
71
76
|
self.error_summary = "No message recieved from GW in status topic after 3 mins."
|
|
72
77
|
self.add_to_stage_report(self.error_summary)
|
|
@@ -167,15 +172,15 @@ class ConnectionTest(GenericTest):
|
|
|
167
172
|
self.__dict__.update(kwargs)
|
|
168
173
|
super().__init__(**self.__dict__, test_name=type(self).__name__)
|
|
169
174
|
stages = STAGES
|
|
170
|
-
|
|
175
|
+
current_version = self.uart.get_version()
|
|
176
|
+
if current_version != None and version.parse(current_version) >= version.parse(INTERFERENCE_ANALYSIS_FW_VER):
|
|
171
177
|
stages.append(InterferenceAnalysisStage)
|
|
172
178
|
self.stages = [stage(**self.__dict__) for stage in stages]
|
|
173
179
|
|
|
174
180
|
def run(self):
|
|
175
181
|
super().run()
|
|
176
|
-
self.test_pass = PERFECT_SCORE
|
|
177
182
|
for stage in self.stages:
|
|
178
183
|
stage.prepare_stage()
|
|
179
184
|
stage.run()
|
|
180
|
-
self.test_pass = PassCriteria.calc_for_test(self
|
|
185
|
+
self.test_pass = PassCriteria.calc_for_test(self, stage)
|
|
181
186
|
self.add_to_test_report(stage.generate_stage_report())
|
gw_certificate/tests/downlink.py
CHANGED
|
@@ -4,7 +4,6 @@ import json
|
|
|
4
4
|
import os
|
|
5
5
|
import time
|
|
6
6
|
import pandas as pd
|
|
7
|
-
import numpy as np
|
|
8
7
|
import plotly.express as px
|
|
9
8
|
from google.protobuf.json_format import MessageToDict
|
|
10
9
|
|
|
@@ -99,7 +98,7 @@ class GenericDownlinkStage(GenericStage):
|
|
|
99
98
|
self.error_summary = channel_err_summary
|
|
100
99
|
self.add_to_stage_report(f"Channel {channel}: {PassCriteria.to_string(channel_pass)}")
|
|
101
100
|
self.add_to_stage_report(f"- Total {len(channel_pkts['payload'])} MQTT payloads sent")
|
|
102
|
-
self.add_to_stage_report(f"- Total {sum(channel_pkts['num_pkts_received'])} BLE Packets received by sniffer")
|
|
101
|
+
self.add_to_stage_report(f"- Total {sum(channel_pkts['num_pkts_received'])} BLE Packets received by sniffer (including duplicates)")
|
|
103
102
|
self.add_to_stage_report(f"- R Value: {rsquared} | Slope: {slope}")
|
|
104
103
|
# Export all stage data
|
|
105
104
|
self.sent_pkts.to_csv(self.sent_csv_path)
|
|
@@ -166,9 +165,8 @@ class DownlinkTest(GenericTest):
|
|
|
166
165
|
|
|
167
166
|
def run(self):
|
|
168
167
|
super().run()
|
|
169
|
-
self.test_pass = PERFECT_SCORE
|
|
170
168
|
for stage in self.stages:
|
|
171
169
|
stage.prepare_stage()
|
|
172
170
|
stage.run()
|
|
173
171
|
self.add_to_test_report(stage.generate_stage_report())
|
|
174
|
-
self.test_pass = PassCriteria.calc_for_test(self
|
|
172
|
+
self.test_pass = PassCriteria.calc_for_test(self, stage)
|
gw_certificate/tests/generic.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import os
|
|
3
|
+
from typing import Literal
|
|
4
|
+
import math
|
|
3
5
|
|
|
4
|
-
from gw_certificate.api.extended_api import ExtendedEdgeClient
|
|
5
6
|
from gw_certificate.common.debug import debug_print
|
|
6
7
|
from gw_certificate.api_if.gw_capabilities import GWCapabilities
|
|
7
8
|
from gw_certificate.interface.ble_simulator import BLESimulator
|
|
8
|
-
from gw_certificate.interface.if_defines import SEP
|
|
9
9
|
from gw_certificate.interface.mqtt import MqttClient
|
|
10
10
|
|
|
11
11
|
PASS_STATUS = {True: 'PASS', False: 'FAIL'}
|
|
@@ -23,6 +23,8 @@ SCORE_BASED = 'score'
|
|
|
23
23
|
INFORMATIVE = 'info'
|
|
24
24
|
OPTIONAL = 'optional'
|
|
25
25
|
|
|
26
|
+
ERR_SUMMARY_DEFAULT = 'View the stage report for more info. '
|
|
27
|
+
|
|
26
28
|
class PassCriteria():
|
|
27
29
|
def __init__(self):
|
|
28
30
|
pass
|
|
@@ -53,7 +55,7 @@ class PassCriteria():
|
|
|
53
55
|
def calc_for_stage_downlink(rsquared, slope, stage_name:str):
|
|
54
56
|
error_msg = ''
|
|
55
57
|
if 'Sanity' in stage_name:
|
|
56
|
-
if rsquared
|
|
58
|
+
if not math.isnan(rsquared) and rsquared != 0:
|
|
57
59
|
return PERFECT_SCORE, error_msg
|
|
58
60
|
else:
|
|
59
61
|
error_msg = 'No advertisements were received from the gateway.'
|
|
@@ -69,14 +71,17 @@ class PassCriteria():
|
|
|
69
71
|
return MINIMUM_SCORE, error_msg
|
|
70
72
|
|
|
71
73
|
@staticmethod
|
|
72
|
-
def calc_for_test(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
def calc_for_test(test, stage) -> int:
|
|
75
|
+
# Some stages shouldn't affect test score
|
|
76
|
+
if 'Geolocation' in stage.stage_name or 'info' in stage.result_indication:
|
|
77
|
+
return test.test_pass
|
|
78
|
+
|
|
79
|
+
if stage.score_inconclusive() and test.score_pass():
|
|
80
|
+
return test.inconclusive_min
|
|
81
|
+
elif stage.score_fail():
|
|
82
|
+
return MINIMUM_SCORE
|
|
78
83
|
else:
|
|
79
|
-
return
|
|
84
|
+
return test.test_pass
|
|
80
85
|
|
|
81
86
|
|
|
82
87
|
class GenericTest:
|
|
@@ -90,7 +95,7 @@ class GenericTest:
|
|
|
90
95
|
self.gw_capabilities = gw_capabilities
|
|
91
96
|
self.report = ''
|
|
92
97
|
self.report_html = ''
|
|
93
|
-
self.test_pass =
|
|
98
|
+
self.test_pass = PERFECT_SCORE
|
|
94
99
|
self.pass_min = PASS_MINIMUM
|
|
95
100
|
self.inconclusive_min = INCONCLUSIVE_MINIMUM
|
|
96
101
|
self.start_time = None
|
|
@@ -104,6 +109,9 @@ class GenericTest:
|
|
|
104
109
|
def __repr__(self):
|
|
105
110
|
return self.test_name
|
|
106
111
|
|
|
112
|
+
def prepare_test(self):
|
|
113
|
+
pass
|
|
114
|
+
|
|
107
115
|
def run(self):
|
|
108
116
|
self.start_time = datetime.datetime.now()
|
|
109
117
|
debug_print(f"Starting Test {self.test_name} : {self.start_time}")
|
|
@@ -121,6 +129,22 @@ class GenericTest:
|
|
|
121
129
|
def end_test(self):
|
|
122
130
|
self.create_test_html()
|
|
123
131
|
|
|
132
|
+
def score_pass(self):
|
|
133
|
+
if self.test_pass >= self.pass_min:
|
|
134
|
+
return True
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
def score_inconclusive(self):
|
|
138
|
+
if self.inconclusive_min <= self.test_pass < self.pass_min:
|
|
139
|
+
return True
|
|
140
|
+
return False
|
|
141
|
+
|
|
142
|
+
def score_fail(self):
|
|
143
|
+
if self.test_pass < self.inconclusive_min:
|
|
144
|
+
return True
|
|
145
|
+
return False
|
|
146
|
+
|
|
147
|
+
|
|
124
148
|
class GenericStage():
|
|
125
149
|
def __init__(self, stage_name, **kwargs):
|
|
126
150
|
#Stage Params
|
|
@@ -134,7 +158,7 @@ class GenericStage():
|
|
|
134
158
|
self.start_time = None
|
|
135
159
|
self.csv_path = os.path.join(self.test_dir, f'{self.stage_name}.csv')
|
|
136
160
|
self.stage_tooltip = kwargs.get('stage_tooltip', 'Missing tooltip')
|
|
137
|
-
self.error_summary = kwargs.get('error_summary',
|
|
161
|
+
self.error_summary = kwargs.get('error_summary', ERR_SUMMARY_DEFAULT)
|
|
138
162
|
|
|
139
163
|
def __repr__(self):
|
|
140
164
|
return self.stage_name
|
|
@@ -159,3 +183,29 @@ class GenericStage():
|
|
|
159
183
|
self.add_to_stage_report(f'Stage run time: {datetime.datetime.now() - self.start_time}')
|
|
160
184
|
self.add_to_stage_report(f'This stage {uncapitalize(self.stage_tooltip)}.')
|
|
161
185
|
self.add_report_line_separator()
|
|
186
|
+
|
|
187
|
+
def add_report_topic_validation(self, topic:Literal['status', 'data']):
|
|
188
|
+
if self.topic_suffix != '':
|
|
189
|
+
return
|
|
190
|
+
valid_topic, invalid_msg, invalid_topic = self.mqttc.validate_serialization_topic(topic)
|
|
191
|
+
if valid_topic == False:
|
|
192
|
+
# For now not failing stage since the customBroker command include topics explicitly
|
|
193
|
+
# self.stage_pass = MINIMUM_SCORE
|
|
194
|
+
# self.error_summary += "Invalid serialization-topic combination. "
|
|
195
|
+
self.add_to_stage_report(f'Warning: Received message on {invalid_topic} although serialization is {self.mqttc.get_serialization()}')
|
|
196
|
+
|
|
197
|
+
def score_pass(self):
|
|
198
|
+
if self.stage_pass >= self.pass_min:
|
|
199
|
+
return True
|
|
200
|
+
return False
|
|
201
|
+
|
|
202
|
+
def score_inconclusive(self):
|
|
203
|
+
if self.inconclusive_min <= self.stage_pass < self.pass_min:
|
|
204
|
+
return True
|
|
205
|
+
return False
|
|
206
|
+
|
|
207
|
+
def score_fail(self):
|
|
208
|
+
if self.stage_pass < self.inconclusive_min:
|
|
209
|
+
return True
|
|
210
|
+
return False
|
|
211
|
+
|
|
@@ -2,6 +2,7 @@ import datetime
|
|
|
2
2
|
import time
|
|
3
3
|
import os
|
|
4
4
|
from enum import Enum
|
|
5
|
+
from typing import Literal
|
|
5
6
|
|
|
6
7
|
from wiliot_api.api_client import WiliotCloudError
|
|
7
8
|
|
|
@@ -15,10 +16,13 @@ from gw_certificate.tests.static.references import GW_REGISTER_DOC, GW_MQTT_DOC
|
|
|
15
16
|
# HELPER DEFINES
|
|
16
17
|
REG_CERT_OWNER_ID = 'gw-certification-account'
|
|
17
18
|
ENV_VAR_AWS = 'WLT_REG_CERT_KEY_AWS'
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
STAGES_TIMEOUT_MINUTES = 2
|
|
19
21
|
TOKEN_EXPIRY_MINUTES = 3
|
|
22
|
+
CLOUD_DELAY_SEC = 7
|
|
23
|
+
BUSY_WAIT_DELAY_SEC = 5
|
|
24
|
+
STAGE_START_DELAY_MS = (BUSY_WAIT_DELAY_SEC + CLOUD_DELAY_SEC + 1) * 1000
|
|
20
25
|
|
|
21
|
-
ERROR_NO_API_KEY = f'You must receive an API security key from wiliot and save if to the environment variable {ENV_VAR_AWS} first.'
|
|
22
26
|
ERROR_NO_REGISTER = 'Gateway did not register itself in time.'
|
|
23
27
|
ERROR_NO_ONLINE = 'Gateway did not connect to MQTT in time.'
|
|
24
28
|
ERROR_NO_ACTIVE = 'Gateway did not upload a status message with its configurations in time.'
|
|
@@ -33,13 +37,10 @@ class GetGwField(Enum):
|
|
|
33
37
|
|
|
34
38
|
class Status(Enum):
|
|
35
39
|
PRE_REGISTERED = 'pre-registered'
|
|
40
|
+
REGISTERED = 'registered'
|
|
36
41
|
APPROVED = 'approved'
|
|
37
42
|
ACTIVE = 'active'
|
|
38
43
|
|
|
39
|
-
class Online(Enum):
|
|
40
|
-
FALSE = False
|
|
41
|
-
TRUE = True
|
|
42
|
-
|
|
43
44
|
class SharedData():
|
|
44
45
|
"""
|
|
45
46
|
Hold variables which values must be shared between different stages.
|
|
@@ -59,7 +60,43 @@ class GenericRegistrationStage(GenericStage):
|
|
|
59
60
|
def get_gateway_field(self, field:GetGwField):
|
|
60
61
|
temp = self.edge.get_gateway(self.gw_id)
|
|
61
62
|
return temp[field.value]
|
|
62
|
-
|
|
63
|
+
|
|
64
|
+
def kick_gw_from_mqtt(self):
|
|
65
|
+
response = self.edge.kick_gw_from_mqtt(self.gw_id)
|
|
66
|
+
debug_print(f"Kick response:{response}")
|
|
67
|
+
|
|
68
|
+
def validate_kong_logs(self, endpoint:Literal['device-authorize', 'registry', 'token', 'refresh']):
|
|
69
|
+
try:
|
|
70
|
+
message = self.edge.get_kong_logs(self.gw_id)
|
|
71
|
+
except WiliotCloudError as wce:
|
|
72
|
+
wce_dict = wce.args[0]
|
|
73
|
+
status_code = wce_dict.get('status_code')
|
|
74
|
+
msg = wce_dict.get('message')
|
|
75
|
+
if status_code == 404 and 'not found' in msg:
|
|
76
|
+
debug_print("Could not find gw when requesting for logs.")
|
|
77
|
+
debug_print("Either it is not registered, didn't issue any requests, or is missing the X-Gateway-ID header.")
|
|
78
|
+
return False
|
|
79
|
+
elif status_code == None:
|
|
80
|
+
raise wce
|
|
81
|
+
if message.get('status_code') != 200:
|
|
82
|
+
debug_print(f"Failed fetching logs, status_code:{message.get('status_code')}")
|
|
83
|
+
return False
|
|
84
|
+
|
|
85
|
+
# Convert datetime.now() format to epoch in MS
|
|
86
|
+
stage_start_ts = self.start_time.timestamp() * 1000 - STAGE_START_DELAY_MS
|
|
87
|
+
|
|
88
|
+
for log in message['data']:
|
|
89
|
+
if log['timestamp'] > stage_start_ts and endpoint in log['endpoint']:
|
|
90
|
+
response_code = log['responseCode']
|
|
91
|
+
if response_code != 200:
|
|
92
|
+
debug_print(f"An HTTP request to /{endpoint} resulted in an invalid response code:{response_code}")
|
|
93
|
+
else:
|
|
94
|
+
debug_print(f"A valid HTTP request to /{endpoint} was received")
|
|
95
|
+
return True
|
|
96
|
+
|
|
97
|
+
debug_print(f"No valid HTTP request to /{endpoint} was found")
|
|
98
|
+
return False
|
|
99
|
+
|
|
63
100
|
class RegistryStage(GenericRegistrationStage):
|
|
64
101
|
def __init__(self, **kwargs):
|
|
65
102
|
self.__dict__.update(kwargs)
|
|
@@ -80,9 +117,13 @@ class RegistryStage(GenericRegistrationStage):
|
|
|
80
117
|
msg = wce_dict.get('message')
|
|
81
118
|
if status_code == 400 and 'already exists' in msg:
|
|
82
119
|
debug_print(f'{gw_id} already exists in Wiliot platform! Deleting and pre-registering from scratch')
|
|
120
|
+
self.kick_gw_from_mqtt()
|
|
83
121
|
self.edge.delete_gateway(gw_id)
|
|
122
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
84
123
|
pre_registered = self.edge.register_gateway([gw_id])
|
|
85
124
|
else:
|
|
125
|
+
if status_code == 403:
|
|
126
|
+
debug_print(f"The API key within {self.env_variable} seems invalid. It is not authorized to pre-register the gateway")
|
|
86
127
|
raise wce
|
|
87
128
|
return pre_registered
|
|
88
129
|
|
|
@@ -96,12 +137,16 @@ class RegistryStage(GenericRegistrationStage):
|
|
|
96
137
|
def run(self):
|
|
97
138
|
super().run()
|
|
98
139
|
debug_print(f"Waiting for the gateway to finish the Registry step..")
|
|
99
|
-
timeout = datetime.datetime.now() + datetime.timedelta(minutes=
|
|
140
|
+
timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT_MINUTES)
|
|
100
141
|
self.status = self.get_gateway_field(GetGwField.STATUS)
|
|
101
142
|
while datetime.datetime.now() < timeout and not any(self.status == s.value for s in {Status.APPROVED, Status.ACTIVE}):
|
|
102
|
-
time.sleep(
|
|
143
|
+
time.sleep(BUSY_WAIT_DELAY_SEC)
|
|
103
144
|
self.status = self.get_gateway_field(GetGwField.STATUS)
|
|
104
145
|
|
|
146
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
147
|
+
self.validate_kong_logs('device-authorize')
|
|
148
|
+
self.validate_kong_logs('registry')
|
|
149
|
+
|
|
105
150
|
def generate_stage_report(self):
|
|
106
151
|
self.add_report_header()
|
|
107
152
|
if not any(self.status == s.value for s in {Status.APPROVED, Status.ACTIVE}):
|
|
@@ -111,7 +156,8 @@ class RegistryStage(GenericRegistrationStage):
|
|
|
111
156
|
debug_print(f"The gateway failed to register. Its status is '{self.status}' while it is expected to be '{Status.APPROVED.value}'.")
|
|
112
157
|
self.add_to_stage_report(f"There was an error in the Device-authorize or Registry steps.")
|
|
113
158
|
self.add_to_stage_report(f"Please go over the Device-authorize and Registry sections in this document:\n{GW_REGISTER_DOC}")
|
|
114
|
-
|
|
159
|
+
if self.status == Status.REGISTERED:
|
|
160
|
+
self.add_to_stage_report(f"Highly likely that the gateway is missing the 'X-Gateway-ID' header in it's HTTP requests.")
|
|
115
161
|
else:
|
|
116
162
|
self.stage_pass = PERFECT_SCORE
|
|
117
163
|
self.add_to_stage_report("Device-authorize and Registry requests were issued well.")
|
|
@@ -134,12 +180,15 @@ class OnlineStage(GenericRegistrationStage):
|
|
|
134
180
|
def run(self):
|
|
135
181
|
super().run()
|
|
136
182
|
debug_print(f"Waiting for the gateway to connect to MQTT..")
|
|
137
|
-
timeout = datetime.datetime.now() + datetime.timedelta(minutes=
|
|
183
|
+
timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT_MINUTES)
|
|
138
184
|
self.online = self.get_gateway_field(GetGwField.ONLINE)
|
|
139
185
|
while datetime.datetime.now() < timeout and self.online != True:
|
|
140
|
-
time.sleep(
|
|
186
|
+
time.sleep(BUSY_WAIT_DELAY_SEC)
|
|
141
187
|
self.online = self.get_gateway_field(GetGwField.ONLINE)
|
|
142
188
|
|
|
189
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
190
|
+
self.validate_kong_logs('token')
|
|
191
|
+
|
|
143
192
|
def generate_stage_report(self):
|
|
144
193
|
self.add_report_header()
|
|
145
194
|
if self.online != True:
|
|
@@ -149,8 +198,7 @@ class OnlineStage(GenericRegistrationStage):
|
|
|
149
198
|
self.add_to_stage_report(f"Either it didn't acquire a token or it didn't connect to MQTT in time.")
|
|
150
199
|
self.add_to_stage_report(f"Please go over the Poll For Token section in:\n{GW_REGISTER_DOC}")
|
|
151
200
|
self.add_to_stage_report(f"and the MQTT details in:\n{GW_MQTT_DOC}")
|
|
152
|
-
debug_print("Gateway did not connect
|
|
153
|
-
# TODO Ideally we should know where the error is exactly and inform the user. We currently lack such resolution
|
|
201
|
+
debug_print("Gateway did not connect to MQTT within time limit")
|
|
154
202
|
else:
|
|
155
203
|
self.stage_pass = PERFECT_SCORE
|
|
156
204
|
self.add_to_stage_report("Token acquisition and MQTT connection were done succesfully.")
|
|
@@ -174,10 +222,10 @@ class ActiveStage(GenericRegistrationStage):
|
|
|
174
222
|
def run(self):
|
|
175
223
|
super().run()
|
|
176
224
|
debug_print(f"Waiting for the gateway to upload a status message..")
|
|
177
|
-
timeout = datetime.datetime.now() + datetime.timedelta(minutes=
|
|
225
|
+
timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT_MINUTES)
|
|
178
226
|
self.status = self.get_gateway_field(GetGwField.STATUS)
|
|
179
227
|
while datetime.datetime.now() < timeout and self.status != Status.ACTIVE.value:
|
|
180
|
-
time.sleep(
|
|
228
|
+
time.sleep(BUSY_WAIT_DELAY_SEC)
|
|
181
229
|
self.status = self.get_gateway_field(GetGwField.STATUS)
|
|
182
230
|
|
|
183
231
|
def generate_stage_report(self):
|
|
@@ -212,22 +260,23 @@ class RefreshStage(GenericRegistrationStage):
|
|
|
212
260
|
debug_print(f"Waiting for the token to expire..")
|
|
213
261
|
timeout = self.shared_data.gw_online_ts + datetime.timedelta(minutes=TOKEN_EXPIRY_MINUTES)
|
|
214
262
|
while datetime.datetime.now() < timeout:
|
|
215
|
-
time.sleep(
|
|
216
|
-
|
|
217
|
-
def kick_gw_from_mqtt():
|
|
218
|
-
response = self.edge.kick_gw_from_mqtt(self.gw_id)
|
|
219
|
-
debug_print(f"Kick response:{response}")
|
|
263
|
+
time.sleep(BUSY_WAIT_DELAY_SEC)
|
|
220
264
|
|
|
221
265
|
debug_print(f"Token expired, kicking gateway")
|
|
222
|
-
kick_gw_from_mqtt()
|
|
266
|
+
self.kick_gw_from_mqtt()
|
|
223
267
|
|
|
268
|
+
# Sleep here since it sometimes take time for the cloud to kick and change the gateway's online status
|
|
269
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
224
270
|
debug_print(f"Waiting for the gateway to refresh its token and connect to MQTT..")
|
|
225
|
-
timeout = datetime.datetime.now() + datetime.timedelta(minutes=
|
|
271
|
+
timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT_MINUTES)
|
|
226
272
|
self.online = self.get_gateway_field(GetGwField.ONLINE)
|
|
227
273
|
while datetime.datetime.now() < timeout and self.online != True:
|
|
228
|
-
time.sleep(
|
|
274
|
+
time.sleep(BUSY_WAIT_DELAY_SEC)
|
|
229
275
|
self.online = self.get_gateway_field(GetGwField.ONLINE)
|
|
230
276
|
|
|
277
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
278
|
+
self.validate_kong_logs('refresh')
|
|
279
|
+
|
|
231
280
|
def generate_stage_report(self):
|
|
232
281
|
self.add_report_header()
|
|
233
282
|
if self.online != True:
|
|
@@ -257,9 +306,10 @@ class RegistrationTest(GenericTest):
|
|
|
257
306
|
|
|
258
307
|
# Set up the edge client for all stages
|
|
259
308
|
env = '' if self.env == 'prod' else '_' + str(self.env).upper()
|
|
260
|
-
|
|
309
|
+
self.env_variable = ENV_VAR_AWS + env
|
|
310
|
+
api_sec_key = os.environ.get(self.env_variable)
|
|
261
311
|
if not api_sec_key:
|
|
262
|
-
raise Exception(f"An API security key must be set to the envrionment variable {
|
|
312
|
+
raise Exception(f"An API security key must be set to the envrionment variable {self.env_variable} in order to run the RegistrationTest")
|
|
263
313
|
self.edge = ExtendedEdgeClient(api_sec_key, REG_CERT_OWNER_ID, env=self.env)
|
|
264
314
|
|
|
265
315
|
self.shared_data = SharedData()
|
|
@@ -275,7 +325,7 @@ class RegistrationTest(GenericTest):
|
|
|
275
325
|
stage.prepare_stage()
|
|
276
326
|
stage.run()
|
|
277
327
|
self.add_to_test_report(stage.generate_stage_report())
|
|
278
|
-
self.test_pass = PassCriteria.calc_for_test(self
|
|
328
|
+
self.test_pass = PassCriteria.calc_for_test(self, stage)
|
|
279
329
|
if self.test_pass != PERFECT_SCORE and stage != self.stages[-1]:
|
|
280
330
|
debug_print(f"{type(self).__name__} stopped without running all of its stages since {type(stage).__name__} failed")
|
|
281
331
|
self.add_to_test_report(f"{type(self).__name__} stopped without running all of its stages since {type(stage).__name__} failed")
|
|
@@ -284,5 +334,6 @@ class RegistrationTest(GenericTest):
|
|
|
284
334
|
|
|
285
335
|
def end_test(self):
|
|
286
336
|
debug_print(f'Deleting {self.gw_id} from {REG_CERT_OWNER_ID} before exiting')
|
|
337
|
+
time.sleep(CLOUD_DELAY_SEC)
|
|
287
338
|
self.edge.delete_gateway(self.gw_id)
|
|
288
339
|
super().end_test()
|