wiliot-certificate 1.4.0a2__py3-none-any.whl → 1.5.1a1__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/ag/energous_v0_defines.py +28 -28
- brg_certificate/ag/energous_v1_defines.py +28 -28
- brg_certificate/ag/energous_v2_defines.py +28 -28
- brg_certificate/ag/energous_v3_defines.py +28 -28
- brg_certificate/ag/energous_v4_defines.py +28 -28
- brg_certificate/ag/fanstel_lan_v0_defines.py +28 -28
- brg_certificate/ag/fanstel_lte_v0_defines.py +28 -28
- brg_certificate/ag/fanstel_wifi_v0_defines.py +28 -28
- brg_certificate/ag/minew_lte_v0_defines.py +28 -28
- brg_certificate/ag/wlt_cmd_if.html +1 -1
- brg_certificate/ag/wlt_types.html +3 -4
- brg_certificate/ag/wlt_types_ag.py +162 -163
- brg_certificate/brg_certificate.py +46 -12
- brg_certificate/brg_certificate_cli.py +1 -0
- brg_certificate/cert_common.py +31 -42
- brg_certificate/cert_config.py +7 -5
- brg_certificate/cert_data_sim.py +26 -4
- brg_certificate/cert_defines.py +30 -3
- brg_certificate/cert_gw_sim.py +12 -8
- brg_certificate/cert_mqtt.py +10 -2
- brg_certificate/cert_prints.py +7 -5
- brg_certificate/cert_protobuf.py +5 -1
- brg_certificate/cert_results.py +134 -84
- brg_certificate/cert_utils.py +14 -17
- brg_certificate/certificate_bcc_sanity_test_list.txt +35 -0
- brg_certificate/certificate_bcc_test_list.txt +45 -0
- brg_certificate/certificate_sanity_test_list.txt +2 -1
- brg_certificate/certificate_test_list.txt +10 -4
- brg_certificate/restore_brg.py +2 -0
- brg_certificate/tests/calibration/interval_test/interval_test.json +2 -1
- brg_certificate/tests/calibration/interval_test/interval_test.py +1 -1
- brg_certificate/tests/calibration/output_power_test/output_power_test.json +5 -3
- brg_certificate/tests/calibration/output_power_test/output_power_test.py +1 -1
- brg_certificate/tests/calibration/pattern_test/pattern_test.json +5 -2
- brg_certificate/tests/calibration/pattern_test/pattern_test.py +1 -1
- brg_certificate/tests/datapath/aging_test/aging_test.json +20 -0
- brg_certificate/tests/datapath/aging_test/aging_test.py +135 -0
- brg_certificate/tests/datapath/num_of_tags_test/num_of_tags_test.json +8 -3
- brg_certificate/tests/datapath/num_of_tags_test/num_of_tags_test.py +2 -2
- brg_certificate/tests/datapath/output_power_test/output_power_test.json +5 -2
- brg_certificate/tests/datapath/output_power_test/output_power_test.py +1 -1
- brg_certificate/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.json +5 -2
- brg_certificate/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.py +1 -1
- brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.json +5 -2
- brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.py +2 -2
- brg_certificate/tests/datapath/pacer_interval_test/pacer_interval_test.json +5 -2
- brg_certificate/tests/datapath/pacer_interval_test/pacer_interval_test.py +1 -1
- brg_certificate/tests/datapath/pattern_test/pattern_test.json +6 -3
- brg_certificate/tests/datapath/pattern_test/pattern_test.py +1 -1
- brg_certificate/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.json +8 -2
- brg_certificate/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.py +1 -1
- brg_certificate/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.json +8 -2
- brg_certificate/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.py +1 -1
- brg_certificate/tests/datapath/pkt_filter_test/pkt_filter_test.json +8 -2
- brg_certificate/tests/datapath/pkt_filter_test/pkt_filter_test.py +1 -1
- brg_certificate/tests/datapath/rssi_threshold_test/rssi_threshold_test.json +6 -2
- brg_certificate/tests/datapath/rssi_threshold_test/rssi_threshold_test.py +1 -1
- brg_certificate/tests/datapath/rx_channel_test/rx_channel_test.json +5 -2
- brg_certificate/tests/datapath/rx_channel_test/rx_channel_test.py +1 -1
- brg_certificate/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.json +3 -4
- brg_certificate/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.py +1 -1
- brg_certificate/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.json +3 -4
- brg_certificate/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.py +1 -1
- brg_certificate/tests/datapath/stress_gen3_test/stress_gen3_test.json +14 -22
- brg_certificate/tests/datapath/stress_gen3_test/stress_gen3_test.py +24 -24
- brg_certificate/tests/datapath/stress_test/stress_test.json +11 -18
- brg_certificate/tests/datapath/stress_test/stress_test.py +20 -27
- brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.json +6 -2
- brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.py +1 -1
- brg_certificate/tests/datapath/tx_repetition_test/tx_repetition_test.json +6 -2
- brg_certificate/tests/datapath/tx_repetition_test/tx_repetition_test.py +1 -1
- brg_certificate/tests/edge_mgmt/actions_test/actions_test.json +2 -1
- brg_certificate/tests/edge_mgmt/actions_test/actions_test.py +4 -24
- brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.json +2 -1
- brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.py +1 -1
- brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.json +2 -1
- brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.py +1 -1
- brg_certificate/tests/edge_mgmt/leds_test/leds_test.json +9 -5
- brg_certificate/tests/edge_mgmt/leds_test/leds_test.py +4 -4
- brg_certificate/tests/edge_mgmt/ota_test/ota_test.json +9 -5
- brg_certificate/tests/edge_mgmt/ota_test/ota_test.py +45 -1
- brg_certificate/tests/edge_mgmt/stat_test/stat_test.json +2 -1
- brg_certificate/tests/edge_mgmt/stat_test/stat_test.py +1 -1
- brg_certificate/tests/energy2400/duty_cycle_test/duty_cycle_test.json +5 -2
- brg_certificate/tests/energy2400/duty_cycle_test/duty_cycle_test.py +1 -1
- brg_certificate/tests/energy2400/output_power_test/output_power_test.json +5 -3
- brg_certificate/tests/energy2400/output_power_test/output_power_test.py +1 -1
- brg_certificate/tests/energy2400/pattern_test/pattern_test.json +5 -2
- brg_certificate/tests/energy2400/pattern_test/pattern_test.py +1 -1
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_250k_test/signal_indicator_ble5_10_250k_test.json +20 -0
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_250k_test/signal_indicator_ble5_10_250k_test.py +346 -0
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_500k_test/signal_indicator_ble5_10_500k_test.json +20 -0
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_500k_test/signal_indicator_ble5_10_500k_test.py +346 -0
- brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.json +2 -1
- brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.py +1 -1
- brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.json +12 -5
- brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.py +130 -43
- brg_certificate/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.json +5 -2
- brg_certificate/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.py +1 -1
- brg_certificate/tests/energy_sub1g/pattern_test/pattern_test.json +9 -3
- brg_certificate/tests/energy_sub1g/pattern_test/pattern_test.py +1 -1
- brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.json +2 -1
- brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.py +1 -1
- brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.json +5 -2
- brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.py +1 -1
- brg_certificate/wltPb_pb2.py +50 -38
- brg_certificate/wltPb_pb2.pyi +40 -34
- brg_certificate/wlt_types.py +4 -6
- common/wlt_logo.png +0 -0
- gw_certificate/ag/ut_defines.py +4 -1
- gw_certificate/cert_results.py +145 -0
- gw_certificate/gw_certificate.py +18 -6
- gw_certificate/gw_certificate_cli.py +3 -3
- gw_certificate/interface/mqtt.py +1 -0
- gw_certificate/interface/uart_if.py +1 -1
- gw_certificate/tests/actions.py +7 -2
- gw_certificate/tests/connection.py +1 -1
- gw_certificate/tests/generic.py +43 -17
- gw_certificate/tests/registration.py +2 -1
- gw_certificate/tests/uplink.py +26 -35
- {wiliot_certificate-1.4.0a2.dist-info → wiliot_certificate-1.5.1a1.dist-info}/METADATA +16 -10
- {wiliot_certificate-1.4.0a2.dist-info → wiliot_certificate-1.5.1a1.dist-info}/RECORD +126 -120
- {wiliot_certificate-1.4.0a2.dist-info → wiliot_certificate-1.5.1a1.dist-info}/WHEEL +1 -1
- {wiliot_certificate-1.4.0a2.dist-info → wiliot_certificate-1.5.1a1.dist-info}/top_level.txt +1 -0
- brg_certificate/tests/datapath/adaptive_pacer_algo_test/adaptive_pacer_algo_test.json +0 -13
- brg_certificate/tests/datapath/adaptive_pacer_algo_test/adaptive_pacer_algo_test.py +0 -76
- brg_certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.json +0 -13
- brg_certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.py +0 -398
- {wiliot_certificate-1.4.0a2.dist-info → wiliot_certificate-1.5.1a1.dist-info}/entry_points.txt +0 -0
- {wiliot_certificate-1.4.0a2.dist-info → wiliot_certificate-1.5.1a1.dist-info/licenses}/LICENSE +0 -0
brg_certificate/wltPb_pb2.pyi
CHANGED
|
@@ -62,6 +62,28 @@ class UplinkMessage(_message.Message):
|
|
|
62
62
|
actionStatus: ActionStatus
|
|
63
63
|
def __init__(self, gatewayStatus: _Optional[_Union[GatewayStatus, _Mapping]] = ..., gatewayInfo: _Optional[_Union[GatewayInfo, _Mapping]] = ..., gatewayLogs: _Optional[_Union[GatewayLogs, _Mapping]] = ..., actionStatus: _Optional[_Union[ActionStatus, _Mapping]] = ...) -> None: ...
|
|
64
64
|
|
|
65
|
+
class ACL(_message.Message):
|
|
66
|
+
__slots__ = ("mode_allow", "ids")
|
|
67
|
+
MODE_ALLOW_FIELD_NUMBER: _ClassVar[int]
|
|
68
|
+
IDS_FIELD_NUMBER: _ClassVar[int]
|
|
69
|
+
mode_allow: bool
|
|
70
|
+
ids: _containers.RepeatedScalarFieldContainer[bytes]
|
|
71
|
+
def __init__(self, mode_allow: bool = ..., ids: _Optional[_Iterable[bytes]] = ...) -> None: ...
|
|
72
|
+
|
|
73
|
+
class GatewayConfigValue(_message.Message):
|
|
74
|
+
__slots__ = ("integerValue", "numberValue", "stringValue", "boolValue", "aclValue")
|
|
75
|
+
INTEGERVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
76
|
+
NUMBERVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
77
|
+
STRINGVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
78
|
+
BOOLVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
79
|
+
ACLVALUE_FIELD_NUMBER: _ClassVar[int]
|
|
80
|
+
integerValue: int
|
|
81
|
+
numberValue: float
|
|
82
|
+
stringValue: str
|
|
83
|
+
boolValue: bool
|
|
84
|
+
aclValue: ACL
|
|
85
|
+
def __init__(self, integerValue: _Optional[int] = ..., numberValue: _Optional[float] = ..., stringValue: _Optional[str] = ..., boolValue: bool = ..., aclValue: _Optional[_Union[ACL, _Mapping]] = ...) -> None: ...
|
|
86
|
+
|
|
65
87
|
class GatewayStatus(_message.Message):
|
|
66
88
|
__slots__ = ("gatewayId", "gatewayType", "downlinkSupported", "bridgeOtaUpgradeSupported", "apiVersion", "version", "bleSwVersion", "interfaceSwVersion", "location", "config", "bleAddress")
|
|
67
89
|
class ConfigEntry(_message.Message):
|
|
@@ -69,8 +91,8 @@ class GatewayStatus(_message.Message):
|
|
|
69
91
|
KEY_FIELD_NUMBER: _ClassVar[int]
|
|
70
92
|
VALUE_FIELD_NUMBER: _ClassVar[int]
|
|
71
93
|
key: str
|
|
72
|
-
value:
|
|
73
|
-
def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[
|
|
94
|
+
value: GatewayConfigValue
|
|
95
|
+
def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[GatewayConfigValue, _Mapping]] = ...) -> None: ...
|
|
74
96
|
GATEWAYID_FIELD_NUMBER: _ClassVar[int]
|
|
75
97
|
GATEWAYTYPE_FIELD_NUMBER: _ClassVar[int]
|
|
76
98
|
DOWNLINKSUPPORTED_FIELD_NUMBER: _ClassVar[int]
|
|
@@ -91,9 +113,9 @@ class GatewayStatus(_message.Message):
|
|
|
91
113
|
bleSwVersion: str
|
|
92
114
|
interfaceSwVersion: str
|
|
93
115
|
location: Location
|
|
94
|
-
config: _containers.MessageMap[str,
|
|
116
|
+
config: _containers.MessageMap[str, GatewayConfigValue]
|
|
95
117
|
bleAddress: str
|
|
96
|
-
def __init__(self, gatewayId: _Optional[str] = ..., gatewayType: _Optional[str] = ..., downlinkSupported: bool = ..., bridgeOtaUpgradeSupported: bool = ..., apiVersion: _Optional[int] = ..., version: _Optional[str] = ..., bleSwVersion: _Optional[str] = ..., interfaceSwVersion: _Optional[str] = ..., location: _Optional[_Union[Location, _Mapping]] = ..., config: _Optional[_Mapping[str,
|
|
118
|
+
def __init__(self, gatewayId: _Optional[str] = ..., gatewayType: _Optional[str] = ..., downlinkSupported: bool = ..., bridgeOtaUpgradeSupported: bool = ..., apiVersion: _Optional[int] = ..., version: _Optional[str] = ..., bleSwVersion: _Optional[str] = ..., interfaceSwVersion: _Optional[str] = ..., location: _Optional[_Union[Location, _Mapping]] = ..., config: _Optional[_Mapping[str, GatewayConfigValue]] = ..., bleAddress: _Optional[str] = ...) -> None: ...
|
|
97
119
|
|
|
98
120
|
class GatewayInfo(_message.Message):
|
|
99
121
|
__slots__ = ("entries",)
|
|
@@ -115,28 +137,32 @@ class GatewayLogs(_message.Message):
|
|
|
115
137
|
def __init__(self, logs: _Optional[_Iterable[str]] = ...) -> None: ...
|
|
116
138
|
|
|
117
139
|
class ActionStatus(_message.Message):
|
|
118
|
-
__slots__ = ("action", "status")
|
|
140
|
+
__slots__ = ("action", "status", "step", "progress", "bridgeId")
|
|
119
141
|
ACTION_FIELD_NUMBER: _ClassVar[int]
|
|
120
142
|
STATUS_FIELD_NUMBER: _ClassVar[int]
|
|
143
|
+
STEP_FIELD_NUMBER: _ClassVar[int]
|
|
144
|
+
PROGRESS_FIELD_NUMBER: _ClassVar[int]
|
|
145
|
+
BRIDGEID_FIELD_NUMBER: _ClassVar[int]
|
|
121
146
|
action: int
|
|
122
147
|
status: int
|
|
123
|
-
|
|
148
|
+
step: int
|
|
149
|
+
progress: int
|
|
150
|
+
bridgeId: bytes
|
|
151
|
+
def __init__(self, action: _Optional[int] = ..., status: _Optional[int] = ..., step: _Optional[int] = ..., progress: _Optional[int] = ..., bridgeId: _Optional[bytes] = ...) -> None: ...
|
|
124
152
|
|
|
125
153
|
class DownlinkMessage(_message.Message):
|
|
126
|
-
__slots__ = ("txPacket", "gatewayAction", "bridgeUpgrade", "gatewayConfig", "
|
|
154
|
+
__slots__ = ("txPacket", "gatewayAction", "bridgeUpgrade", "gatewayConfig", "customMessage")
|
|
127
155
|
TXPACKET_FIELD_NUMBER: _ClassVar[int]
|
|
128
156
|
GATEWAYACTION_FIELD_NUMBER: _ClassVar[int]
|
|
129
157
|
BRIDGEUPGRADE_FIELD_NUMBER: _ClassVar[int]
|
|
130
158
|
GATEWAYCONFIG_FIELD_NUMBER: _ClassVar[int]
|
|
131
|
-
CUSTOMBROKER_FIELD_NUMBER: _ClassVar[int]
|
|
132
159
|
CUSTOMMESSAGE_FIELD_NUMBER: _ClassVar[int]
|
|
133
160
|
txPacket: TxPacket
|
|
134
161
|
gatewayAction: GatewayAction
|
|
135
162
|
bridgeUpgrade: BridgeUpgrade
|
|
136
163
|
gatewayConfig: GatewayConfig
|
|
137
|
-
customBroker: CustomBroker
|
|
138
164
|
customMessage: CustomMessage
|
|
139
|
-
def __init__(self, txPacket: _Optional[_Union[TxPacket, _Mapping]] = ..., gatewayAction: _Optional[_Union[GatewayAction, _Mapping]] = ..., bridgeUpgrade: _Optional[_Union[BridgeUpgrade, _Mapping]] = ..., gatewayConfig: _Optional[_Union[GatewayConfig, _Mapping]] = ...,
|
|
165
|
+
def __init__(self, txPacket: _Optional[_Union[TxPacket, _Mapping]] = ..., gatewayAction: _Optional[_Union[GatewayAction, _Mapping]] = ..., bridgeUpgrade: _Optional[_Union[BridgeUpgrade, _Mapping]] = ..., gatewayConfig: _Optional[_Union[GatewayConfig, _Mapping]] = ..., customMessage: _Optional[_Union[CustomMessage, _Mapping]] = ...) -> None: ...
|
|
140
166
|
|
|
141
167
|
class TxPacket(_message.Message):
|
|
142
168
|
__slots__ = ("payload", "maxRetries", "maxDurationMs")
|
|
@@ -179,8 +205,8 @@ class GatewayConfig(_message.Message):
|
|
|
179
205
|
KEY_FIELD_NUMBER: _ClassVar[int]
|
|
180
206
|
VALUE_FIELD_NUMBER: _ClassVar[int]
|
|
181
207
|
key: str
|
|
182
|
-
value:
|
|
183
|
-
def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[
|
|
208
|
+
value: GatewayConfigValue
|
|
209
|
+
def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[GatewayConfigValue, _Mapping]] = ...) -> None: ...
|
|
184
210
|
VERSION_FIELD_NUMBER: _ClassVar[int]
|
|
185
211
|
BLESWVERSION_FIELD_NUMBER: _ClassVar[int]
|
|
186
212
|
INTERFACESWVERSION_FIELD_NUMBER: _ClassVar[int]
|
|
@@ -190,28 +216,8 @@ class GatewayConfig(_message.Message):
|
|
|
190
216
|
bleSwVersion: str
|
|
191
217
|
interfaceSwVersion: str
|
|
192
218
|
location: Location
|
|
193
|
-
config: _containers.MessageMap[str,
|
|
194
|
-
def __init__(self, version: _Optional[str] = ..., bleSwVersion: _Optional[str] = ..., interfaceSwVersion: _Optional[str] = ..., location: _Optional[_Union[Location, _Mapping]] = ..., config: _Optional[_Mapping[str,
|
|
195
|
-
|
|
196
|
-
class CustomBroker(_message.Message):
|
|
197
|
-
__slots__ = ("customBroker", "port", "brokerUrl", "username", "password", "updateTopic", "statusTopic", "dataTopic")
|
|
198
|
-
CUSTOMBROKER_FIELD_NUMBER: _ClassVar[int]
|
|
199
|
-
PORT_FIELD_NUMBER: _ClassVar[int]
|
|
200
|
-
BROKERURL_FIELD_NUMBER: _ClassVar[int]
|
|
201
|
-
USERNAME_FIELD_NUMBER: _ClassVar[int]
|
|
202
|
-
PASSWORD_FIELD_NUMBER: _ClassVar[int]
|
|
203
|
-
UPDATETOPIC_FIELD_NUMBER: _ClassVar[int]
|
|
204
|
-
STATUSTOPIC_FIELD_NUMBER: _ClassVar[int]
|
|
205
|
-
DATATOPIC_FIELD_NUMBER: _ClassVar[int]
|
|
206
|
-
customBroker: bool
|
|
207
|
-
port: int
|
|
208
|
-
brokerUrl: str
|
|
209
|
-
username: str
|
|
210
|
-
password: str
|
|
211
|
-
updateTopic: str
|
|
212
|
-
statusTopic: str
|
|
213
|
-
dataTopic: str
|
|
214
|
-
def __init__(self, customBroker: bool = ..., port: _Optional[int] = ..., brokerUrl: _Optional[str] = ..., username: _Optional[str] = ..., password: _Optional[str] = ..., updateTopic: _Optional[str] = ..., statusTopic: _Optional[str] = ..., dataTopic: _Optional[str] = ...) -> None: ...
|
|
219
|
+
config: _containers.MessageMap[str, GatewayConfigValue]
|
|
220
|
+
def __init__(self, version: _Optional[str] = ..., bleSwVersion: _Optional[str] = ..., interfaceSwVersion: _Optional[str] = ..., location: _Optional[_Union[Location, _Mapping]] = ..., config: _Optional[_Mapping[str, GatewayConfigValue]] = ...) -> None: ...
|
|
215
221
|
|
|
216
222
|
class CustomMessage(_message.Message):
|
|
217
223
|
__slots__ = ("entries",)
|
brg_certificate/wlt_types.py
CHANGED
|
@@ -92,16 +92,11 @@ class WltPkt():
|
|
|
92
92
|
self.pkt = ag.UnifiedEchoPktV1()
|
|
93
93
|
elif self.data_hdr.group_id_major == ag.GROUP_ID_BLE5_EXTENDED:
|
|
94
94
|
self.pkt = ag.UnifiedEchoExtPkt()
|
|
95
|
-
else:
|
|
96
|
-
print(f"Unidentified unified group id found: {hex(self.data_hdr.group_id_major)}")
|
|
97
95
|
# SideInfo pkts
|
|
98
96
|
elif self.hdr.group_id == ag.GROUP_ID_SIDE_INFO_SENSOR:
|
|
99
97
|
self.pkt = ag.SideInfoSensor()
|
|
100
98
|
elif self.hdr.group_id == ag.GROUP_ID_SIDE_INFO:
|
|
101
99
|
self.pkt = ag.SideInfo()
|
|
102
|
-
else:
|
|
103
|
-
print(f"Unidentified sensor group id found: {hex(self.data_hdr.group_id_major)}")
|
|
104
|
-
|
|
105
100
|
if self.pkt:
|
|
106
101
|
if self.data_hdr.group_id_major == ag.GROUP_ID_BLE5_EXTENDED:
|
|
107
102
|
self.pkt.set(string[14:84])
|
|
@@ -111,4 +106,7 @@ class WltPkt():
|
|
|
111
106
|
elif self.hdr.group_id == ag.GROUP_ID_SIGNAL_INDICATOR:
|
|
112
107
|
self.pkt = eval_pkt(f'SignalIndicatorDataV{ag.SIGNAL_INDICATOR_PACKET_VERSION_LATEST}')(string[8:62])
|
|
113
108
|
elif self.hdr.uuid_lsb == ag.HDR_DEFAULT_BRG_SENSOR_UUID_LSB and self.hdr.uuid_msb == ag.HDR_DEFAULT_BRG_SENSOR_UUID_MSB:
|
|
114
|
-
self.pkt = ag.SensorData(string)
|
|
109
|
+
self.pkt = ag.SensorData(string)
|
|
110
|
+
# Unparsed pkts
|
|
111
|
+
else:
|
|
112
|
+
print(f"Unable to parse packet with payload: {string}")
|
common/wlt_logo.png
ADDED
|
Binary file
|
gw_certificate/ag/ut_defines.py
CHANGED
|
@@ -164,9 +164,12 @@ GLOBAL_PACING_GROUP_THRESHOLD = 0.70
|
|
|
164
164
|
PACKETS_ECHO_OFF = 16
|
|
165
165
|
TEST_PASSED = 0
|
|
166
166
|
TEST_FAILED = -1
|
|
167
|
+
TEST_INCONCLUSIVE = 1
|
|
168
|
+
TEST_INFO = 2
|
|
169
|
+
TEST_WARNING = 3
|
|
170
|
+
TEST_OPTIONAL = 4
|
|
167
171
|
NO_RESPONSE = "NO_RESPONSE"
|
|
168
172
|
DONE = "DONE"
|
|
169
|
-
TEST_SUCCESS = ":)"
|
|
170
173
|
MGMT_PKT = "mgmt_pkt"
|
|
171
174
|
UNIFIED_PKT = "unified_pkt"
|
|
172
175
|
SIDE_INFO_PKT = "side_info_pkt"
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tabulate
|
|
3
|
+
from reportlab.lib import colors
|
|
4
|
+
from reportlab.lib.pagesizes import letter
|
|
5
|
+
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, PageBreak, KeepTogether, Image
|
|
6
|
+
from reportlab.lib.styles import ParagraphStyle
|
|
7
|
+
from reportlab.lib.enums import TA_CENTER, TA_LEFT
|
|
8
|
+
|
|
9
|
+
# Local imports
|
|
10
|
+
from gw_certificate.ag.ut_defines import TEST_FAILED, TEST_INCONCLUSIVE, TEST_PASSED, TEST_INFO, TEST_WARNING, TEST_OPTIONAL
|
|
11
|
+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
12
|
+
format_timedelta = lambda delta: f"{int(delta.total_seconds()//3600):02}:{int((delta.total_seconds()%3600)//60):02}:{int(delta.total_seconds()%60):02}"
|
|
13
|
+
|
|
14
|
+
##################################
|
|
15
|
+
# GENERIC
|
|
16
|
+
##################################
|
|
17
|
+
def generate_pdf_results_file(gw_cert):
|
|
18
|
+
# Extract GW certificate tests results
|
|
19
|
+
failures, inconclusive = 0, 0
|
|
20
|
+
for test in gw_cert.tests:
|
|
21
|
+
if test.rc == TEST_INCONCLUSIVE:
|
|
22
|
+
inconclusive += 1
|
|
23
|
+
elif test.rc == TEST_FAILED:
|
|
24
|
+
failures += 1
|
|
25
|
+
|
|
26
|
+
# Generate PDF file
|
|
27
|
+
doc = SimpleDocTemplate(gw_cert.result_pdf_path, pagesize=letter)
|
|
28
|
+
doc.title = f"Wiliot Gateway Certificate Results"
|
|
29
|
+
elements, hdr_page = [], []
|
|
30
|
+
|
|
31
|
+
# Add Wiliot Logo
|
|
32
|
+
img = Image(os.path.join(BASE_DIR, "../common", "wlt_logo.png"), width=100, height=40) # Adjust size as needed
|
|
33
|
+
hdr_page.append(img)
|
|
34
|
+
hdr_page.append(Spacer(1, 20))
|
|
35
|
+
|
|
36
|
+
# Title and Summary
|
|
37
|
+
red_header = STYLES_PDF.get("RED_HEADER", ParagraphStyle("Default"))
|
|
38
|
+
green_header = STYLES_PDF.get("GREEN_HEADER", ParagraphStyle("Default"))
|
|
39
|
+
module_header = STYLES_PDF.get("MODULE_HEADER", ParagraphStyle("Default"))
|
|
40
|
+
test_header = STYLES_PDF.get("TEST_HEADER", ParagraphStyle("Default"))
|
|
41
|
+
text_style_bold = STYLES_PDF.get("BLACK_BOLD", ParagraphStyle("Default"))
|
|
42
|
+
text_style_centered = STYLES_PDF.get("BLACK", ParagraphStyle("Default"))
|
|
43
|
+
if gw_cert.error:
|
|
44
|
+
title = Paragraph(f"<b>Wiliot Gateway Certificate Error!</b>", red_header)
|
|
45
|
+
hdr_page.append(title)
|
|
46
|
+
hdr_page.append(Spacer(1, 20))
|
|
47
|
+
hdr_page.append(Paragraph(f"{gw_cert.error}", text_style_bold))
|
|
48
|
+
else:
|
|
49
|
+
title = Paragraph(f"<b>Wiliot Gateway Certificate Passed!</b>", green_header) if not failures else Paragraph(f"<b>Wiliot Gateway Certificate Failed!</b>", red_header)
|
|
50
|
+
hdr_page.append(title)
|
|
51
|
+
hdr_page.append(Spacer(1, 20))
|
|
52
|
+
hdr_page.append(Paragraph(f"<b>Summary</b>", module_header))
|
|
53
|
+
hdr_page.append(Spacer(1, 20))
|
|
54
|
+
hdr_page.append(Paragraph("<u>Run Info:</u>", text_style_bold))
|
|
55
|
+
hdr_page.append(Paragraph(f"Run date: {gw_cert.current_datetime.strftime('%d/%m/%Y, %H:%M:%S')}", text_style_bold))
|
|
56
|
+
hdr_page.append(Paragraph(f"Tests duration: {format_timedelta(gw_cert.runtime())}", text_style_bold))
|
|
57
|
+
hdr_page.append(Paragraph(f"Certificate version: {gw_cert.gw_cert_version}", text_style_bold))
|
|
58
|
+
hdr_page.append(Spacer(1, 10))
|
|
59
|
+
if gw_cert.use_uart:
|
|
60
|
+
hdr_page.append(Paragraph("<u>Certification Kit Info:</u>", text_style_bold))
|
|
61
|
+
hdr_page.append(Paragraph(f"BLE simulator mac: {gw_cert.uart.mac}", text_style_bold))
|
|
62
|
+
hdr_page.append(Paragraph(f"BLE simulator version: {gw_cert.uart.fw_version}", text_style_bold))
|
|
63
|
+
hdr_page.append(Spacer(1, 10))
|
|
64
|
+
hdr_page.append(Paragraph("<u>Tested Device Info:</u>", text_style_bold))
|
|
65
|
+
hdr_page.append(Paragraph(f"Tested gateway ID: {gw_cert.gw_id}", text_style_bold))
|
|
66
|
+
hdr_page.append(Spacer(1, 20))
|
|
67
|
+
|
|
68
|
+
# Count Table
|
|
69
|
+
count_data = [
|
|
70
|
+
["PASSED", "INCONCLUSIVE", "FAILED", "TOTAL"],
|
|
71
|
+
[len(gw_cert.tests)-(failures+inconclusive), inconclusive, failures, len(gw_cert.tests)]
|
|
72
|
+
]
|
|
73
|
+
count_table = Table(count_data)
|
|
74
|
+
count_table.setStyle(INNER_TABLE_STYLE)
|
|
75
|
+
hdr_page.append(count_table)
|
|
76
|
+
hdr_page.append(Spacer(1, 20))
|
|
77
|
+
|
|
78
|
+
# Test Results
|
|
79
|
+
summary_data = []
|
|
80
|
+
text_style_center = STYLES_PDF.get("BLACK", ParagraphStyle("Default"))
|
|
81
|
+
text_style_left = STYLES_PDF.get("BLACK_LEFT", ParagraphStyle("Default"))
|
|
82
|
+
for test in gw_cert.tests:
|
|
83
|
+
summary_data += [[Paragraph(f'<a href="#{test}">{test}</a>', text_style_centered), pass_or_fail_pdf(test), format_timedelta(test.duration)]]
|
|
84
|
+
elements.append(Paragraph(f"<a name='{test}'/><b>{test}</b>", module_header))
|
|
85
|
+
elements.append(Spacer(1, 20))
|
|
86
|
+
elements.append(pass_or_fail_pdf(test))
|
|
87
|
+
elements.append(Spacer(1, 10))
|
|
88
|
+
elements.append(Paragraph(f"Test duration: {format_timedelta(test.duration)}", text_style_bold))
|
|
89
|
+
elements.append(Spacer(1, 10))
|
|
90
|
+
inner_table, stages_breakdown = [["Phase", "Result", "Duration"]], []
|
|
91
|
+
for stage in test.stages:
|
|
92
|
+
stages_breakdown += [KeepTogether([Paragraph(stage.stage_name, test_header), Spacer(1, 10), pass_or_fail_pdf(stage), Spacer(1, 10)]
|
|
93
|
+
+ [Paragraph(l, text_style_left) for l in stage.report.split('\n')]
|
|
94
|
+
+ [Spacer(1, 10)])]
|
|
95
|
+
inner_table += [[Paragraph(stage.stage_name, text_style_center), pass_or_fail_pdf(stage), Paragraph(format_timedelta(stage.duration), text_style_center)]]
|
|
96
|
+
test_table = Table(inner_table)
|
|
97
|
+
test_table.setStyle(INNER_TABLE_STYLE)
|
|
98
|
+
elements.append(test_table)
|
|
99
|
+
elements.append(Spacer(1, 20))
|
|
100
|
+
elements += stages_breakdown
|
|
101
|
+
elements.append(PageBreak())
|
|
102
|
+
summary_table = Table([["Name", "Result", "Duration"]] + summary_data)
|
|
103
|
+
summary_table.setStyle(INNER_TABLE_STYLE)
|
|
104
|
+
elements = hdr_page + [summary_table, PageBreak()] + elements
|
|
105
|
+
|
|
106
|
+
doc.build(elements)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
##################################
|
|
110
|
+
# PDF
|
|
111
|
+
##################################
|
|
112
|
+
STYLES_PDF = {
|
|
113
|
+
"GREEN_HEADER": ParagraphStyle("Green Header", fontName="Helvetica-Bold", fontSize=20, textColor=colors.green, alignment=TA_CENTER),
|
|
114
|
+
"RED_HEADER": ParagraphStyle("Red Header", fontName="Helvetica-Bold", fontSize=20, textColor=colors.red, alignment=TA_CENTER),
|
|
115
|
+
"MODULE_HEADER": ParagraphStyle("Module Header", fontName="Helvetica-Bold", fontSize=16, textColor=colors.navy, alignment=TA_CENTER),
|
|
116
|
+
"TEST_HEADER": ParagraphStyle("Test Header", fontName="Helvetica-Bold", fontSize=12, textColor=colors.black, alignment=TA_CENTER),
|
|
117
|
+
"BLACK": ParagraphStyle("Black", fontName="Helvetica", fontSize=9, textColor=colors.black, splitLongWords=False, alignment=TA_CENTER, wordWrap = 'CJK'),
|
|
118
|
+
"BLACK_LEFT": ParagraphStyle("Black Left", fontName="Helvetica", fontSize=9, textColor=colors.black, splitLongWords=False, alignment=TA_LEFT, wordWrap = 'CJK'),
|
|
119
|
+
"BLACK_BOLD": ParagraphStyle("Black Bold", fontName="Helvetica-Bold", fontSize=9, textColor=colors.black, splitLongWords=False, alignment=TA_LEFT, wordWrap = 'CJK'),
|
|
120
|
+
"BLUE": ParagraphStyle("Blue", fontName="Helvetica-Bold", fontSize=9, textColor=colors.navy, splitLongWords=False, alignment=TA_CENTER),
|
|
121
|
+
"CYAN": ParagraphStyle("Cyan", fontName="Helvetica-Bold", fontSize=9, textColor=colors.cyan, splitLongWords=False, alignment=TA_CENTER),
|
|
122
|
+
"GREEN": ParagraphStyle("Green", fontName="Helvetica-Bold", fontSize=9, textColor=colors.green, splitLongWords=False, alignment=TA_CENTER),
|
|
123
|
+
"WARNING": ParagraphStyle("Warning", fontName="Helvetica-Bold", fontSize=9, textColor=colors.gold, splitLongWords=False, alignment=TA_CENTER),
|
|
124
|
+
"RED": ParagraphStyle("Red", fontName="Helvetica-Bold", fontSize=9, textColor=colors.red, splitLongWords=False, alignment=TA_CENTER),
|
|
125
|
+
"GRAY": ParagraphStyle("Gray", fontName="Helvetica-Bold", fontSize=9, textColor=colors.gray, splitLongWords=False, alignment=TA_CENTER),
|
|
126
|
+
}
|
|
127
|
+
def color_pdf(c, t):
|
|
128
|
+
style = STYLES_PDF.get(c, ParagraphStyle("Default"))
|
|
129
|
+
return Paragraph(t, style)
|
|
130
|
+
pdf_result_map = {TEST_FAILED: color_pdf("RED", "FAILED"), TEST_INCONCLUSIVE: color_pdf("WARNING", "INCONCLUSIVE"),
|
|
131
|
+
TEST_PASSED: color_pdf("GREEN", "PASSED"), TEST_INFO: color_pdf("CYAN", "INFO"),
|
|
132
|
+
TEST_WARNING: color_pdf("WARNING", "WARNING"), TEST_OPTIONAL: color_pdf("GRAY", "OPTIONAL")}
|
|
133
|
+
pass_or_fail_pdf = lambda obj : pdf_result_map[obj.rc]
|
|
134
|
+
|
|
135
|
+
INNER_TABLE_STYLE = TableStyle([
|
|
136
|
+
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
|
|
137
|
+
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
|
|
138
|
+
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
|
|
139
|
+
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
|
|
140
|
+
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
|
141
|
+
('FONTSIZE', (0, 0), (-1, 0), 9),
|
|
142
|
+
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
|
|
143
|
+
('BACKGROUND', (0, 1), (-1, -1), colors.whitesmoke),
|
|
144
|
+
('WORDWRAP', (0, 0), (-1, -1), False),
|
|
145
|
+
])
|
gw_certificate/gw_certificate.py
CHANGED
|
@@ -20,6 +20,7 @@ from gw_certificate.tests import *
|
|
|
20
20
|
from gw_certificate.interface.uart_ports import get_uart_ports
|
|
21
21
|
from gw_certificate.api_if.gw_capabilities import GWCapabilities
|
|
22
22
|
from gw_certificate.tests import TESTS_NO_UART
|
|
23
|
+
import gw_certificate.cert_results as cert_results
|
|
23
24
|
|
|
24
25
|
GW_CERT_VERSION = importlib.metadata.version("wiliot-certificate")
|
|
25
26
|
|
|
@@ -45,14 +46,16 @@ class GWCertificate:
|
|
|
45
46
|
aggregation_time=0, env='prod'):
|
|
46
47
|
# Runtime
|
|
47
48
|
self.env_dirs = WiliotDir()
|
|
48
|
-
self.current_datetime = datetime.datetime.now()
|
|
49
|
-
self.
|
|
49
|
+
self.current_datetime = datetime.datetime.now()
|
|
50
|
+
self.duration = None
|
|
51
|
+
self.certificate_dir = os.path.join(self.env_dirs.get_wiliot_root_app_dir(), 'gw-certificate', self.current_datetime.strftime('%Y%m%d_%H%M%S'))
|
|
50
52
|
self.env_dirs.create_dir(self.certificate_dir)
|
|
51
53
|
self.logger_filename = initialize_logger(self.certificate_dir)
|
|
52
54
|
self.logger_filepath = os.path.join(self.certificate_dir, f'{self.logger_filename}.log')
|
|
53
55
|
self.mqtt_logger_filepath = os.path.join(self.certificate_dir, f'{self.logger_filename}_mqtt.log')
|
|
54
56
|
self.sniffer_logger_filepath = os.path.join(self.certificate_dir, f'{self.logger_filename}_sniffer.log')
|
|
55
|
-
self.result_html_path = os.path.join(self.certificate_dir, f'results_{self.current_datetime}.html')
|
|
57
|
+
self.result_html_path = os.path.join(self.certificate_dir, f'results_{self.current_datetime.strftime('%Y%m%d_%H%M%S')}.html')
|
|
58
|
+
self.result_pdf_path = os.path.join(self.certificate_dir, f'results_{self.current_datetime.strftime('%Y%m%d_%H%M%S')}.pdf')
|
|
56
59
|
self.template_engine = TemplateEngine()
|
|
57
60
|
self.env = env
|
|
58
61
|
|
|
@@ -68,6 +71,7 @@ class GWCertificate:
|
|
|
68
71
|
self.stress_pps = stress_pps
|
|
69
72
|
self.aggregation_time = aggregation_time
|
|
70
73
|
self.actions = actions
|
|
74
|
+
self.error = ""
|
|
71
75
|
|
|
72
76
|
# UART-related. Require only when running tests that need it
|
|
73
77
|
self.use_uart = not all(test in TESTS_NO_UART for test in tests)
|
|
@@ -76,7 +80,8 @@ class GWCertificate:
|
|
|
76
80
|
self.uart_comports = get_uart_ports()
|
|
77
81
|
debug_print(f'UART Ports:{self.uart_comports}')
|
|
78
82
|
if len(self.uart_comports) < 1:
|
|
79
|
-
|
|
83
|
+
self.error = "A Wiliot certification kit must be connected to USB!"
|
|
84
|
+
raise GWCertificateError(self.error)
|
|
80
85
|
|
|
81
86
|
for port in self.uart_comports:
|
|
82
87
|
try:
|
|
@@ -85,13 +90,18 @@ class GWCertificate:
|
|
|
85
90
|
except UARTError as e:
|
|
86
91
|
debug_print(f'Port: {port} - {e}')
|
|
87
92
|
if type(self.uart) is not UARTInterface:
|
|
88
|
-
|
|
93
|
+
self.error = "Cannot initialize any port!"
|
|
94
|
+
raise GWCertificateError(self.error)
|
|
89
95
|
self.ble_sim = BLESimulator(self.uart)
|
|
90
96
|
self.sniffer = BLESniffer(self.uart, logger_filepath=self.sniffer_logger_filepath)
|
|
91
97
|
|
|
92
98
|
# Tests
|
|
93
99
|
self.tests = [t(**self.__dict__) for t in tests]
|
|
94
100
|
debug_print(f'Running Tests: {self.tests}')
|
|
101
|
+
|
|
102
|
+
def runtime(self):
|
|
103
|
+
datetime.timedelta
|
|
104
|
+
return datetime.datetime.now() - self.current_datetime
|
|
95
105
|
|
|
96
106
|
def run_tests(self):
|
|
97
107
|
debug_print("Sleeping 20 seconds after mqtt connect")
|
|
@@ -125,11 +135,13 @@ class GWCertificate:
|
|
|
125
135
|
sniffer_log = sniffer_log,
|
|
126
136
|
gw_id = self.gw_id,
|
|
127
137
|
version = self.gw_cert_version,
|
|
128
|
-
datetime = self.current_datetime)
|
|
138
|
+
datetime = self.current_datetime.strftime('%Y%m%d_%H%M%S'))
|
|
129
139
|
with open(self.result_html_path, 'w', encoding="utf-8") as f:
|
|
130
140
|
f.write(html)
|
|
141
|
+
cert_results.generate_pdf_results_file(self)
|
|
131
142
|
debug_print("Test Finished. Results HTML Saved: " + self.result_html_path)
|
|
132
143
|
webbrowser.open('file://' + os.path.realpath(self.result_html_path))
|
|
144
|
+
webbrowser.open('file://' + os.path.realpath(self.result_pdf_path))
|
|
133
145
|
|
|
134
146
|
if __name__ == "__main__":
|
|
135
147
|
from api_secrets import *
|
|
@@ -27,8 +27,8 @@ def filter_actions(actions_names):
|
|
|
27
27
|
def main():
|
|
28
28
|
usage = (
|
|
29
29
|
"usage: wlt-gw-certificate [-h] -owner OWNER -gw GW\n"
|
|
30
|
-
f" [-tests {{connection, uplink, downlink, stress}}] [-update] [-pps {STRESS_DEFAULT_PPS}]\n"
|
|
31
|
-
"
|
|
30
|
+
f" [-tests {{connection, uplink, downlink, actions, stress}}] [-update] [-pps {STRESS_DEFAULT_PPS}]\n"
|
|
31
|
+
f" [-actions {{info, reboot, bridgeota}}] [-agg AGG] [-env {{prod, test, dev}}]"
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
parser = ArgumentParser(prog='wlt-gw-certificate',
|
|
@@ -43,7 +43,7 @@ def main():
|
|
|
43
43
|
help="Tests to run. Registration omitted by default.", required=False, nargs='+',
|
|
44
44
|
default=['connection', 'uplink', 'downlink', 'actions', 'stress'])
|
|
45
45
|
optional.add_argument('-actions', type=str, choices=['info', 'reboot', 'bridgeota'],
|
|
46
|
-
help="Action stages to run under ActionsTest", required=False, nargs='+', default=['info', 'reboot', '
|
|
46
|
+
help="Action stages to run under ActionsTest", required=False, nargs='+', default=['info', 'reboot', 'bridgeota'])
|
|
47
47
|
optional.add_argument('-update', action='store_true', help='Update test board firmware', default=False, required=False)
|
|
48
48
|
optional.add_argument('-pps', type=int, help='Single packets-per-second rate to simulate in the stress test',
|
|
49
49
|
choices=STRESS_DEFAULT_PPS, default=None, required=False)
|
gw_certificate/interface/mqtt.py
CHANGED
|
@@ -216,6 +216,7 @@ class MqttClient:
|
|
|
216
216
|
"gatewayId": gw_id,
|
|
217
217
|
"imageDirUrl": image_dir_url,
|
|
218
218
|
"versionUUID": version_uuid,
|
|
219
|
+
"upgradeBlSd": upgrade_bl_sd,
|
|
219
220
|
"txPacket": reboot_packet,
|
|
220
221
|
"txMaxRetries": tx_max_duration // 100,
|
|
221
222
|
"txMaxDurationMs": tx_max_duration,
|
|
@@ -167,7 +167,7 @@ class UARTInterface:
|
|
|
167
167
|
def check_fw_supported(self):
|
|
168
168
|
hex_version = version.parse(os.path.splitext(os.path.basename(LATEST_VERSION_PATH))[0].split('_')[0])
|
|
169
169
|
if self.fw_version >= hex_version:
|
|
170
|
-
debug_print(f'
|
|
170
|
+
debug_print(f'Certification kit version {self.fw_version}')
|
|
171
171
|
return True
|
|
172
172
|
return False
|
|
173
173
|
|
gw_certificate/tests/actions.py
CHANGED
|
@@ -128,7 +128,7 @@ class BridgeOTAStage(GenericActionsStage):
|
|
|
128
128
|
def __init__(self, **kwargs):
|
|
129
129
|
super().__init__(**kwargs, stage_name=type(self).__name__)
|
|
130
130
|
self.stage_tooltip = "Issues a bridge OTA action to the gateway. Expects it to upgrade the bridge"
|
|
131
|
-
self.error_summary = "
|
|
131
|
+
self.error_summary = "Bridge wasn't upgraded."
|
|
132
132
|
self.action = "Bridge Upgrade"
|
|
133
133
|
|
|
134
134
|
OTA_VERSIONS_TO_USE = ("4.4.52", "4.4.53")
|
|
@@ -195,6 +195,7 @@ class BridgeOTAStage(GenericActionsStage):
|
|
|
195
195
|
|
|
196
196
|
# Calculate whether stage pass/failed
|
|
197
197
|
if self.action_status is None or self.status_code != 0:
|
|
198
|
+
debug_print("Failed to receive an actionStatus message.")
|
|
198
199
|
self.stage_pass = MINIMUM_SCORE
|
|
199
200
|
self.add_to_stage_report(f"The bridge OTA test failed")
|
|
200
201
|
if self.action_status is None:
|
|
@@ -204,17 +205,22 @@ class BridgeOTAStage(GenericActionsStage):
|
|
|
204
205
|
elif self.status_code != 0:
|
|
205
206
|
self.add_to_stage_report(f"Uploaded actionStatus status value received is {self.status_code}.")
|
|
206
207
|
if self.current_version == self.desired_version:
|
|
208
|
+
debug_print("Bridge was upgraded successfully")
|
|
209
|
+
self.error_summary = "Failed to receive actionStatus message."
|
|
207
210
|
self.add_to_stage_report(f"Note that the bridge was actually upgraded successfully.")
|
|
211
|
+
self.add_to_stage_report(f"Reboot packet received {(self.reboot_packet_ts - self.start_time).total_seconds():.1f}s after start.")
|
|
208
212
|
self.add_to_stage_report(f"{GW_BRIDGE_OTA_DOC}")
|
|
209
213
|
else:
|
|
210
214
|
if self.current_version == self.desired_version:
|
|
211
215
|
self.stage_pass = PERFECT_SCORE
|
|
216
|
+
debug_print("Bridge was upgraded successfully, actionStatus message received")
|
|
212
217
|
self.add_to_stage_report(f"Bridge was upgraded and an actionStatus message was received from the gateway.")
|
|
213
218
|
self.add_to_stage_report(f"Action status received {(self.action_status_ts - self.start_time).total_seconds():.1f}s after start.")
|
|
214
219
|
self.add_to_stage_report(f"Reboot packet received {(self.reboot_packet_ts - self.start_time).total_seconds():.1f}s after start.")
|
|
215
220
|
self.add_to_stage_report(f"Action status received {(self.action_status_ts - self.reboot_packet_ts).total_seconds():.1f}s after reboot.")
|
|
216
221
|
else:
|
|
217
222
|
self.stage_pass = MINIMUM_SCORE
|
|
223
|
+
debug_print("Bridge failed to upgrade")
|
|
218
224
|
self.add_to_stage_report(f"The bridge OTA test failed")
|
|
219
225
|
self.add_to_stage_report(f"Uploaded actionStatus message indicated success although the bridge was not upgraded.")
|
|
220
226
|
|
|
@@ -248,7 +254,6 @@ class ActionsTest(GenericTest):
|
|
|
248
254
|
|
|
249
255
|
def run(self):
|
|
250
256
|
super().run()
|
|
251
|
-
self.test_pass = PERFECT_SCORE
|
|
252
257
|
for stage in self.stages:
|
|
253
258
|
stage.prepare_stage()
|
|
254
259
|
stage.run()
|
|
@@ -182,5 +182,5 @@ class ConnectionTest(GenericTest):
|
|
|
182
182
|
for stage in self.stages:
|
|
183
183
|
stage.prepare_stage()
|
|
184
184
|
stage.run()
|
|
185
|
-
self.test_pass = PassCriteria.calc_for_test(self, stage)
|
|
186
185
|
self.add_to_test_report(stage.generate_stage_report())
|
|
186
|
+
self.test_pass = PassCriteria.calc_for_test(self, stage)
|
gw_certificate/tests/generic.py
CHANGED
|
@@ -7,6 +7,7 @@ from gw_certificate.common.debug import debug_print
|
|
|
7
7
|
from gw_certificate.api_if.gw_capabilities import GWCapabilities
|
|
8
8
|
from gw_certificate.interface.ble_simulator import BLESimulator
|
|
9
9
|
from gw_certificate.interface.mqtt import MqttClient
|
|
10
|
+
from gw_certificate.ag.ut_defines import TEST_PASSED, TEST_FAILED, TEST_INCONCLUSIVE, TEST_OPTIONAL, TEST_WARNING, TEST_INFO
|
|
10
11
|
|
|
11
12
|
PASS_STATUS = {True: 'PASS', False: 'FAIL'}
|
|
12
13
|
|
|
@@ -37,19 +38,6 @@ class PassCriteria():
|
|
|
37
38
|
return 'Inconclusive'
|
|
38
39
|
else:
|
|
39
40
|
return 'Fail'
|
|
40
|
-
|
|
41
|
-
@staticmethod
|
|
42
|
-
def missing_score(pass_value:int) -> int:
|
|
43
|
-
return PERFECT_SCORE - pass_value
|
|
44
|
-
|
|
45
|
-
@staticmethod
|
|
46
|
-
def calc_for_stage_uplink(pass_value:int, stage_name:str) -> int:
|
|
47
|
-
error_msg = "Insufficient amount of packets were scanned & uploaded by the gateway"
|
|
48
|
-
return pass_value, error_msg
|
|
49
|
-
|
|
50
|
-
@staticmethod
|
|
51
|
-
def calc_for_stage_stress(pass_value: int, stage_name:str) -> int:
|
|
52
|
-
return pass_value
|
|
53
41
|
|
|
54
42
|
@staticmethod
|
|
55
43
|
def calc_for_stage_downlink(rsquared, slope, stage_name:str):
|
|
@@ -99,12 +87,14 @@ class GenericTest:
|
|
|
99
87
|
self.pass_min = PASS_MINIMUM
|
|
100
88
|
self.inconclusive_min = INCONCLUSIVE_MINIMUM
|
|
101
89
|
self.start_time = None
|
|
90
|
+
self.duration = None
|
|
102
91
|
self.test_name = test_name
|
|
103
92
|
self.test_dir = os.path.join(self.certificate_dir, self.test_name)
|
|
104
93
|
self.env_dirs.create_dir(self.test_dir)
|
|
105
94
|
self.stages = []
|
|
106
95
|
self.test_tooltip = kwargs.get('test_tooltip', 'Missing tooltip')
|
|
107
96
|
self.result_indication = kwargs.get('result_indication', SCORE_BASED)
|
|
97
|
+
self.rc = TEST_PASSED
|
|
108
98
|
|
|
109
99
|
def __repr__(self):
|
|
110
100
|
return self.test_name
|
|
@@ -125,8 +115,12 @@ class GenericTest:
|
|
|
125
115
|
def create_test_html(self):
|
|
126
116
|
self.report_html = self.template_engine.render_template('test.html', test=self,
|
|
127
117
|
running_time = self.runtime())
|
|
128
|
-
|
|
118
|
+
|
|
129
119
|
def end_test(self):
|
|
120
|
+
self.determine_rc()
|
|
121
|
+
for stage in self.stages:
|
|
122
|
+
stage.determine_rc()
|
|
123
|
+
self.duration = self.runtime()
|
|
130
124
|
self.create_test_html()
|
|
131
125
|
|
|
132
126
|
def score_pass(self):
|
|
@@ -143,6 +137,21 @@ class GenericTest:
|
|
|
143
137
|
if self.test_pass < self.inconclusive_min:
|
|
144
138
|
return True
|
|
145
139
|
return False
|
|
140
|
+
|
|
141
|
+
def determine_rc(self):
|
|
142
|
+
# Set test rc - defaults to TEST_PASSED (rc=0)
|
|
143
|
+
if self.result_indication == 'info':
|
|
144
|
+
if self.score_pass():
|
|
145
|
+
self.rc = TEST_INFO
|
|
146
|
+
else:
|
|
147
|
+
self.rc = TEST_WARNING
|
|
148
|
+
elif self.result_indication == 'optional':
|
|
149
|
+
self.rc = TEST_OPTIONAL
|
|
150
|
+
else:
|
|
151
|
+
if self.score_inconclusive():
|
|
152
|
+
self.rc = TEST_INCONCLUSIVE
|
|
153
|
+
elif self.score_fail():
|
|
154
|
+
self.rc = TEST_FAILED
|
|
146
155
|
|
|
147
156
|
|
|
148
157
|
class GenericStage():
|
|
@@ -156,9 +165,11 @@ class GenericStage():
|
|
|
156
165
|
self.report = ''
|
|
157
166
|
self.report_html = ''
|
|
158
167
|
self.start_time = None
|
|
168
|
+
self.duration = None
|
|
159
169
|
self.csv_path = os.path.join(self.test_dir, f'{self.stage_name}.csv')
|
|
160
170
|
self.stage_tooltip = kwargs.get('stage_tooltip', 'Missing tooltip')
|
|
161
171
|
self.error_summary = kwargs.get('error_summary', ERR_SUMMARY_DEFAULT)
|
|
172
|
+
self.rc = TEST_PASSED
|
|
162
173
|
|
|
163
174
|
def __repr__(self):
|
|
164
175
|
return self.stage_name
|
|
@@ -180,11 +191,14 @@ class GenericStage():
|
|
|
180
191
|
|
|
181
192
|
def add_report_header(self):
|
|
182
193
|
uncapitalize = lambda s: s[:1].lower() + s[1:] if s else ''
|
|
183
|
-
self.
|
|
194
|
+
self.duration = datetime.datetime.now() - self.start_time
|
|
195
|
+
self.add_to_stage_report(f'Stage run time: {self.duration}')
|
|
184
196
|
self.add_to_stage_report(f'This stage {uncapitalize(self.stage_tooltip)}.')
|
|
185
197
|
self.add_report_line_separator()
|
|
186
198
|
|
|
187
199
|
def add_report_topic_validation(self, topic:Literal['status', 'data']):
|
|
200
|
+
pass
|
|
201
|
+
# Pass until validated
|
|
188
202
|
if self.topic_suffix != '':
|
|
189
203
|
return
|
|
190
204
|
valid_topic, invalid_msg, invalid_topic = self.mqttc.validate_serialization_topic(topic)
|
|
@@ -192,7 +206,7 @@ class GenericStage():
|
|
|
192
206
|
# For now not failing stage since the customBroker command include topics explicitly
|
|
193
207
|
# self.stage_pass = MINIMUM_SCORE
|
|
194
208
|
# self.error_summary += "Invalid serialization-topic combination. "
|
|
195
|
-
self.add_to_stage_report(f'
|
|
209
|
+
self.add_to_stage_report(f'Note: Received message on {invalid_topic} although serialization is {self.mqttc.get_serialization()}')
|
|
196
210
|
|
|
197
211
|
def score_pass(self):
|
|
198
212
|
if self.stage_pass >= self.pass_min:
|
|
@@ -208,4 +222,16 @@ class GenericStage():
|
|
|
208
222
|
if self.stage_pass < self.inconclusive_min:
|
|
209
223
|
return True
|
|
210
224
|
return False
|
|
211
|
-
|
|
225
|
+
|
|
226
|
+
def determine_rc(self):
|
|
227
|
+
# Set stage rc - defaults to TEST_PASSED (rc=0)
|
|
228
|
+
if self.result_indication == 'info':
|
|
229
|
+
if self.score_pass():
|
|
230
|
+
self.rc = TEST_INFO
|
|
231
|
+
else:
|
|
232
|
+
self.rc = TEST_WARNING
|
|
233
|
+
else:
|
|
234
|
+
if self.score_inconclusive():
|
|
235
|
+
self.rc = TEST_INCONCLUSIVE
|
|
236
|
+
elif self.score_fail():
|
|
237
|
+
self.rc = TEST_FAILED
|
|
@@ -66,6 +66,7 @@ class GenericRegistrationStage(GenericStage):
|
|
|
66
66
|
debug_print(f"Kick response:{response}")
|
|
67
67
|
|
|
68
68
|
def validate_kong_logs(self, endpoint:Literal['device-authorize', 'registry', 'token', 'refresh']):
|
|
69
|
+
message = None
|
|
69
70
|
try:
|
|
70
71
|
message = self.edge.get_kong_logs(self.gw_id)
|
|
71
72
|
except WiliotCloudError as wce:
|
|
@@ -78,7 +79,7 @@ class GenericRegistrationStage(GenericStage):
|
|
|
78
79
|
return False
|
|
79
80
|
elif status_code == None:
|
|
80
81
|
raise wce
|
|
81
|
-
if message.get('status_code') != 200:
|
|
82
|
+
if isinstance(message, dict) and message.get('status_code') != 200:
|
|
82
83
|
debug_print(f"Failed fetching logs, status_code:{message.get('status_code')}")
|
|
83
84
|
return False
|
|
84
85
|
|