From 1a83fe8e497adde8e7a12e797fd32783d8e88696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Ean=20G=C3=BCne=C5=9F?= <180301198+sgunes-wirepas@users.noreply.github.com> Date: Thu, 14 Aug 2025 16:22:18 +0300 Subject: [PATCH 1/5] Update backend-apis to get the key management parameters for sink --- backend-apis | 2 +- wirepas_mesh_messaging/gateway_feature.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backend-apis b/backend-apis index 85a6ffd..56c734f 160000 --- a/backend-apis +++ b/backend-apis @@ -1 +1 @@ -Subproject commit 85a6ffd5168f42ac18561e25cc2cf334cd8ded17 +Subproject commit 56c734f1804b27f04d64da3f001321fc7472754e diff --git a/wirepas_mesh_messaging/gateway_feature.py b/wirepas_mesh_messaging/gateway_feature.py index cf6100d..98e269e 100644 --- a/wirepas_mesh_messaging/gateway_feature.py +++ b/wirepas_mesh_messaging/gateway_feature.py @@ -19,4 +19,5 @@ class GatewayFeature(enum.Enum): GW_FEATURE_UNKNOWN = GatewayFeature_pb.UNKNOWN GW_FEATURE_SCRATCHPAD_CHUNK_V1 = GatewayFeature_pb.SCRATCHPAD_CHUNK_V1 GW_FEATURE_CONFIGURATION_DATA_V1 = GatewayFeature_pb.CONFIGURATION_DATA_V1 + GW_FEATURE_SINK_KEY_MANAGEMENT_V1 = GatewayFeature_pb.SINK_KEY_MANAGEMENT_V1 From f6d187f0cfad12709c3f39abd06b7e9b51105974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Ean=20G=C3=BCne=C5=9F?= <180301198+sgunes-wirepas@users.noreply.github.com> Date: Fri, 15 Aug 2025 11:17:55 +0300 Subject: [PATCH 2/5] Add unit test for SetConfigRequest with writeable fields --- tests/default_value.py | 16 ++++++++++++++++ tests/test_set_config.py | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/tests/default_value.py b/tests/default_value.py index 7c405cf..2805b3c 100644 --- a/tests/default_value.py +++ b/tests/default_value.py @@ -63,3 +63,19 @@ ("stored_scratchpad", SCRATCHPAD_INFO), ("configuration_data_content", TEST_CDC1) ]) + +NODE_CONFIG_FOR_SETTING = { + "sink_id": SINK_ID, + "node_role": 1, + "node_address": 1516, + "network_address": 879123, + "network_channel": 7, + "app_config_diag": 30, + "app_config_seq": 300, + "app_config_data": bytes.fromhex("90807060"), + "channel_map": 120, + "cipher_key": bytes.fromhex("102030"), + "authentication_key": bytes.fromhex("AABBCC"), + "started": True +} + diff --git a/tests/test_set_config.py b/tests/test_set_config.py index bb8d805..053be3e 100644 --- a/tests/test_set_config.py +++ b/tests/test_set_config.py @@ -43,3 +43,17 @@ def test_generate_parse_response_with_readonly_fields(): for k, v in request.__dict__.items(): assert v == request2.__dict__[k] + +def test_generate_parse_request_with_writeable_fields(): + request = wirepas_mesh_messaging.SetConfigRequest( + SINK_ID, NODE_CONFIG_FOR_SETTING, REQUEST_ID + ) + + request2 = wirepas_mesh_messaging.SetConfigRequest.from_payload( + request.payload + ) + + assert NODE_CONFIG_FOR_SETTING == request2.new_config + for k, v in request.__dict__.items(): + assert v == request2.__dict__[k] + From 39eddca63811ddb68b0763e5fb4ddb0b80fb0340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Ean=20G=C3=BCne=C5=9F?= <180301198+sgunes-wirepas@users.noreply.github.com> Date: Fri, 15 Aug 2025 11:36:05 +0300 Subject: [PATCH 3/5] Refactor config_helper: Add new functions for write only config fields(similar to read only fields) and move key parameters there. --- wirepas_mesh_messaging/config_helper.py | 26 +++++++++++++++---------- wirepas_mesh_messaging/set_config.py | 8 ++++---- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/wirepas_mesh_messaging/config_helper.py b/wirepas_mesh_messaging/config_helper.py index 2882f49..6ed07d4 100644 --- a/wirepas_mesh_messaging/config_helper.py +++ b/wirepas_mesh_messaging/config_helper.py @@ -243,33 +243,39 @@ def set_config_otap(message_obj, dic): set_scratchpad_target(message_obj.target_and_action, dic["target_and_action"]) -def parse_config_keys(message_obj, dic): +def parse_config_wo(message_obj, dic): """ - Parses network keys. + Parses the message_obj for write only (wo) fields and copies them into + dic. - The keys are only available on a SinkNewConfig message. + Write only fields are ones that are only available on a SinkNewConfig + message. Args: message_obj (proto): protocol buffer object - dic (dict): the dictionary where to copy the keys into + dic (dict): the dictionary where to copy the wo fields + """ parse_optional_field(message_obj.keys, "cipher", dic, "cipher_key") parse_optional_field(message_obj.keys, "authentication", dic, "authentication_key") -def set_config_keys(message_obj, dic): +def set_config_wo(message_obj, dic): """ - Sets network keys. + Sets the message_obj with the write only (wo) fields present in dic. - The keys are only available on a SinkNewConfig message. + Write only fields are ones that are only available on a SinkNewConfig + message. Args: message_obj (proto): protocol buffer object - dic (dict): the dictionary where to copy the keys from + dic (dict): the dictionary where to copy the wo fields from + """ - set_optional_field(message_obj, "cipher", dic, "cipher_key") - set_optional_field(message_obj, "authentication", dic, "authentication_key") + + set_optional_field(message_obj.keys, "cipher", dic, "cipher_key") + set_optional_field(message_obj.keys, "authentication", dic, "authentication_key") def parse_config_ro(message_obj, dic): diff --git a/wirepas_mesh_messaging/set_config.py b/wirepas_mesh_messaging/set_config.py index 7b650d7..a6deae3 100644 --- a/wirepas_mesh_messaging/set_config.py +++ b/wirepas_mesh_messaging/set_config.py @@ -14,13 +14,13 @@ from .config_helper import ( parse_config_rw, - parse_config_keys, set_config_rw, - set_config_keys, parse_config_ro, parse_config_otap, set_config_otap, set_config_ro, + set_config_wo, + parse_config_wo, ) @@ -71,7 +71,7 @@ def from_payload(cls, payload): new_config = {} new_config["sink_id"] = req.config.sink_id parse_config_rw(req.config, new_config) - parse_config_keys(req.config, new_config) + parse_config_wo(req.config, new_config) return cls(req.config.sink_id, new_config, d["req_id"], time_ms_epoch=d["time_ms_epoch"]) @@ -84,7 +84,7 @@ def payload(self): set_config.config.sink_id = self.sink_id set_config_rw(set_config.config, self.new_config) - set_config_keys(set_config.config.keys, self.new_config) + set_config_wo(set_config.config, self.new_config) return message.SerializeToString() From 10a0412b303ab476eb3078e2497a32c6644d48fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Ean=20G=C3=BCne=C5=9F?= <180301198+sgunes-wirepas@users.noreply.github.com> Date: Fri, 15 Aug 2025 15:14:52 +0300 Subject: [PATCH 4/5] Add support for network_keys and management_keys in SetConfigRequest Using a nested dictionary under new_config parameter doesn't follow the existing convention (such as the app_config and earlier key related entries), but it should make it easier to maintain the new_config dictionary in the long run if we have a structure which is more similar to the SinkNewConfig structure in protobuf. --- tests/default_value.py | 12 +++++++++++- wirepas_mesh_messaging/config_helper.py | 24 ++++++++++++++++++++++++ wirepas_mesh_messaging/set_config.py | 8 ++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/tests/default_value.py b/tests/default_value.py index 2805b3c..49cea2c 100644 --- a/tests/default_value.py +++ b/tests/default_value.py @@ -76,6 +76,16 @@ "channel_map": 120, "cipher_key": bytes.fromhex("102030"), "authentication_key": bytes.fromhex("AABBCC"), - "started": True + "started": True, + "network_keys": { + "cipher": bytes.fromhex("5000"), + "authentication": bytes.fromhex("6000"), + "sequence": 6767 + }, + "management_keys": { + "cipher": bytes.fromhex("10AA"), + "authentication": bytes.fromhex("20BB"), + "sequence": 520 + }, } diff --git a/wirepas_mesh_messaging/config_helper.py b/wirepas_mesh_messaging/config_helper.py index 6ed07d4..d6cde53 100644 --- a/wirepas_mesh_messaging/config_helper.py +++ b/wirepas_mesh_messaging/config_helper.py @@ -260,6 +260,20 @@ def parse_config_wo(message_obj, dic): parse_optional_field(message_obj.keys, "cipher", dic, "cipher_key") parse_optional_field(message_obj.keys, "authentication", dic, "authentication_key") + if message_obj.HasField("network_keys"): + dic["network_keys"] = { + "cipher": message_obj.network_keys.cipher, + "authentication": message_obj.network_keys.authentication, + "sequence": message_obj.network_keys.sequence + } + + if message_obj.HasField("management_keys"): + dic["management_keys"] = { + "cipher": message_obj.management_keys.cipher, + "authentication": message_obj.management_keys.authentication, + "sequence": message_obj.management_keys.sequence + } + def set_config_wo(message_obj, dic): """ @@ -277,6 +291,16 @@ def set_config_wo(message_obj, dic): set_optional_field(message_obj.keys, "cipher", dic, "cipher_key") set_optional_field(message_obj.keys, "authentication", dic, "authentication_key") + if "network_keys" in dic: + message_obj.network_keys.cipher = dic["network_keys"]["cipher"] + message_obj.network_keys.authentication = dic["network_keys"]["authentication"] + message_obj.network_keys.sequence = dic["network_keys"]["sequence"] + + if "management_keys" in dic: + message_obj.management_keys.cipher = dic["management_keys"]["cipher"] + message_obj.management_keys.authentication = dic["management_keys"]["authentication"] + message_obj.management_keys.sequence = dic["management_keys"]["sequence"] + def parse_config_ro(message_obj, dic): """ diff --git a/wirepas_mesh_messaging/set_config.py b/wirepas_mesh_messaging/set_config.py index a6deae3..efc5567 100644 --- a/wirepas_mesh_messaging/set_config.py +++ b/wirepas_mesh_messaging/set_config.py @@ -43,6 +43,14 @@ class SetConfigRequest(Request): cipher_key (bytearray) authentication_key (bytearray) started (bool) + network_keys (dict): with following required keys: + cipher (bytearray) + authentication (bytearray) + sequence (int) + management_keys (dict): with following required keys: + cipher (bytearray) + authentication (bytearray) + sequence (int) Note: app_config_data/app_config_seq/app_config_data must all be defined to change one of them only relevant keys for new config has to be defined From f55ccc16bd48b9c0c36ad4574f1d7402bd3044aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=9Ean=20G=C3=BCne=C5=9F?= <180301198+sgunes-wirepas@users.noreply.github.com> Date: Wed, 20 Aug 2025 17:04:34 +0300 Subject: [PATCH 5/5] Rename helper functions for write only config fields --- wirepas_mesh_messaging/config_helper.py | 4 ++-- wirepas_mesh_messaging/set_config.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wirepas_mesh_messaging/config_helper.py b/wirepas_mesh_messaging/config_helper.py index d6cde53..3f1e011 100644 --- a/wirepas_mesh_messaging/config_helper.py +++ b/wirepas_mesh_messaging/config_helper.py @@ -243,7 +243,7 @@ def set_config_otap(message_obj, dic): set_scratchpad_target(message_obj.target_and_action, dic["target_and_action"]) -def parse_config_wo(message_obj, dic): +def parse_config_wo_fields(message_obj, dic): """ Parses the message_obj for write only (wo) fields and copies them into dic. @@ -275,7 +275,7 @@ def parse_config_wo(message_obj, dic): } -def set_config_wo(message_obj, dic): +def set_config_wo_fields(message_obj, dic): """ Sets the message_obj with the write only (wo) fields present in dic. diff --git a/wirepas_mesh_messaging/set_config.py b/wirepas_mesh_messaging/set_config.py index efc5567..4a5fb81 100644 --- a/wirepas_mesh_messaging/set_config.py +++ b/wirepas_mesh_messaging/set_config.py @@ -19,8 +19,8 @@ parse_config_otap, set_config_otap, set_config_ro, - set_config_wo, - parse_config_wo, + set_config_wo_fields, + parse_config_wo_fields, ) @@ -79,7 +79,7 @@ def from_payload(cls, payload): new_config = {} new_config["sink_id"] = req.config.sink_id parse_config_rw(req.config, new_config) - parse_config_wo(req.config, new_config) + parse_config_wo_fields(req.config, new_config) return cls(req.config.sink_id, new_config, d["req_id"], time_ms_epoch=d["time_ms_epoch"]) @@ -92,7 +92,7 @@ def payload(self): set_config.config.sink_id = self.sink_id set_config_rw(set_config.config, self.new_config) - set_config_wo(set_config.config, self.new_config) + set_config_wo_fields(set_config.config, self.new_config) return message.SerializeToString()