wiliot-certificate 4.5.0a1__py3-none-any.whl → 4.5.0a3__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.
- certificate/cert_common.py +14 -15
- certificate/cert_config.py +3 -3
- certificate/cert_defines.py +1 -0
- certificate/cert_gw_sim.py +3 -0
- certificate/cert_results.py +8 -0
- certificate/cert_utils.py +3 -0
- certificate/certificate_eth_test_list.txt +5 -3
- certificate/certificate_sanity_test_list.txt +3 -2
- certificate/certificate_test_list.txt +4 -3
- certificate/tests/cloud_connectivity/acl_ext_adv_test/acl_ext_adv_test.json +1 -1
- certificate/tests/cloud_connectivity/acl_test/acl_test.json +1 -1
- certificate/tests/cloud_connectivity/channel_scan_behaviour_test/channel_scan_behaviour_test.json +1 -1
- certificate/tests/cloud_connectivity/deduplication_test/deduplication_test.json +14 -0
- certificate/tests/cloud_connectivity/deduplication_test/deduplication_test.py +85 -0
- certificate/tests/cloud_connectivity/downlink_test/downlink_test.py +1 -4
- certificate/tests/cloud_connectivity/ext_adv_stress_test/ext_adv_stress_test.json +1 -1
- certificate/tests/cloud_connectivity/ext_adv_stress_test/ext_adv_stress_test.py +10 -9
- certificate/tests/cloud_connectivity/stress_test/stress_test.json +1 -1
- certificate/tests/cloud_connectivity/stress_test/stress_test.py +10 -10
- certificate/tests/cloud_connectivity/uplink_test/uplink_test.py +1 -0
- certificate/tests/datapath/event_ble5_test/event_ble5_test.py +6 -4
- certificate/tests/datapath/event_test/event_test.py +4 -3
- certificate/tests/datapath/num_of_tags_test/num_of_tags_test.json +1 -1
- certificate/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.py +4 -4
- certificate/tests/datapath/pkt_filter_ble5_chl21_test/pkt_filter_ble5_chl21_test.py +5 -5
- certificate/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.py +5 -5
- certificate/tests/datapath/pkt_filter_brg2gw_ext_adv_test/pkt_filter_brg2gw_ext_adv_test.py +10 -8
- certificate/tests/datapath/rssi_threshold_test/rssi_threshold_test.json +1 -1
- certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.py +1 -2
- certificate/tests/energy2400/signal_indicator_ext_adv_test/signal_indicator_ext_adv_test.json +8 -9
- certificate/tests/energy2400/signal_indicator_ext_adv_test/signal_indicator_ext_adv_test.py +110 -270
- certificate/tests/sensors/ext_sensor_test/ext_sensor_test.py +4 -9
- common/api_if/api_validation.py +2 -2
- common/web/templates/generator.html +141 -79
- common/web/web_utils.py +78 -56
- gui_certificate/server.py +111 -19
- gui_certificate/templates/cert_run.html +43 -6
- {wiliot_certificate-4.5.0a1.dist-info → wiliot_certificate-4.5.0a3.dist-info}/METADATA +35 -36
- {wiliot_certificate-4.5.0a1.dist-info → wiliot_certificate-4.5.0a3.dist-info}/RECORD +43 -41
- {wiliot_certificate-4.5.0a1.dist-info → wiliot_certificate-4.5.0a3.dist-info}/WHEEL +0 -0
- {wiliot_certificate-4.5.0a1.dist-info → wiliot_certificate-4.5.0a3.dist-info}/entry_points.txt +0 -0
- {wiliot_certificate-4.5.0a1.dist-info → wiliot_certificate-4.5.0a3.dist-info}/licenses/LICENSE +0 -0
- {wiliot_certificate-4.5.0a1.dist-info → wiliot_certificate-4.5.0a3.dist-info}/top_level.txt +0 -0
gui_certificate/server.py
CHANGED
|
@@ -70,9 +70,32 @@ def get_mandatory_modules_for_flavor(flavor):
|
|
|
70
70
|
return [MODULE_CLOUD_CONNECTIVITY, MODULE_EDGE_MGMT]
|
|
71
71
|
return []
|
|
72
72
|
|
|
73
|
+
def get_mandatory_modules_by_schema(schema_data, flavor):
|
|
74
|
+
"""Get modules that are mandatory by schema (modules declared in schema)."""
|
|
75
|
+
if not schema_data or "modules" not in schema_data:
|
|
76
|
+
return []
|
|
77
|
+
|
|
78
|
+
# Only apply to bridge flavors (bridge_only and combo)
|
|
79
|
+
if flavor not in (FLAVOR_BRIDGE_ONLY, FLAVOR_COMBO):
|
|
80
|
+
return []
|
|
81
|
+
|
|
82
|
+
schema_modules = schema_data.get("modules", {})
|
|
83
|
+
if not isinstance(schema_modules, dict):
|
|
84
|
+
return []
|
|
85
|
+
|
|
86
|
+
# Map schema module names to test module names
|
|
87
|
+
mandatory_by_schema = []
|
|
88
|
+
for schema_mod_name in schema_modules.keys():
|
|
89
|
+
# Map schema module name to test module name
|
|
90
|
+
test_mod_name = test_module_and_schema_module_to_other(schema_mod_name)
|
|
91
|
+
if test_mod_name not in mandatory_by_schema:
|
|
92
|
+
mandatory_by_schema.append(test_mod_name)
|
|
93
|
+
|
|
94
|
+
return mandatory_by_schema
|
|
95
|
+
|
|
73
96
|
# TODO: This is a temporary mapping to map test module names to schema module names - remove this
|
|
74
|
-
def
|
|
75
|
-
"""Map test module names
|
|
97
|
+
def test_module_and_schema_module_to_other(module_name):
|
|
98
|
+
"""Map test module names and schema module names to one another."""
|
|
76
99
|
mapping = {
|
|
77
100
|
"calibration": "calibration",
|
|
78
101
|
"datapath": "datapath",
|
|
@@ -82,7 +105,12 @@ def test_module_to_schema_module(test_module_name):
|
|
|
82
105
|
"sensors": "externalSensor", # different name
|
|
83
106
|
"custom": "custom"
|
|
84
107
|
}
|
|
85
|
-
|
|
108
|
+
for k, v in mapping.items():
|
|
109
|
+
if module_name == k:
|
|
110
|
+
return v
|
|
111
|
+
if module_name == v:
|
|
112
|
+
return k
|
|
113
|
+
return module_name # Return as-is if not in mapping
|
|
86
114
|
|
|
87
115
|
def filter_modules_by_flavor(tests_schema, flavor, schema_data=None):
|
|
88
116
|
"""Filter modules and tests based on selected flavor."""
|
|
@@ -115,12 +143,17 @@ def filter_modules_by_flavor(tests_schema, flavor, schema_data=None):
|
|
|
115
143
|
# Include all tests for combo
|
|
116
144
|
filtered_tests.append(test)
|
|
117
145
|
|
|
118
|
-
#
|
|
146
|
+
# Get modules mandatory by schema
|
|
147
|
+
mandatory_by_schema = get_mandatory_modules_by_schema(schema_data, flavor) if schema_data else []
|
|
148
|
+
is_mandatory_by_schema = mod_name in mandatory_by_schema
|
|
149
|
+
|
|
150
|
+
# Only include module if it has tests or is mandatory (by flavor or schema)
|
|
119
151
|
# For mandatory modules, include even if no tests match (they'll be shown but empty)
|
|
120
|
-
if filtered_tests or mod_name in mandatory_modules:
|
|
152
|
+
if filtered_tests or mod_name in mandatory_modules or is_mandatory_by_schema:
|
|
121
153
|
mod_copy = mod.copy()
|
|
122
154
|
mod_copy["tests"] = filtered_tests
|
|
123
155
|
mod_copy["is_mandatory"] = mod_name in mandatory_modules
|
|
156
|
+
mod_copy["is_mandatory_by_schema"] = is_mandatory_by_schema
|
|
124
157
|
filtered_modules.append(mod_copy)
|
|
125
158
|
|
|
126
159
|
# Sort modules: cloud_connectivity first, then edge_mgmt, then by schema order
|
|
@@ -136,7 +169,7 @@ def filter_modules_by_flavor(tests_schema, flavor, schema_data=None):
|
|
|
136
169
|
if schema_module_order:
|
|
137
170
|
try:
|
|
138
171
|
# Map test module name to schema module name
|
|
139
|
-
schema_mod_name =
|
|
172
|
+
schema_mod_name = test_module_and_schema_module_to_other(mod_name)
|
|
140
173
|
idx = schema_module_order.index(schema_mod_name)
|
|
141
174
|
return (2, idx)
|
|
142
175
|
except ValueError:
|
|
@@ -285,30 +318,37 @@ def verify_schema_matches_selection(schema_data, flavor, selected_modules, selec
|
|
|
285
318
|
bridge_modules_to_check = [m for m in selected_modules if m not in (MODULE_CLOUD_CONNECTIVITY, MODULE_EDGE_MGMT)]
|
|
286
319
|
for test_mod_name in bridge_modules_to_check:
|
|
287
320
|
# Map test module name to schema module name
|
|
288
|
-
schema_mod_name =
|
|
321
|
+
schema_mod_name = test_module_and_schema_module_to_other(test_mod_name)
|
|
289
322
|
if schema_mod_name not in schema_module_names:
|
|
290
323
|
warnings.append(f"Module '{test_mod_name}' may not be supported according to the uploaded schema")
|
|
291
324
|
|
|
292
325
|
return len(errors) == 0, errors, warnings
|
|
293
326
|
|
|
294
|
-
def check_certification_status(flavor, selected_modules, selected_tests, tests_schema):
|
|
327
|
+
def check_certification_status(flavor, selected_modules, selected_tests, tests_schema, schema_data=None):
|
|
295
328
|
"""Check if the selection qualifies for certification or is test-only."""
|
|
296
329
|
mandatory_modules = get_mandatory_modules_for_flavor(flavor)
|
|
330
|
+
mandatory_by_schema = get_mandatory_modules_by_schema(schema_data, flavor) if schema_data else []
|
|
297
331
|
all_mandatory_tests = []
|
|
298
332
|
|
|
299
|
-
# Get
|
|
333
|
+
# Get selected module names (handle both dict and string formats)
|
|
334
|
+
selected_module_names = [m.get("name") if isinstance(m, dict) else m for m in selected_modules]
|
|
335
|
+
|
|
336
|
+
# Get all mandatory tests from ALL selected modules (not just mandatory modules)
|
|
337
|
+
# When a module is selected, its mandatory tests become mandatory
|
|
300
338
|
for mod in tests_schema.get("modules", []):
|
|
301
339
|
mod_name = mod.get("name", "")
|
|
302
|
-
if mod_name in
|
|
340
|
+
if mod_name in selected_module_names:
|
|
303
341
|
for test in mod.get("tests", []):
|
|
304
342
|
if test.get("meta", {}).get("mandatory", 0) == 1:
|
|
305
343
|
all_mandatory_tests.append(test.get("id"))
|
|
306
344
|
|
|
307
345
|
# Check if all mandatory modules are selected
|
|
308
|
-
selected_module_names = [m.get("name") if isinstance(m, dict) else m for m in selected_modules]
|
|
309
346
|
missing_modules = [m for m in mandatory_modules if m not in selected_module_names]
|
|
310
347
|
|
|
311
|
-
# Check if all mandatory
|
|
348
|
+
# Check if all schema-mandatory modules are selected
|
|
349
|
+
missing_modules_by_schema = [m for m in mandatory_by_schema if m not in selected_module_names]
|
|
350
|
+
|
|
351
|
+
# Check if all mandatory tests (from selected modules) are selected
|
|
312
352
|
missing_tests = [t for t in all_mandatory_tests if t not in selected_tests]
|
|
313
353
|
|
|
314
354
|
# Check for "at least one additional module" requirement for Bridge Only and Combo
|
|
@@ -319,9 +359,10 @@ def check_certification_status(flavor, selected_modules, selected_tests, tests_s
|
|
|
319
359
|
if len(additional_modules) == 0:
|
|
320
360
|
missing_additional_module = True
|
|
321
361
|
|
|
322
|
-
is_certified = len(missing_modules) == 0 and len(
|
|
362
|
+
is_certified = (len(missing_modules) == 0 and len(missing_modules_by_schema) == 0 and
|
|
363
|
+
len(missing_tests) == 0 and not missing_additional_module)
|
|
323
364
|
|
|
324
|
-
return is_certified, missing_modules, missing_tests, missing_additional_module
|
|
365
|
+
return is_certified, missing_modules, missing_tests, missing_additional_module, missing_modules_by_schema
|
|
325
366
|
|
|
326
367
|
def _prepare_form_data_for_template(session, cert_schema):
|
|
327
368
|
"""Prepare form_data for template, ensuring custom_broker_path is included if available."""
|
|
@@ -451,6 +492,7 @@ def step(step_num):
|
|
|
451
492
|
session['selected_modules'] = []
|
|
452
493
|
session['selected_tests'] = []
|
|
453
494
|
session['form_data'] = {}
|
|
495
|
+
session['schema_mandatory_initialized'] = False
|
|
454
496
|
|
|
455
497
|
title = "Run Certificate"
|
|
456
498
|
tests_schema = web_utils.scan_tests_dir(CERT_TESTS_ROOT)
|
|
@@ -505,7 +547,22 @@ def step(step_num):
|
|
|
505
547
|
flavor = session.get('flavor')
|
|
506
548
|
if 'selected_modules' not in session or not session.get('selected_modules'):
|
|
507
549
|
mandatory_modules = get_mandatory_modules_for_flavor(flavor)
|
|
508
|
-
|
|
550
|
+
# Add schema-mandatory modules
|
|
551
|
+
schema_data = result # result is the validated schema data
|
|
552
|
+
mandatory_by_schema = get_mandatory_modules_by_schema(schema_data, flavor)
|
|
553
|
+
all_mandatory = list(set(mandatory_modules + mandatory_by_schema))
|
|
554
|
+
session['selected_modules'] = all_mandatory
|
|
555
|
+
# Mark schema-mandatory modules as initialized
|
|
556
|
+
session['schema_mandatory_initialized'] = True
|
|
557
|
+
else:
|
|
558
|
+
# If modules already exist, add schema-mandatory modules and mark as initialized
|
|
559
|
+
schema_data = result
|
|
560
|
+
mandatory_by_schema = get_mandatory_modules_by_schema(schema_data, flavor)
|
|
561
|
+
current_modules = session.get('selected_modules', [])
|
|
562
|
+
updated_modules = list(set(current_modules + mandatory_by_schema))
|
|
563
|
+
if len(updated_modules) > len(current_modules):
|
|
564
|
+
session['selected_modules'] = updated_modules
|
|
565
|
+
session['schema_mandatory_initialized'] = True
|
|
509
566
|
# For GW only, skip step 3 (modules)
|
|
510
567
|
if session.get('flavor') == FLAVOR_GW_ONLY:
|
|
511
568
|
session['current_step'] = 4
|
|
@@ -681,9 +738,30 @@ def step(step_num):
|
|
|
681
738
|
# This ensures mandatory items are only pre-checked at the beginning
|
|
682
739
|
if flavor and not selected_modules:
|
|
683
740
|
mandatory_modules = get_mandatory_modules_for_flavor(flavor)
|
|
684
|
-
|
|
741
|
+
# Add schema-mandatory modules if schema is available
|
|
742
|
+
schema_data = load_schema_data(schema_path) if schema_path else None
|
|
743
|
+
mandatory_by_schema = get_mandatory_modules_by_schema(schema_data, flavor) if schema_data else []
|
|
744
|
+
all_mandatory = list(set(mandatory_modules + mandatory_by_schema))
|
|
745
|
+
selected_modules = all_mandatory
|
|
685
746
|
session['selected_modules'] = selected_modules
|
|
686
747
|
|
|
748
|
+
# Ensure schema-mandatory modules are added when first reaching step 3 (only if not already initialized)
|
|
749
|
+
# Use a session flag to track if schema-mandatory modules have been initialized
|
|
750
|
+
if step_num == 3 and flavor and schema_path:
|
|
751
|
+
schema_mandatory_initialized = session.get('schema_mandatory_initialized', False)
|
|
752
|
+
if not schema_mandatory_initialized:
|
|
753
|
+
schema_data = load_schema_data(schema_path) if schema_path else None
|
|
754
|
+
if schema_data:
|
|
755
|
+
mandatory_by_schema = get_mandatory_modules_by_schema(schema_data, flavor)
|
|
756
|
+
# Add schema-mandatory modules that aren't already selected
|
|
757
|
+
current_modules = session.get('selected_modules', [])
|
|
758
|
+
updated_modules = list(set(current_modules + mandatory_by_schema))
|
|
759
|
+
if len(updated_modules) > len(current_modules):
|
|
760
|
+
selected_modules = updated_modules
|
|
761
|
+
session['selected_modules'] = selected_modules
|
|
762
|
+
# Mark as initialized so we don't re-add them when going back
|
|
763
|
+
session['schema_mandatory_initialized'] = True
|
|
764
|
+
|
|
687
765
|
# Initialize mandatory tests only if not already in session and we have selected modules
|
|
688
766
|
# Only initialize when first reaching step 4 (not on every GET request)
|
|
689
767
|
if flavor and selected_modules and not selected_tests and step_num == 4:
|
|
@@ -720,11 +798,13 @@ def step(step_num):
|
|
|
720
798
|
missing_tests = []
|
|
721
799
|
missing_tests_details = [] # List of dicts with test id and label
|
|
722
800
|
missing_additional_module = False
|
|
801
|
+
missing_modules_by_schema = []
|
|
723
802
|
if step_num >= 4 and flavor and selected_modules and selected_tests:
|
|
724
803
|
# Convert selected_modules to module dicts for check_certification_status
|
|
725
804
|
module_dicts = [m for m in filtered_modules if m.get('name') in selected_modules]
|
|
726
|
-
|
|
727
|
-
|
|
805
|
+
schema_data = load_schema_data(schema_path) if schema_path else None
|
|
806
|
+
is_certified, missing_modules, missing_tests, missing_additional_module, missing_modules_by_schema = check_certification_status(
|
|
807
|
+
flavor, module_dicts, selected_tests, tests_schema, schema_data
|
|
728
808
|
)
|
|
729
809
|
|
|
730
810
|
# Get test details (labels) for missing tests
|
|
@@ -751,6 +831,11 @@ def step(step_num):
|
|
|
751
831
|
)
|
|
752
832
|
schema_errors = errors
|
|
753
833
|
schema_warnings = warnings
|
|
834
|
+
# Get missing schema-mandatory modules for display (recalculate if not already set)
|
|
835
|
+
if not missing_modules_by_schema and step_num >= 4 and flavor and selected_modules:
|
|
836
|
+
_, _, _, _, missing_modules_by_schema = check_certification_status(
|
|
837
|
+
flavor, module_dicts, selected_tests, tests_schema, schema_data
|
|
838
|
+
)
|
|
754
839
|
|
|
755
840
|
# Get CLI schemas for form fields - use certificate_cli for all flavors
|
|
756
841
|
cert_cli = CertificateCLI()
|
|
@@ -770,6 +855,8 @@ def step(step_num):
|
|
|
770
855
|
# Prepare data for JavaScript validation
|
|
771
856
|
# Always initialize these to avoid Undefined errors in template
|
|
772
857
|
mandatory_modules_for_js = get_mandatory_modules_for_flavor(flavor) if flavor else []
|
|
858
|
+
schema_data_for_js = load_schema_data(schema_path) if schema_path else None
|
|
859
|
+
mandatory_modules_by_schema_for_js = get_mandatory_modules_by_schema(schema_data_for_js, flavor) if (schema_data_for_js and flavor) else []
|
|
773
860
|
mandatory_tests_for_js = []
|
|
774
861
|
|
|
775
862
|
if step_num in [3, 4] and flavor:
|
|
@@ -839,7 +926,9 @@ def step(step_num):
|
|
|
839
926
|
missing_additional_module=missing_additional_module,
|
|
840
927
|
schema_errors=schema_errors,
|
|
841
928
|
schema_warnings=schema_warnings,
|
|
929
|
+
missing_modules_by_schema=missing_modules_by_schema,
|
|
842
930
|
mandatory_modules_for_js=mandatory_modules_for_js,
|
|
931
|
+
mandatory_modules_by_schema_for_js=mandatory_modules_by_schema_for_js,
|
|
843
932
|
mandatory_tests_for_js=mandatory_tests_for_js,
|
|
844
933
|
error=error,
|
|
845
934
|
warning=warning,
|
|
@@ -874,7 +963,8 @@ def execute_certificate():
|
|
|
874
963
|
tests_schema = web_utils.scan_tests_dir(CERT_TESTS_ROOT)
|
|
875
964
|
filtered_modules = filter_modules_by_flavor(tests_schema, flavor)
|
|
876
965
|
module_dicts = [m for m in filtered_modules if m.get('name') in session.get('selected_modules', [])]
|
|
877
|
-
|
|
966
|
+
schema_data = load_schema_data(schema_path) if schema_path else None
|
|
967
|
+
is_certified, _, _, _, _ = check_certification_status(flavor, module_dicts, selected_tests, tests_schema, schema_data)
|
|
878
968
|
|
|
879
969
|
full_cmd = []
|
|
880
970
|
|
|
@@ -1047,6 +1137,8 @@ def import_config():
|
|
|
1047
1137
|
def clear_session():
|
|
1048
1138
|
"""Clear session and start fresh."""
|
|
1049
1139
|
session.clear()
|
|
1140
|
+
# Initialize session flags
|
|
1141
|
+
session['schema_mandatory_initialized'] = False
|
|
1050
1142
|
return redirect(url_for('step', step_num=1))
|
|
1051
1143
|
|
|
1052
1144
|
@app.route("/parser")
|
|
@@ -326,12 +326,15 @@
|
|
|
326
326
|
name="modules[]"
|
|
327
327
|
id="module_{{ mod.name }}"
|
|
328
328
|
value="{{ mod.name }}"
|
|
329
|
-
{% if is_selected
|
|
329
|
+
{% if is_selected or (is_mandatory and not has_selections) or (mod.is_mandatory_by_schema and not has_selections) %}checked{% endif %}>
|
|
330
330
|
<label class="form-check-label" for="module_{{ mod.name }}" style="font-weight: bold; font-size: 1.1rem;">
|
|
331
331
|
{{ mod.name }}
|
|
332
332
|
{% if is_mandatory %}
|
|
333
333
|
<span class="mandatory-badge">Mandatory</span>
|
|
334
334
|
{% endif %}
|
|
335
|
+
{% if mod.is_mandatory_by_schema %}
|
|
336
|
+
<span class="mandatory-badge" style="background: #0066cc;">Mandatory by Schema</span>
|
|
337
|
+
{% endif %}
|
|
335
338
|
{{ kb_link(mod_doc) }}
|
|
336
339
|
</label>
|
|
337
340
|
<p class="text-muted mt-1 mb-0">
|
|
@@ -644,12 +647,13 @@
|
|
|
644
647
|
{% endif %}
|
|
645
648
|
{% if missing_tests_details %}
|
|
646
649
|
<div class="alert alert-warning">
|
|
647
|
-
<strong>Missing Mandatory Tests:</strong>
|
|
650
|
+
<strong>Missing Mandatory Tests from Selected Modules:</strong>
|
|
648
651
|
<ul class="mb-0">
|
|
649
652
|
{% for test in missing_tests_details %}
|
|
650
653
|
<li>{{ test.label }} <small class="text-muted">({{ test.module }})</small></li>
|
|
651
654
|
{% endfor %}
|
|
652
655
|
</ul>
|
|
656
|
+
<small class="d-block mt-2">When a module is selected, its mandatory tests must also be selected.</small>
|
|
653
657
|
</div>
|
|
654
658
|
{% endif %}
|
|
655
659
|
{% endif %}
|
|
@@ -662,7 +666,10 @@
|
|
|
662
666
|
<h5 class="mb-0">Schema Verification</h5>
|
|
663
667
|
</div>
|
|
664
668
|
<div class="card-body">
|
|
665
|
-
{% if schema_errors or schema_warnings %}
|
|
669
|
+
{% if schema_errors or schema_warnings or missing_modules_by_schema %}
|
|
670
|
+
<p><strong>Schema Status:</strong>
|
|
671
|
+
<span class="badge bg-warning text-dark">SCHEMA DOES NOT MATCH RUN SETTINGS</span>
|
|
672
|
+
</p>
|
|
666
673
|
{% if schema_errors %}
|
|
667
674
|
<div class="alert alert-danger">
|
|
668
675
|
<strong>Errors:</strong>
|
|
@@ -683,12 +690,24 @@
|
|
|
683
690
|
</ul>
|
|
684
691
|
</div>
|
|
685
692
|
{% endif %}
|
|
693
|
+
{% if missing_modules_by_schema %}
|
|
694
|
+
<div class="alert alert-warning mt-3">
|
|
695
|
+
<strong>Missing Modules Mandatory by Schema:</strong>
|
|
696
|
+
<ul class="mb-0">
|
|
697
|
+
{% for mod in missing_modules_by_schema %}
|
|
698
|
+
<li>{{ mod }}</li>
|
|
699
|
+
{% endfor %}
|
|
700
|
+
</ul>
|
|
701
|
+
<small class="d-block mt-2">These modules are declared in your validation schema but are not selected. They should be included for proper certification.</small>
|
|
702
|
+
</div>
|
|
703
|
+
{% endif %}
|
|
686
704
|
{% else %}
|
|
687
705
|
<p><strong>Schema Status:</strong>
|
|
688
|
-
<span class="badge bg-success">SCHEMA MATCHES
|
|
706
|
+
<span class="badge bg-success">SCHEMA MATCHES RUN SETTINGS</span>
|
|
689
707
|
<small class="text-muted d-block mt-1">The uploaded schema matches the selected flavor, modules, and tests</small>
|
|
690
708
|
</p>
|
|
691
709
|
{% endif %}
|
|
710
|
+
|
|
692
711
|
</div>
|
|
693
712
|
</div>
|
|
694
713
|
|
|
@@ -843,6 +862,7 @@
|
|
|
843
862
|
const brgCertSchema = {{ cert_schema|tojson|safe }};
|
|
844
863
|
|
|
845
864
|
// Step 3: Module selection validation
|
|
865
|
+
const mandatoryModulesBySchema = {{ mandatory_modules_by_schema_for_js|tojson|safe }};
|
|
846
866
|
function checkStep3Validation() {
|
|
847
867
|
if (stepNum !== 3) return;
|
|
848
868
|
|
|
@@ -861,6 +881,14 @@
|
|
|
861
881
|
warnings.push('Missing mandatory modules: ' + missingMandatory.join(', '));
|
|
862
882
|
}
|
|
863
883
|
|
|
884
|
+
// Check if schema-mandatory modules are deselected
|
|
885
|
+
if (mandatoryModulesBySchema && mandatoryModulesBySchema.length > 0) {
|
|
886
|
+
const missingBySchema = mandatoryModulesBySchema.filter(m => !selectedModules.includes(m));
|
|
887
|
+
if (missingBySchema.length > 0) {
|
|
888
|
+
warnings.push('Missing modules mandatory by schema: ' + missingBySchema.join(', '));
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
864
892
|
// Check Bridge/Combo requirement for at least one additional module
|
|
865
893
|
if (selectedFlavor === 'bridge_only' || selectedFlavor === 'combo') {
|
|
866
894
|
const nonMandatorySelected = selectedModules.filter(m => !mandatoryModules.includes(m));
|
|
@@ -903,12 +931,21 @@
|
|
|
903
931
|
warnings.push('Missing mandatory modules: ' + missingMandatoryModules.join(', '));
|
|
904
932
|
}
|
|
905
933
|
|
|
906
|
-
// Check if mandatory
|
|
934
|
+
// Check if schema-mandatory modules are deselected
|
|
935
|
+
if (mandatoryModulesBySchema && mandatoryModulesBySchema.length > 0) {
|
|
936
|
+
const missingBySchema = mandatoryModulesBySchema.filter(m => !selectedModules.includes(m));
|
|
937
|
+
if (missingBySchema.length > 0) {
|
|
938
|
+
warnings.push('Missing modules mandatory by schema: ' + missingBySchema.join(', '));
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// Check if mandatory tests from selected modules are deselected
|
|
943
|
+
// When a module is selected, its mandatory tests become mandatory
|
|
907
944
|
const missingMandatoryTests = mandatoryTests
|
|
908
945
|
.filter(t => selectedModules.includes(t.module) && !selectedTests.includes(t.id))
|
|
909
946
|
.map(t => t.label + ' (' + t.module + ')');
|
|
910
947
|
if (missingMandatoryTests.length > 0) {
|
|
911
|
-
warnings.push('Missing mandatory tests: ' + missingMandatoryTests.length + ' test(s)');
|
|
948
|
+
warnings.push('Missing mandatory tests from selected modules: ' + missingMandatoryTests.length + ' test(s)');
|
|
912
949
|
}
|
|
913
950
|
|
|
914
951
|
if (warnings.length > 0) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wiliot_certificate
|
|
3
|
-
Version: 4.5.
|
|
3
|
+
Version: 4.5.0a3
|
|
4
4
|
Summary: A library for certifying Wiliot-compliant boards
|
|
5
5
|
Author-email: Wiliot <support@wiliot.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -30,35 +30,60 @@ Requires-Dist: reportlab>=4.3.1
|
|
|
30
30
|
Requires-Dist: google-api-python-client>=2.162.0
|
|
31
31
|
Dynamic: license-file
|
|
32
32
|
|
|
33
|
-
# wiliot-certificate
|
|
33
|
+
# wiliot-certificate
|
|
34
34
|
|
|
35
35
|
<!-- Description -->
|
|
36
36
|
wiliot-certificate is a Python library that provides tools for testing and certifying boards for compatibility with Wiliot’s ecosystem.
|
|
37
|
-
This python package includes the following
|
|
37
|
+
This python package includes the following tools:
|
|
38
38
|
- Certification Wizard (`wlt-cert`)
|
|
39
39
|
- Certificate CLI (`wlt-cert-cli`)
|
|
40
40
|
- Tester Upgrade (`wlt-cert-tester-upgrade`)
|
|
41
41
|
- Registration Certificate (`wlt-cert-reg`)
|
|
42
42
|
|
|
43
|
-
#
|
|
44
|
-
wiliot-certificate versions 4.5.
|
|
43
|
+
# Versioning:
|
|
44
|
+
wiliot-certificate versions 4.5.x are compatible with firmware version >=4.5.0 (API VERSION: 13)
|
|
45
45
|
|
|
46
46
|
## Installing wiliot-certificate
|
|
47
|
-
Install wiliot-certificate:
|
|
48
47
|
````commandline
|
|
49
48
|
pip install wiliot-certificate
|
|
50
49
|
````
|
|
51
50
|
|
|
52
51
|
## Using wiliot-certificate
|
|
53
52
|
### Certification
|
|
54
|
-
In terminal, run:
|
|
55
53
|
````commandline
|
|
56
54
|
wlt-cert
|
|
57
55
|
````
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
This tool is the default to test and certify your device.
|
|
57
|
+
It runs a setup wizard that walks you through the initialization steps before running the tests.
|
|
58
|
+
You'll need a [validation schema](https://community.wiliot.com/customers/s/article/Validation-Schema), tester device and custom broker json file ([more info here](https://community.wiliot.com/customers/s/article/Wiliot-Gateway-Certification)).
|
|
59
|
+
Once set up it opens a terminal and tests your device.
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
### Certificate CLI
|
|
64
|
+
````commandline
|
|
65
|
+
wlt-cert-cli -h
|
|
66
|
+
````
|
|
67
|
+
CLI version of the certificate. Use -h for details on the different arguments.
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
### Tester Upgrade
|
|
71
|
+
````commandline
|
|
72
|
+
wlt-cert-tester-upgrade
|
|
73
|
+
````
|
|
74
|
+
Upgrades the firmware of the tester device to the version required for certification.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### Registration Certificate
|
|
78
|
+
````commandline
|
|
79
|
+
wlt-cert-reg
|
|
80
|
+
````
|
|
81
|
+
Certify the gateway registration process to Wiliot platform.
|
|
82
|
+
The gateway must use Wiliot production MQTT broker, and mustn't be registered to any account on Wiliot platform.
|
|
83
|
+
Use -h for details on the arguments. [More info here](https://community.wiliot.com/customers/s/article/Wiliot-Gateway-Certification)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## The following capabilities are not tested in this version
|
|
62
87
|
##### Cloud Connectivity & Misc
|
|
63
88
|
- Board type registered within the Board Type Management system
|
|
64
89
|
- Bridge OTA progress reporting
|
|
@@ -82,29 +107,3 @@ wlt-cert
|
|
|
82
107
|
##### Calibration
|
|
83
108
|
- Functionality of output power and interval calibration
|
|
84
109
|
- Functionality of calibration transmission patterns for the configuration STANDARD & EU & DISABLE
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
### Certificate CLI
|
|
88
|
-
In terminal, run:
|
|
89
|
-
````commandline
|
|
90
|
-
wlt-cert-cli -h
|
|
91
|
-
````
|
|
92
|
-
CLI version of the certificate. Use -h for details on the different arguments.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
### Tester Upgrade
|
|
96
|
-
In terminal, run:
|
|
97
|
-
````commandline
|
|
98
|
-
wlt-cert-tester-upgrade
|
|
99
|
-
````
|
|
100
|
-
Upgrades the firmware of the tester device to the version required for certification.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
### Registration Certificate
|
|
104
|
-
In terminal, run:
|
|
105
|
-
````commandline
|
|
106
|
-
wlt-cert-reg
|
|
107
|
-
````
|
|
108
|
-
Certify the gateway registration process to Wiliot platform.
|
|
109
|
-
The gateway must use Wiliot production MQTT broker, and mustn't be registered to any account on Wiliot platform.
|
|
110
|
-
Use -h for details on the arguments. <!-- More info can be found in TODO link-->
|