From 6e4ef259d1b1dcd92bc37aef9b945b8e7e7e9e55 Mon Sep 17 00:00:00 2001 From: Kars de Jong Date: Mon, 17 Jun 2024 20:35:58 +0200 Subject: [PATCH 1/5] Add impersonation support to send_packet service --- .gitignore | 1 + custom_components/ramses_cc/schemas.py | 3 ++- custom_components/ramses_cc/services.yaml | 8 ++++++++ custom_components/ramses_cc/translations/en.json | 2 +- tests/tests_old/test_services.py | 15 +++++++++++++++ 5 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f40f208f..5a789c8 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ __snapshots__ !custom_components/ramses_cc !custom_components/ramses_cc/manifest.json +!custom_components/ramses_cc/services.yaml !.flake8 !.gitignore diff --git a/custom_components/ramses_cc/schemas.py b/custom_components/ramses_cc/schemas.py index 8e4389a..fb101b6 100644 --- a/custom_components/ramses_cc/schemas.py +++ b/custom_components/ramses_cc/schemas.py @@ -231,7 +231,8 @@ def schema_is_minimal(schema: _SchemaT) -> bool: SCH_SEND_PACKET = vol.Schema( { - vol.Required(ATTR_DEVICE_ID): cv.matches_regex(r"^[0-9]{2}:[0-9]{6}$"), + vol.Required(ATTR_DEVICE_ID): _SCH_DEVICE_ID, + Vol.Optional("from_id"): _SCH_DEVICE_ID, vol.Required("verb"): vol.In((" I", "I", "RQ", "RP", " W", "W")), vol.Required("code"): cv.matches_regex(r"^[0-9A-F]{4}$"), vol.Required("payload"): cv.matches_regex(r"^([0-9A-F][0-9A-F]){1,48}$"), diff --git a/custom_components/ramses_cc/services.yaml b/custom_components/ramses_cc/services.yaml index ebc35b8..c5891d2 100644 --- a/custom_components/ramses_cc/services.yaml +++ b/custom_components/ramses_cc/services.yaml @@ -65,6 +65,14 @@ send_packet: example: 01:123456 required: true + from_id: + description: >- + The source device ID (a RAMSES ID, not an entity_id). + This can be used to send a packet from a faked device. + If not specified, the device ID of the gateway is used. + example: 18:123456 + required: false + verb: description: 'The packet verb, one of: I, RQ, RP, W (leading space not required).' example: RQ diff --git a/custom_components/ramses_cc/translations/en.json b/custom_components/ramses_cc/translations/en.json index 01c798c..bede5a7 100644 --- a/custom_components/ramses_cc/translations/en.json +++ b/custom_components/ramses_cc/translations/en.json @@ -152,7 +152,7 @@ "advanced_features": { "title": "Advanced features", "data": { - "send_packet": "Enable send_packet service for broadcasting bespoke packets", + "send_packet": "Enable send_packet service for sending bespoke packets", "message_events": "Emit events for messages matching regular expression" }, "data_description": { diff --git a/tests/tests_old/test_services.py b/tests/tests_old/test_services.py index fac0c2c..81a4f5c 100644 --- a/tests/tests_old/test_services.py +++ b/tests/tests_old/test_services.py @@ -100,6 +100,7 @@ "32:097710": {"class": "CO2"}, "32:139773": {"class": "HUM"}, "40:123456": {"class": "REM", "faked": True}, + "37:123456": {"class": "FAN"} }, } @@ -793,3 +794,17 @@ async def test_svc_send_packet(hass: HomeAssistant, entry: ConfigEntry) -> None: schemas = {SVC_SEND_PACKET: SCH_SEND_PACKET} await _test_service_call(hass, SVC_SEND_PACKET, data, schemas=schemas) + +async def test_svc_send_packet_with_impersonation(hass: HomeAssistant, entry: ConfigEntry) -> None: + """Test the service call.""" + + data = { + "device_id": "32:123456", + "from_id": "40:123456", + "verb": " I", + "code": "22F1", + "payload": "000304", + } + schemas = {SVC_SEND_PACKET: SCH_SEND_PACKET} + + await _test_service_call(hass, SVC_SEND_PACKET, data, schemas=schemas) From b61a7985b19f68d01101e555db52c7d4dacb993c Mon Sep 17 00:00:00 2001 From: Kars de Jong Date: Mon, 17 Jun 2024 20:43:30 +0200 Subject: [PATCH 2/5] Fix device_id in test_svc_send_packet_with_impersonation test --- tests/tests_old/test_services.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests_old/test_services.py b/tests/tests_old/test_services.py index 81a4f5c..638e10e 100644 --- a/tests/tests_old/test_services.py +++ b/tests/tests_old/test_services.py @@ -799,7 +799,7 @@ async def test_svc_send_packet_with_impersonation(hass: HomeAssistant, entry: Co """Test the service call.""" data = { - "device_id": "32:123456", + "device_id": "37:123456", "from_id": "40:123456", "verb": " I", "code": "22F1", From 8f19a5cebe26f8003dde9e02045841b6538a084f Mon Sep 17 00:00:00 2001 From: Kars de Jong Date: Tue, 18 Jun 2024 09:50:00 +0200 Subject: [PATCH 3/5] Process review comments --- custom_components/ramses_cc/services.yaml | 2 +- custom_components/ramses_cc/translations/en.json | 2 +- tests/tests_old/test_services.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/custom_components/ramses_cc/services.yaml b/custom_components/ramses_cc/services.yaml index c5891d2..c782c1b 100644 --- a/custom_components/ramses_cc/services.yaml +++ b/custom_components/ramses_cc/services.yaml @@ -69,7 +69,7 @@ send_packet: description: >- The source device ID (a RAMSES ID, not an entity_id). This can be used to send a packet from a faked device. - If not specified, the device ID of the gateway is used. + Optional: if not specified, the device ID of the gateway is used. example: 18:123456 required: false diff --git a/custom_components/ramses_cc/translations/en.json b/custom_components/ramses_cc/translations/en.json index bede5a7..fd182f2 100644 --- a/custom_components/ramses_cc/translations/en.json +++ b/custom_components/ramses_cc/translations/en.json @@ -152,7 +152,7 @@ "advanced_features": { "title": "Advanced features", "data": { - "send_packet": "Enable send_packet service for sending bespoke packets", + "send_packet": "Enable send_packet service for casting bespoke packets", "message_events": "Emit events for messages matching regular expression" }, "data_description": { diff --git a/tests/tests_old/test_services.py b/tests/tests_old/test_services.py index 638e10e..e2725a2 100644 --- a/tests/tests_old/test_services.py +++ b/tests/tests_old/test_services.py @@ -99,8 +99,8 @@ "03:123456": {"class": "THM", "faked": True}, "32:097710": {"class": "CO2"}, "32:139773": {"class": "HUM"}, - "40:123456": {"class": "REM", "faked": True}, - "37:123456": {"class": "FAN"} + "37:123456": {"class": "FAN"}, + "40:123456": {"class": "REM", "faked": True} }, } From 5180185a1c1716a36c9af881e80a7b5271fca08d Mon Sep 17 00:00:00 2001 From: Kars de Jong Date: Sat, 22 Jun 2024 10:49:11 +0200 Subject: [PATCH 4/5] Fix typo in schemas.py --- custom_components/ramses_cc/schemas.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/ramses_cc/schemas.py b/custom_components/ramses_cc/schemas.py index fb101b6..fd2ec43 100644 --- a/custom_components/ramses_cc/schemas.py +++ b/custom_components/ramses_cc/schemas.py @@ -232,7 +232,7 @@ def schema_is_minimal(schema: _SchemaT) -> bool: SCH_SEND_PACKET = vol.Schema( { vol.Required(ATTR_DEVICE_ID): _SCH_DEVICE_ID, - Vol.Optional("from_id"): _SCH_DEVICE_ID, + vol.Optional("from_id"): _SCH_DEVICE_ID, vol.Required("verb"): vol.In((" I", "I", "RQ", "RP", " W", "W")), vol.Required("code"): cv.matches_regex(r"^[0-9A-F]{4}$"), vol.Required("payload"): cv.matches_regex(r"^([0-9A-F][0-9A-F]){1,48}$"), From 07b143bd261e09d11a1e61ceea3e0aa5edb2cc4f Mon Sep 17 00:00:00 2001 From: Kars de Jong Date: Sat, 28 Dec 2024 15:56:35 +0100 Subject: [PATCH 5/5] Fix ruff issue --- tests/tests_old/test_services.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/tests_old/test_services.py b/tests/tests_old/test_services.py index e2725a2..ddcedd1 100644 --- a/tests/tests_old/test_services.py +++ b/tests/tests_old/test_services.py @@ -100,7 +100,7 @@ "32:097710": {"class": "CO2"}, "32:139773": {"class": "HUM"}, "37:123456": {"class": "FAN"}, - "40:123456": {"class": "REM", "faked": True} + "40:123456": {"class": "REM", "faked": True}, }, } @@ -795,7 +795,10 @@ async def test_svc_send_packet(hass: HomeAssistant, entry: ConfigEntry) -> None: await _test_service_call(hass, SVC_SEND_PACKET, data, schemas=schemas) -async def test_svc_send_packet_with_impersonation(hass: HomeAssistant, entry: ConfigEntry) -> None: + +async def test_svc_send_packet_with_impersonation( + hass: HomeAssistant, entry: ConfigEntry +) -> None: """Test the service call.""" data = {