wiliot-certificate 1.3.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.
Files changed (51) hide show
  1. gw_certificate/__init__.py +0 -0
  2. gw_certificate/ag/ut_defines.py +361 -0
  3. gw_certificate/ag/wlt_types.py +85 -0
  4. gw_certificate/ag/wlt_types_ag.py +5310 -0
  5. gw_certificate/ag/wlt_types_data.py +64 -0
  6. gw_certificate/api/extended_api.py +1547 -0
  7. gw_certificate/api_if/__init__.py +0 -0
  8. gw_certificate/api_if/api_validation.py +40 -0
  9. gw_certificate/api_if/gw_capabilities.py +18 -0
  10. gw_certificate/common/analysis_data_bricks.py +1455 -0
  11. gw_certificate/common/debug.py +63 -0
  12. gw_certificate/common/utils.py +219 -0
  13. gw_certificate/common/utils_defines.py +102 -0
  14. gw_certificate/common/wltPb_pb2.py +72 -0
  15. gw_certificate/common/wltPb_pb2.pyi +227 -0
  16. gw_certificate/gw_certificate.py +138 -0
  17. gw_certificate/gw_certificate_cli.py +70 -0
  18. gw_certificate/interface/ble_simulator.py +91 -0
  19. gw_certificate/interface/ble_sniffer.py +189 -0
  20. gw_certificate/interface/if_defines.py +35 -0
  21. gw_certificate/interface/mqtt.py +469 -0
  22. gw_certificate/interface/packet_error.py +22 -0
  23. gw_certificate/interface/pkt_generator.py +720 -0
  24. gw_certificate/interface/uart_if.py +193 -0
  25. gw_certificate/interface/uart_ports.py +20 -0
  26. gw_certificate/templates/results.html +241 -0
  27. gw_certificate/templates/stage.html +22 -0
  28. gw_certificate/templates/table.html +6 -0
  29. gw_certificate/templates/test.html +38 -0
  30. gw_certificate/tests/__init__.py +11 -0
  31. gw_certificate/tests/actions.py +131 -0
  32. gw_certificate/tests/bad_crc_to_PER_quantization.csv +51 -0
  33. gw_certificate/tests/connection.py +181 -0
  34. gw_certificate/tests/downlink.py +174 -0
  35. gw_certificate/tests/generic.py +161 -0
  36. gw_certificate/tests/registration.py +288 -0
  37. gw_certificate/tests/static/__init__.py +0 -0
  38. gw_certificate/tests/static/connection_defines.py +9 -0
  39. gw_certificate/tests/static/downlink_defines.py +9 -0
  40. gw_certificate/tests/static/generated_packet_table.py +209 -0
  41. gw_certificate/tests/static/packet_table.csv +10051 -0
  42. gw_certificate/tests/static/references.py +4 -0
  43. gw_certificate/tests/static/uplink_defines.py +20 -0
  44. gw_certificate/tests/throughput.py +244 -0
  45. gw_certificate/tests/uplink.py +683 -0
  46. wiliot_certificate-1.3.0a1.dist-info/LICENSE +21 -0
  47. wiliot_certificate-1.3.0a1.dist-info/METADATA +113 -0
  48. wiliot_certificate-1.3.0a1.dist-info/RECORD +51 -0
  49. wiliot_certificate-1.3.0a1.dist-info/WHEEL +5 -0
  50. wiliot_certificate-1.3.0a1.dist-info/entry_points.txt +2 -0
  51. wiliot_certificate-1.3.0a1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,288 @@
1
+ import datetime
2
+ import time
3
+ import os
4
+ from enum import Enum
5
+
6
+ from wiliot_api.api_client import WiliotCloudError
7
+
8
+ from gw_certificate.common.debug import debug_print
9
+ from gw_certificate.tests.generic import INCONCLUSIVE_MINIMUM, PassCriteria, MINIMUM_SCORE, PERFECT_SCORE, GenericStage, GenericTest, INFORMATIVE
10
+ from gw_certificate.api.extended_api import ExtendedEdgeClient
11
+ from gw_certificate.tests.static.connection_defines import *
12
+ from gw_certificate.tests.static.references import GW_REGISTER_DOC, GW_MQTT_DOC
13
+
14
+
15
+ # HELPER DEFINES
16
+ REG_CERT_OWNER_ID = 'gw-certification-account'
17
+ ENV_VAR_AWS = 'WLT_REG_CERT_KEY_AWS'
18
+ STAGES_TIMEOUT = 2
19
+ TOKEN_EXPIRY_MINUTES = 3
20
+
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
+ ERROR_NO_REGISTER = 'Gateway did not register itself in time.'
23
+ ERROR_NO_ONLINE = 'Gateway did not connect to MQTT in time.'
24
+ ERROR_NO_ACTIVE = 'Gateway did not upload a status message with its configurations in time.'
25
+ ERROR_NO_REFRESH = 'Gateway did not reconnect to MQTT in time.'
26
+
27
+ # HELPER CLASSES
28
+ class GetGwField(Enum):
29
+ STATUS = 'status'
30
+ ONLINE = 'online'
31
+ ONLINE_UPDATED_AT = 'onlineUpdatedAt'
32
+ ACTIVATED_AT = 'activatedAt'
33
+
34
+ class Status(Enum):
35
+ PRE_REGISTERED = 'pre-registered'
36
+ APPROVED = 'approved'
37
+ ACTIVE = 'active'
38
+
39
+ class Online(Enum):
40
+ FALSE = False
41
+ TRUE = True
42
+
43
+ class SharedData():
44
+ """
45
+ Hold variables which values must be shared between different stages.
46
+ gw_online_ts hold the time in which the gateway status became online
47
+ """
48
+ def __init__(self):
49
+ self.gw_online_ts = None
50
+
51
+ # TEST STAGES
52
+ class GenericRegistrationStage(GenericStage):
53
+ def __init__(self, gw_id, edge:ExtendedEdgeClient, **kwargs):
54
+ self.__dict__.update(kwargs)
55
+ self.gw_id = gw_id
56
+ self.edge = edge
57
+ super().__init__(**self.__dict__)
58
+
59
+ def get_gateway_field(self, field:GetGwField):
60
+ temp = self.edge.get_gateway(self.gw_id)
61
+ return temp[field.value]
62
+
63
+ class RegistryStage(GenericRegistrationStage):
64
+ def __init__(self, **kwargs):
65
+ self.__dict__.update(kwargs)
66
+ self.stage_tooltip = "Validate the gateway's registry step"
67
+ super().__init__(stage_name=type(self).__name__, **self.__dict__)
68
+
69
+ def prepare_stage(self):
70
+ super().prepare_stage()
71
+ debug_print('Pre-registering the gateway, please make sure it is not registered to any other account '
72
+ 'and that your device is ready to run the registration flow')
73
+
74
+ def pre_register_gw_anew(gw_id):
75
+ try:
76
+ pre_registered = self.edge.register_gateway([gw_id])
77
+ except WiliotCloudError as wce:
78
+ wce_dict = wce.args[0]
79
+ status_code = wce_dict.get('status_code')
80
+ msg = wce_dict.get('message')
81
+ if status_code == 400 and 'already exists' in msg:
82
+ debug_print(f'{gw_id} already exists in Wiliot platform! Deleting and pre-registering from scratch')
83
+ self.edge.delete_gateway(gw_id)
84
+ pre_registered = self.edge.register_gateway([gw_id])
85
+ else:
86
+ raise wce
87
+ return pre_registered
88
+
89
+ pre_registered = pre_register_gw_anew(self.gw_id)
90
+ if not pre_registered:
91
+ debug_print('Failed pre-registering the gateway')
92
+ raise Exception(f"Failed pre-registering the gateway. Make sure:\n-Your API key ({ENV_VAR_AWS}) is valid.\n"
93
+ "-You have a stable internet connection.\nOtherwise, try again later.")
94
+ debug_print(f"{self.gw_id} was pre-registered successfully")
95
+
96
+ def run(self):
97
+ super().run()
98
+ debug_print(f"Waiting for the gateway to finish the Registry step..")
99
+ timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT)
100
+ self.status = self.get_gateway_field(GetGwField.STATUS)
101
+ while datetime.datetime.now() < timeout and not any(self.status == s.value for s in {Status.APPROVED, Status.ACTIVE}):
102
+ time.sleep(5)
103
+ self.status = self.get_gateway_field(GetGwField.STATUS)
104
+
105
+ def generate_stage_report(self):
106
+ self.add_report_header()
107
+ if not any(self.status == s.value for s in {Status.APPROVED, Status.ACTIVE}):
108
+ self.stage_pass = MINIMUM_SCORE
109
+ self.error_summary = ERROR_NO_REGISTER
110
+ self.add_to_stage_report(ERROR_NO_REGISTER)
111
+ debug_print(f"The gateway failed to register. Its status is '{self.status}' while it is expected to be '{Status.APPROVED.value}'.")
112
+ self.add_to_stage_report(f"There was an error in the Device-authorize or Registry steps.")
113
+ self.add_to_stage_report(f"Please go over the Device-authorize and Registry sections in this document:\n{GW_REGISTER_DOC}")
114
+ # TODO Ideally we should know where the error is exactly and inform the user. We currently lack such resolution
115
+ else:
116
+ self.stage_pass = PERFECT_SCORE
117
+ self.add_to_stage_report("Device-authorize and Registry requests were issued well.")
118
+ self.add_to_stage_report("Gateway registered successfully.")
119
+ debug_print("Gateway registered successfully")
120
+
121
+ self.report_html = self.template_engine.render_template('stage.html', stage=self,
122
+ stage_report=self.report.split('\n'))
123
+ return super().generate_stage_report()
124
+
125
+ class OnlineStage(GenericRegistrationStage):
126
+ def __init__(self, **kwargs):
127
+ self.__dict__.update(kwargs)
128
+ self.stage_tooltip = "Validate the gateway become online on the platform"
129
+ super().__init__(stage_name=type(self).__name__, **self.__dict__)
130
+
131
+ def prepare_stage(self):
132
+ super().prepare_stage()
133
+
134
+ def run(self):
135
+ super().run()
136
+ debug_print(f"Waiting for the gateway to connect to MQTT..")
137
+ timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT)
138
+ self.online = self.get_gateway_field(GetGwField.ONLINE)
139
+ while datetime.datetime.now() < timeout and self.online != True:
140
+ time.sleep(5)
141
+ self.online = self.get_gateway_field(GetGwField.ONLINE)
142
+
143
+ def generate_stage_report(self):
144
+ self.add_report_header()
145
+ if self.online != True:
146
+ self.stage_pass = MINIMUM_SCORE
147
+ self.error_summary = ERROR_NO_ONLINE
148
+ self.add_to_stage_report(ERROR_NO_ONLINE)
149
+ self.add_to_stage_report(f"Either it didn't acquire a token or it didn't connect to MQTT in time.")
150
+ self.add_to_stage_report(f"Please go over the Poll For Token section in:\n{GW_REGISTER_DOC}")
151
+ self.add_to_stage_report(f"and the MQTT details in:\n{GW_MQTT_DOC}")
152
+ debug_print("Gateway did not connect ot MQTT within time limit")
153
+ # TODO Ideally we should know where the error is exactly and inform the user. We currently lack such resolution
154
+ else:
155
+ self.stage_pass = PERFECT_SCORE
156
+ self.add_to_stage_report("Token acquisition and MQTT connection were done succesfully.")
157
+ self.add_to_stage_report("Gateway is online.")
158
+ debug_print("Gateway connected to MQTT successfully, it is online")
159
+ self.shared_data.gw_online_ts = datetime.datetime.now()
160
+
161
+ self.report_html = self.template_engine.render_template('stage.html', stage=self,
162
+ stage_report=self.report.split('\n'))
163
+ return super().generate_stage_report()
164
+
165
+ class ActiveStage(GenericRegistrationStage):
166
+ def __init__(self, **kwargs):
167
+ self.__dict__.update(kwargs)
168
+ self.stage_tooltip = "Validate the gateway upload a status message upon MQTT connection"
169
+ super().__init__(stage_name=type(self).__name__, **self.__dict__)
170
+
171
+ def prepare_stage(self):
172
+ super().prepare_stage()
173
+
174
+ def run(self):
175
+ super().run()
176
+ debug_print(f"Waiting for the gateway to upload a status message..")
177
+ timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT)
178
+ self.status = self.get_gateway_field(GetGwField.STATUS)
179
+ while datetime.datetime.now() < timeout and self.status != Status.ACTIVE.value:
180
+ time.sleep(5)
181
+ self.status = self.get_gateway_field(GetGwField.STATUS)
182
+
183
+ def generate_stage_report(self):
184
+ self.add_report_header()
185
+ if self.status != Status.ACTIVE.value:
186
+ self.stage_pass = MINIMUM_SCORE
187
+ self.error_summary = ERROR_NO_ACTIVE
188
+ self.add_to_stage_report(ERROR_NO_ACTIVE)
189
+ self.add_to_stage_report(f"Please go over the Status section in:\n{GW_MQTT_DOC}")
190
+ debug_print("Gateway did not upload a status message upon connecting to MQTT")
191
+ else:
192
+ self.stage_pass = PERFECT_SCORE
193
+ self.add_to_stage_report("The gateway uploaded a status message in time.")
194
+ self.add_to_stage_report("Gateway is active.")
195
+ debug_print("Gateway uploaded a status message, it is active")
196
+
197
+ self.report_html = self.template_engine.render_template('stage.html', stage=self,
198
+ stage_report=self.report.split('\n'))
199
+ return super().generate_stage_report()
200
+
201
+ class RefreshStage(GenericRegistrationStage):
202
+ def __init__(self, **kwargs):
203
+ self.__dict__.update(kwargs)
204
+ self.stage_tooltip = "Validate the gateway refresh-token step"
205
+ super().__init__(stage_name=type(self).__name__, **self.__dict__)
206
+
207
+ def prepare_stage(self):
208
+ super().prepare_stage()
209
+
210
+ def run(self):
211
+ super().run()
212
+ debug_print(f"Waiting for the token to expire..")
213
+ timeout = self.shared_data.gw_online_ts + datetime.timedelta(minutes=TOKEN_EXPIRY_MINUTES)
214
+ while datetime.datetime.now() < timeout:
215
+ time.sleep(5)
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}")
220
+
221
+ debug_print(f"Token expired, kicking gateway")
222
+ kick_gw_from_mqtt()
223
+
224
+ debug_print(f"Waiting for the gateway to refresh its token and connect to MQTT..")
225
+ timeout = datetime.datetime.now() + datetime.timedelta(minutes=STAGES_TIMEOUT)
226
+ self.online = self.get_gateway_field(GetGwField.ONLINE)
227
+ while datetime.datetime.now() < timeout and self.online != True:
228
+ time.sleep(5)
229
+ self.online = self.get_gateway_field(GetGwField.ONLINE)
230
+
231
+ def generate_stage_report(self):
232
+ self.add_report_header()
233
+ if self.online != True:
234
+ self.stage_pass = MINIMUM_SCORE
235
+ self.error_summary = ERROR_NO_REFRESH
236
+ self.add_to_stage_report(ERROR_NO_REFRESH)
237
+ self.add_to_stage_report(f"Either it didn't refresh its token or it didn't connect to MQTT in time.")
238
+ self.add_to_stage_report(f"Please go over the Refresh Token section in:\n{GW_REGISTER_DOC}")
239
+ self.add_to_stage_report(f"and the MQTT details in:\n{GW_MQTT_DOC}")
240
+ debug_print("Gateway did not reconnect MQTT (was the token refreshed?)")
241
+ else:
242
+ self.stage_pass = PERFECT_SCORE
243
+ self.add_to_stage_report("Token refresh and MQTT reconnection were done succesfully.")
244
+ self.add_to_stage_report("Gateway is online.")
245
+
246
+ self.report_html = self.template_engine.render_template('stage.html', stage=self,
247
+ stage_report=self.report.split('\n'))
248
+ return super().generate_stage_report()
249
+
250
+
251
+ STAGES = [RegistryStage, OnlineStage, ActiveStage, RefreshStage]
252
+
253
+ class RegistrationTest(GenericTest):
254
+ def __init__(self, **kwargs):
255
+ self.__dict__.update(kwargs)
256
+ self.test_tooltip = "Stages related to the process of registering a gateway with the Wiliot cloud"
257
+
258
+ # Set up the edge client for all stages
259
+ env = '' if self.env == 'prod' else '_' + str(self.env).upper()
260
+ api_sec_key = os.environ.get(ENV_VAR_AWS + env)
261
+ if not api_sec_key:
262
+ raise Exception(f"An API security key must be set to the envrionment variable {ENV_VAR_AWS} in order to run the RegistrationTest")
263
+ self.edge = ExtendedEdgeClient(api_sec_key, REG_CERT_OWNER_ID, env=self.env)
264
+
265
+ self.shared_data = SharedData()
266
+
267
+ super().__init__(**self.__dict__, test_name=type(self).__name__)
268
+ stages = STAGES
269
+ self.stages = [stage(**self.__dict__) for stage in stages]
270
+
271
+ def run(self):
272
+ super().run()
273
+ self.test_pass = PERFECT_SCORE
274
+ for idx, stage in enumerate(self.stages):
275
+ stage.prepare_stage()
276
+ stage.run()
277
+ self.add_to_test_report(stage.generate_stage_report())
278
+ self.test_pass = PassCriteria.calc_for_test(self.test_pass, stage)
279
+ if self.test_pass != PERFECT_SCORE and stage != self.stages[-1]:
280
+ debug_print(f"{type(self).__name__} stopped without running all of its stages since {type(stage).__name__} failed")
281
+ self.add_to_test_report(f"{type(self).__name__} stopped without running all of its stages since {type(stage).__name__} failed")
282
+ self.stages = self.stages[0:idx + 1]
283
+ break
284
+
285
+ def end_test(self):
286
+ debug_print(f'Deleting {self.gw_id} from {REG_CERT_OWNER_ID} before exiting')
287
+ self.edge.delete_gateway(self.gw_id)
288
+ super().end_test()
File without changes
@@ -0,0 +1,9 @@
1
+ CSV_NAME = 'bad_crc_to_PER_quantization.csv'
2
+ INTERFERENCE_ANALYSIS_FW_VER = "4.2.0"
3
+ CHANNELS_TO_ANALYZE = [(37, 2402), (38, 2426), (39, 2480)]
4
+ CNTRS_LISTEN_TIME_SEC = 30
5
+ MAX_UNSIGNED_32_BIT = 4294967295
6
+ NON_WLT_RX = 'non_wlt_rx'
7
+ WLT_RX = 'wlt_rx'
8
+ BAD_CRC = 'bad_crc'
9
+ CNTRS_KEYS = [NON_WLT_RX, WLT_RX, BAD_CRC]
@@ -0,0 +1,9 @@
1
+ SANITY_STAGE = "SanityStage"
2
+ CORRELATION_STAGE = "CorrelationStage"
3
+ STAGE_CONFIGS = {
4
+ SANITY_STAGE:([i for i in range(700, 901, 100)], range(3)),
5
+ CORRELATION_STAGE:([i for i in range(100, 2001, 400)], range(3))}
6
+ TX_MAX_DURATIONS = range(100, 501, 100)
7
+ RETRIES = range(5)
8
+ MAX_RX_TX_PERIOD_SECS = 0.255
9
+ DEFAULT_BRG_ID = "FFFFFFFFFFFF"
@@ -0,0 +1,209 @@
1
+
2
+ import pkg_resources
3
+ import pandas as pd
4
+
5
+ from gw_certificate.common.debug import debug_print
6
+ from gw_certificate.interface.pkt_generator import BrgPktGeneratorNetwork
7
+ from gw_certificate.interface.if_defines import *
8
+ from gw_certificate.interface.packet_error import PacketError
9
+
10
+ CSV_NAME = 'packet_table.csv'
11
+ PACKET_TABLE_CSV_PATH = pkg_resources.resource_filename(__name__, CSV_NAME)
12
+
13
+ TEST_STRESS = 'stress'
14
+ TEST_COUPLING = 'coupling'
15
+ TEST_DOWNLINK = 'downlink'
16
+ TEST_UPLINK = 'uplink'
17
+ TEST_UNIFIED = 'unified'
18
+ TEST_SENSOR = 'sensor'
19
+
20
+ TESTS = [TEST_COUPLING, TEST_UPLINK, TEST_UNIFIED]
21
+ class GeneratedPacketTable:
22
+
23
+ def __init__(self) -> None:
24
+ self.brg_network = BrgPktGeneratorNetwork()
25
+ self.table = pd.read_csv(PACKET_TABLE_CSV_PATH)
26
+
27
+ def get_data(self, test, duplication, time_delay, bridge_idx) -> list:
28
+ assert test in TESTS, 'Invalid Test'
29
+ assert (duplication in UPLINK_DUPLICATIONS) or (duplication in UNIFIED_DUPLICATIONS), 'Invalid Duplication'
30
+ assert (time_delay in UPLINK_TIME_DELAYS) or (time_delay in UNIFIED_TIME_DELAYS), 'Invalid Time Delay'
31
+ assert bridge_idx in BRIDGES, 'Invalid Bridge'
32
+
33
+ t = self.table
34
+ return t.loc[((t['test'] == test) &
35
+ (t['duplication'] == duplication) &
36
+ (t['time_delay'] == time_delay) &
37
+ (t['bridge_idx'] == bridge_idx))].to_dict('records')[0]
38
+
39
+ def get_df(self, columns=None):
40
+ if columns is not None:
41
+ return self.table[columns]
42
+ return self.table
43
+
44
+ # def get_unified_data(self) -> pd.DataFrame:
45
+ # t = self.table
46
+ # return t.loc[((t['test'] == 'stress'))]
47
+
48
+ def get_stress_data(self) -> pd.DataFrame:
49
+ t = self.table
50
+ return t.loc[((t['test'] == 'stress'))]
51
+
52
+ def get_sensor_data(self) -> pd.DataFrame:
53
+ t = self.table
54
+ return t.loc[((t['test'] == 'sensor'))]
55
+
56
+ def get_mgmt_data(self) -> pd.DataFrame:
57
+ t = self.table
58
+ return t.loc[((t['test'] == 'mgmt'))]
59
+
60
+ def get_unified_data(self) -> pd.DataFrame:
61
+ t = self.table
62
+ return t.loc[((t['test'] == 'unified'))]
63
+
64
+ def _generate_packet_table(self):
65
+ packet_list = []
66
+
67
+ # UNIFIED TEST
68
+ for duplication in UNIFIED_DUPLICATIONS:
69
+ debug_print(f'Duplication {duplication}')
70
+ for time_delay in UNIFIED_TIME_DELAYS:
71
+ debug_print(f'Time Delay {time_delay}')
72
+ pkts = self.brg_network.get_new_pkt_unified()
73
+ for idx, brg in enumerate(self.brg_network.brg_list):
74
+ debug_print(f'Bridge {idx}')
75
+ data = pkts[idx]['data_packet']
76
+ brg_id = self.brg_network.brg_list[idx].bridge_id
77
+ # log the sent packet with relevant info from run
78
+ expected_pkt = brg.get_expected_mqtt_unified(full_data_pkt=data)
79
+ for pkt in expected_pkt:
80
+ pkt.update({'duplication': duplication, 'time_delay': time_delay})
81
+ packet_list.append({'test': TEST_UNIFIED,
82
+ 'duplication': duplication,
83
+ 'time_delay': time_delay,
84
+ 'bridge_idx': idx,
85
+ 'expected_mqtt': expected_pkt
86
+ ,ADVA_PAYLOAD: data, 'bridge_id': brg_id,
87
+ 'adva': data[:12], 'payload': data[16:], 'pkt_id': data[-8:]
88
+ })
89
+
90
+ #STRESS TEST
91
+ i = 0
92
+ while i < 10000:
93
+ i += 1
94
+ pkts = self.brg_network.get_new_pkt_unified()
95
+ target_idx = 0
96
+ brg = self.brg_network.brg_list[target_idx]
97
+ debug_print(f'Bridge {target_idx}')
98
+ data = pkts[target_idx]['data_packet']
99
+ brg_id = brg.bridge_id
100
+ expected_pkt = brg.get_expected_mqtt_unified(full_data_pkt=data)
101
+ packet_list.append({
102
+ 'test': TEST_STRESS,
103
+ 'duplication': 1,
104
+ 'bridge_idx': target_idx,
105
+ 'expected_mqtt': expected_pkt,
106
+ ADVA_PAYLOAD: data,
107
+ 'bridge_id': brg_id,
108
+ 'adva': data[:12],
109
+ 'payload': data[16:],
110
+ 'pkt_id': data[-8:]
111
+ })
112
+
113
+ def _sensor_data(df):
114
+ hardcoded_data = [
115
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC020000B54D387A227038613C0D8E0FF376D199289FE6679AA0D902", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B87B44500000000000000000000009AA0D902", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC020000B54D387A227038613C0D8E0FF376D199289FE6679AA0D902", "payload":"90FC020000B54D387A227038613C0D8E0FF376D199289FE6679AA0D902" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B87B44500000000000000000000009AA0D902", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "9AA0D902"},
116
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC0200003A79C9BEF41223AC3F4A962D97F519C9DA06CA5F4F643826", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B7D396B00000000000000000000004F643826", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC0200003A79C9BEF41223AC3F4A962D97F519C9DA06CA5F4F643826", "payload":"90FC0200003A79C9BEF41223AC3F4A962D97F519C9DA06CA5F4F643826" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B7D396B00000000000000000000004F643826", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "4F643826"},
117
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC0200001B65E90DDC0090175F67F3F8E7E3DA2FFA6A945076D1D979", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B39B69D000000000000000000000076D1D979", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC0200001B65E90DDC0090175F67F3F8E7E3DA2FFA6A945076D1D979", "payload":"90FC0200001B65E90DDC0090175F67F3F8E7E3DA2FFA6A945076D1D979" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B39B69D000000000000000000000076D1D979", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "76D1D979"},
118
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC020000D337363E43CDDDFC897492917BCC2DA2977E2751E31CAAA6", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B3E21640000000000000000000000E31CAAA6", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC020000D337363E43CDDDFC897492917BCC2DA2977E2751E31CAAA6", "payload":"90FC020000D337363E43CDDDFC897492917BCC2DA2977E2751E31CAAA6" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B3E21640000000000000000000000E31CAAA6", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "E31CAAA6"},
119
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC0200001D646652892618D2CE80CA4A880A8CF46346C7743C509B54", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B5BCD2900000000000000000000003C509B54", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC0200001D646652892618D2CE80CA4A880A8CF46346C7743C509B54", "payload":"90FC0200001D646652892618D2CE80CA4A880A8CF46346C7743C509B54" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B5BCD2900000000000000000000003C509B54", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "3C509B54"},
120
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC020000CEE15F2E2EE026B22C739867453C6E2E108E9E8610FE7F07", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B9647FC000000000000000000000010FE7F07", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC020000CEE15F2E2EE026B22C739867453C6E2E108E9E8610FE7F07", "payload":"90FC020000CEE15F2E2EE026B22C739867453C6E2E108E9E8610FE7F07" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B9647FC000000000000000000000010FE7F07", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "10FE7F07"},
121
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC0200002CC60917A02CB02367771BE9EA20F9666ED8A06F6612745B", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177BF1EBC500000000000000000000006612745B", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC0200002CC60917A02CB02367771BE9EA20F9666ED8A06F6612745B", "payload":"90FC0200002CC60917A02CB02367771BE9EA20F9666ED8A06F6612745B" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177BF1EBC500000000000000000000006612745B", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "6612745B"},
122
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC02000007EFE229109B044DB995A506179C99094720AE8BF9F78C1A", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B6CEC9A0000000000000000000000F9F78C1A", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC02000007EFE229109B044DB995A506179C99094720AE8BF9F78C1A", "payload":"90FC02000007EFE229109B044DB995A506179C99094720AE8BF9F78C1A" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B6CEC9A0000000000000000000000F9F78C1A", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "F9F78C1A"},
123
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC0200002CA1E008E364D0DCF65631718BCD659DE3323A69A674F7B9", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B1051900000000000000000000000A674F7B9", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC0200002CA1E008E364D0DCF65631718BCD659DE3323A69A674F7B9", "payload":"90FC0200002CA1E008E364D0DCF65631718BCD659DE3323A69A674F7B9" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B1051900000000000000000000000A674F7B9", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "A674F7B9"},
124
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC02000049ADD722F535679C37983927655C974A4980B080045DA6C2", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B5280B20000000000000000000000045DA6C2", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC02000049ADD722F535679C37983927655C974A4980B080045DA6C2", "payload":"90FC02000049ADD722F535679C37983927655C974A4980B080045DA6C2" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B5280B20000000000000000000000045DA6C2", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "045DA6C2"},
125
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC0200004C8AD49C6D96923BFB70DF06554F5E8F438F1DF57E063773", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177BB4085900000000000000000000007E063773", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC0200004C8AD49C6D96923BFB70DF06554F5E8F438F1DF57E063773", "payload":"90FC0200004C8AD49C6D96923BFB70DF06554F5E8F438F1DF57E063773" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177BB4085900000000000000000000007E063773", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "7E063773"},
126
+ {"test": "sensor", "duplication": "5", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "90FC02000064A5B54285BB6BCDB457ABBED8EE26B4EB43B27A8C26781C", "duplication": 3, "time_delay": 20}, {"timestamp": 4278768225950047766, "payload": "C6FC0000EB3B613D08177B27363800000000000000000000008C26781C", "duplication": 3, "time_delay": 20}], ADVA_PAYLOAD: "F0287B2557141E1690FC02000064A5B54285BB6BCDB457ABBED8EE26B4EB43B27A8C26781C", "payload":"90FC02000064A5B54285BB6BCDB457ABBED8EE26B4EB43B27A8C26781C" ,"si": "3B613D0817FB1E16C6FC0000EB3B613D08177B27363800000000000000000000008C26781C", "bridge_id": "3B613D08177B", "adva": "F0287B255714", "pkt_id": "8C26781C"},
127
+ ]
128
+
129
+ hardcoded_df = pd.DataFrame(hardcoded_data)
130
+ return pd.concat([df, hardcoded_df], ignore_index=True)
131
+
132
+ def _mgmt_data(df):
133
+ hardcoded_data = [
134
+ # First pkt is HB, second is CFG_INFO of MODULE_IF
135
+ {"test": "mgmt", "duplication": "10", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "C6FC0000EE020AD2A365FEC65912095E9101FF1104EB0958D400110100", "duplication": 10, "time_delay": 20}], ADVA_PAYLOAD: "A365FEC659D21E16C6FC0000EE020AD2A365FEC65912095E9101FF1104EB0958D400110100", "payload": "C6FC0000EE020AD2A365FEC65912095E9101FF1104EB0958D400110100", "si": "", "bridge_id": "A365FEC65912", "adva": "A365FEC659D2", "pkt_id": "00110100"},
136
+ {"test": "mgmt", "duplication": "10", "time_delay": "20", "bridge_idx": 2, "expected_mqtt": [{"timestamp": 17305216968476073494, "payload": "C6FC0000EE110BD3A365FEC6591203040121E8F2FDB000000000000000", "duplication": 10, "time_delay": 20}], ADVA_PAYLOAD: "A365FEC659D21E16C6FC0000EE110BD3A365FEC6591203040121E8F2FDB000000000000000", "payload": "C6FC0000EE110BD3A365FEC6591203040121E8F2FDB000000000000000", "si": "", "bridge_id": "A365FEC65912", "adva": "A365FEC659D2", "pkt_id": "00000000"},
137
+ ]
138
+
139
+ hardcoded_df = pd.DataFrame(hardcoded_data)
140
+ return pd.concat([df, hardcoded_df], ignore_index=True)
141
+
142
+ df = pd.DataFrame(packet_list)
143
+ df = _sensor_data(df)
144
+ df = _mgmt_data(df)
145
+ df.to_csv(PACKET_TABLE_CSV_PATH)
146
+
147
+ class CouplingRunData:
148
+ def __init__(self, data) -> None:
149
+ self.test = data['test']
150
+ self.duplication = data['duplication']
151
+ self.time_delay = data['time_delay']
152
+ self.bridge_idx = data['bridge_idx']
153
+ self.packet_error = eval(data['packet_error'])
154
+ self.expected_mqtt = eval(data['expected_mqtt'])
155
+ self.data = data[ADVA_PAYLOAD]
156
+ self.si = data['si']
157
+ self.bridge_id = data['bridge_id']
158
+ self.scattered_time_delay = data['scattered_time_delay']
159
+
160
+
161
+ @classmethod
162
+ def get_data(cls, test, duplication, time_delay, bridge_idx):
163
+ packet_data = GeneratedPacketTable().get_data(test, duplication, time_delay, bridge_idx)
164
+ return cls(packet_data)
165
+
166
+ class UplinkRunData:
167
+ def __init__(self, data) -> None:
168
+ self.test = data['test']
169
+ self.duplication = data['duplication']
170
+ self.time_delay = data['time_delay']
171
+ self.bridge_idx = data['bridge_idx']
172
+ self.expected_mqtt = eval(data['expected_mqtt'])
173
+ self.data = data[ADVA_PAYLOAD]
174
+ self.si = data['si']
175
+ self.bridge_id = data['bridge_id']
176
+
177
+ @classmethod
178
+ def get_data(cls, test, duplication, time_delay, bridge_idx):
179
+ packet_data = GeneratedPacketTable().get_data(test, duplication, time_delay, bridge_idx)
180
+ return cls(packet_data)
181
+
182
+ class UnifiedRunData:
183
+ def __init__(self) -> None:
184
+ self.data = GeneratedPacketTable().get_unified_data()
185
+
186
+ class StressRunData:
187
+ def __init__(self) -> None:
188
+ self.data = GeneratedPacketTable().get_stress_data()
189
+
190
+ class SensorRunData:
191
+ def __init__(self) -> None:
192
+ self.data = GeneratedPacketTable().get_sensor_data()
193
+
194
+ class MgmtRunData:
195
+ def __init__(self) -> None:
196
+ self.data = GeneratedPacketTable().get_mgmt_data()
197
+
198
+ class PacketTableHelper():
199
+ def __init__(self):
200
+ self.table = GeneratedPacketTable().get_df()
201
+
202
+ def set_field(self, data_payload, field, value):
203
+ self.table.loc[self.table[ADVA_PAYLOAD].str.contains(data_payload) == True, field] = value
204
+
205
+ def get_field(self, data_payload, field):
206
+ return self.table[self.table[ADVA_PAYLOAD].str.contains(data_payload) == True][field]
207
+
208
+ if __name__ == "__main__":
209
+ GeneratedPacketTable()._generate_packet_table()