From 1359ba0aa975432f97778bc8cb9147a3551a2459 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Feb 2026 08:39:50 +0100 Subject: [PATCH 01/23] Start adding options-flow for plus pairing --- custom_components/plugwise_usb/config_flow.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index ad0cc527..05a291b0 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -8,6 +8,7 @@ from homeassistant.components import usb from homeassistant.config_entries import SOURCE_USER, ConfigFlow, ConfigFlowResult +from homeassistant.config_entries import SOURCE_USER, ConfigEntry, ConfigFlow from homeassistant.const import CONF_BASE from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult @@ -19,6 +20,7 @@ vol.Required(CONF_USB_PATH): str, } ) +CONF_ZIGBEE_MAC: Final[str] = "zigbee_mac" @callback @@ -164,3 +166,30 @@ async def async_step_reconfigure( description_placeholders={"title": reconfigure_entry.title}, errors=errors, ) + + @staticmethod + @callback + def async_get_options_flow( + config_entry: ConfigEntry, + ) -> PlugwiseOptionsFlowHandler: + """Get the options flow for this handler.""" + return PlugwiseOptionsFlowHandler(config_entry) + + +class PlugwiseUSBOptionsFlowHandler(OptionsFlow): + """Plugwise USB options flow.""" + + async def async_step_user( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Handle the input of the plus-device MAC address.""" + errors: dict[str, str] = {} + if user_input is not None: + errors, mac = await validate_mac(user_input) # check if zb-mac address has a valid format + if not errors: + #execute pair_plus_device function - use CirclePlusConnectRequest + return self.async_show_form( + step_id=SOURCE_USER, + data_schema=vol.Schema({vol.Required(CONF_ZIGBEE_MAC): str}), + errors=errors, + ) From 678a0d21c1c46274295239091f2cf346c14b980a Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Feb 2026 08:44:23 +0100 Subject: [PATCH 02/23] Start adding pair_plus_device function --- custom_components/plugwise_usb/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/custom_components/plugwise_usb/__init__.py b/custom_components/plugwise_usb/__init__.py index a54b4c0d..363633aa 100644 --- a/custom_components/plugwise_usb/__init__.py +++ b/custom_components/plugwise_usb/__init__.py @@ -132,6 +132,17 @@ async def disable_production(call: ServiceCall) -> bool: ) from exc return result + async def pair_plus_device(call: ServiceCall) -> bool: + """Pair a plus device.""" + mac = mac = call.data[ATTR_MAC] + try: + result = await api_stick.plus_pair_request(mac) + except (NodeError, StickError) as exc: + raise HomeAssistantError( + f"Pairing with Plus-device failed for {mac}: {exc}" + ) from exc + return result + hass.services.async_register( DOMAIN, SERVICE_ENABLE_PRODUCTION, enable_production, SERVICE_USB_DEVICE_SCHEMA ) From c06b932f41bec38e509f5c2e3fc21d86671b75ad Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Feb 2026 16:11:14 +0100 Subject: [PATCH 03/23] Add validate_mac function --- custom_components/plugwise_usb/util.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 custom_components/plugwise_usb/util.py diff --git a/custom_components/plugwise_usb/util.py b/custom_components/plugwise_usb/util.py new file mode 100644 index 00000000..1745ced8 --- /dev/null +++ b/custom_components/plugwise_usb/util.py @@ -0,0 +1,19 @@ +"""Plugwise USB helper functions.""" + +from __future__ import annotations + +import re + +def validate_mac(mac: str) -> bool: + """Validate the supplied string is in a ZigBee MAC address format.""" + try: + if not re.match("^[A-F0-9]+$", mac): + return False + except TypeError: + return False + + try: + _ = int(mac, 16) + except ValueError: + return False + return True \ No newline at end of file From 808e05d896e5bb92170dc66ba30aaa4d5e9e2a1a Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Feb 2026 16:48:53 +0100 Subject: [PATCH 04/23] Update config_flow --- custom_components/plugwise_usb/config_flow.py | 24 +++++++++++++++---- custom_components/plugwise_usb/strings.json | 10 ++++++++ custom_components/plugwise_usb/util.py | 3 ++- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index 05a291b0..0682654e 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -3,17 +3,24 @@ from typing import Any from plugwise_usb import Stick -from plugwise_usb.exceptions import StickError +from plugwise_usb.exceptions import NodeError, StickError import voluptuous as vol from homeassistant.components import usb +from homeassistant.config_entries import ( + SOURCE_USER, + ConfigEntry, + ConfigFlow, + OptionsFlow, +) from homeassistant.config_entries import SOURCE_USER, ConfigFlow, ConfigFlowResult -from homeassistant.config_entries import SOURCE_USER, ConfigEntry, ConfigFlow from homeassistant.const import CONF_BASE from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult +from homeassistant.exceptions import HomeAssistantError from .const import CONF_MANUAL_PATH, CONF_USB_PATH, DOMAIN, MANUAL_PATH +from .util import validate_mac STICK_RECONF_SCHEMA = vol.Schema( { @@ -185,9 +192,16 @@ async def async_step_user( """Handle the input of the plus-device MAC address.""" errors: dict[str, str] = {} if user_input is not None: - errors, mac = await validate_mac(user_input) # check if zb-mac address has a valid format - if not errors: - #execute pair_plus_device function - use CirclePlusConnectRequest + valid = await validate_mac(user_input) + if not valid: + try: + coordinator.api_stick.plus_pair_request(user_input) + except NodeError: + raise HomeAssistantError(f"Pairing of Plus-device {user_input} failed") + return None + + errors["init"] = "invalid mac" + return self.async_show_form( step_id=SOURCE_USER, data_schema=vol.Schema({vol.Required(CONF_ZIGBEE_MAC): str}), diff --git a/custom_components/plugwise_usb/strings.json b/custom_components/plugwise_usb/strings.json index 3f5dde0a..aacf9855 100644 --- a/custom_components/plugwise_usb/strings.json +++ b/custom_components/plugwise_usb/strings.json @@ -32,6 +32,16 @@ "stick_init": "Initialization of Plugwise USB-stick failed" } }, + "options": { + "step": { + "user": { + "data": { + "mac": " ZigBee MAC" + }, + "description": "Pair Plus-device, please enter:" + } + } + }, "services": { "enable_production":{ "name": "Enable production logging", diff --git a/custom_components/plugwise_usb/util.py b/custom_components/plugwise_usb/util.py index 1745ced8..cdc829c5 100644 --- a/custom_components/plugwise_usb/util.py +++ b/custom_components/plugwise_usb/util.py @@ -4,6 +4,7 @@ import re + def validate_mac(mac: str) -> bool: """Validate the supplied string is in a ZigBee MAC address format.""" try: @@ -16,4 +17,4 @@ def validate_mac(mac: str) -> bool: _ = int(mac, 16) except ValueError: return False - return True \ No newline at end of file + return True From 03abe9fbbf817b1d46f07bbc97677a0b3959ed69 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Feb 2026 19:04:07 +0100 Subject: [PATCH 05/23] Fixes --- custom_components/plugwise_usb/__init__.py | 2 +- custom_components/plugwise_usb/config_flow.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/custom_components/plugwise_usb/__init__.py b/custom_components/plugwise_usb/__init__.py index 363633aa..314359ee 100644 --- a/custom_components/plugwise_usb/__init__.py +++ b/custom_components/plugwise_usb/__init__.py @@ -134,7 +134,7 @@ async def disable_production(call: ServiceCall) -> bool: async def pair_plus_device(call: ServiceCall) -> bool: """Pair a plus device.""" - mac = mac = call.data[ATTR_MAC] + mac = call.data[ATTR_MAC] try: result = await api_stick.plus_pair_request(mac) except (NodeError, StickError) as exc: diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index 0682654e..3e4141ec 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -1,6 +1,6 @@ """Config flow for Plugwise USB integration.""" -from typing import Any +from typing import Any, Final from plugwise_usb import Stick from plugwise_usb.exceptions import NodeError, StickError @@ -11,6 +11,7 @@ SOURCE_USER, ConfigEntry, ConfigFlow, + ConfigFlowResult, OptionsFlow, ) from homeassistant.config_entries import SOURCE_USER, ConfigFlow, ConfigFlowResult @@ -178,9 +179,9 @@ async def async_step_reconfigure( @callback def async_get_options_flow( config_entry: ConfigEntry, - ) -> PlugwiseOptionsFlowHandler: + ) -> PlugwiseUSBOptionsFlowHandler: """Get the options flow for this handler.""" - return PlugwiseOptionsFlowHandler(config_entry) + return PlugwiseUSBOptionsFlowHandler(config_entry) class PlugwiseUSBOptionsFlowHandler(OptionsFlow): @@ -190,14 +191,15 @@ async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult: """Handle the input of the plus-device MAC address.""" + coordinator = self.config_entry.runtime_data errors: dict[str, str] = {} if user_input is not None: valid = await validate_mac(user_input) if not valid: try: coordinator.api_stick.plus_pair_request(user_input) - except NodeError: - raise HomeAssistantError(f"Pairing of Plus-device {user_input} failed") + except NodeError as exc: + raise HomeAssistantError(f"Pairing of Plus-device {user_input} failed") from exc return None errors["init"] = "invalid mac" From 3929bd172878396deeac1b3a719d15bd17304d9a Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Feb 2026 19:10:58 +0100 Subject: [PATCH 06/23] Focus on options-flow --- custom_components/plugwise_usb/__init__.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/custom_components/plugwise_usb/__init__.py b/custom_components/plugwise_usb/__init__.py index 314359ee..a54b4c0d 100644 --- a/custom_components/plugwise_usb/__init__.py +++ b/custom_components/plugwise_usb/__init__.py @@ -132,17 +132,6 @@ async def disable_production(call: ServiceCall) -> bool: ) from exc return result - async def pair_plus_device(call: ServiceCall) -> bool: - """Pair a plus device.""" - mac = call.data[ATTR_MAC] - try: - result = await api_stick.plus_pair_request(mac) - except (NodeError, StickError) as exc: - raise HomeAssistantError( - f"Pairing with Plus-device failed for {mac}: {exc}" - ) from exc - return result - hass.services.async_register( DOMAIN, SERVICE_ENABLE_PRODUCTION, enable_production, SERVICE_USB_DEVICE_SCHEMA ) From 3da41954da87ccaf25d3be45e9c8eef50330bdf8 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Feb 2026 19:19:20 +0100 Subject: [PATCH 07/23] Test with LOGGER.debug() --- custom_components/plugwise_usb/config_flow.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index 3e4141ec..c8c4f760 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -20,7 +20,7 @@ from homeassistant.data_entry_flow import FlowResult from homeassistant.exceptions import HomeAssistantError -from .const import CONF_MANUAL_PATH, CONF_USB_PATH, DOMAIN, MANUAL_PATH +from .const import CONF_MANUAL_PATH, CONF_USB_PATH, DOMAIN, LOGGER, MANUAL_PATH from .util import validate_mac STICK_RECONF_SCHEMA = vol.Schema( @@ -189,15 +189,15 @@ class PlugwiseUSBOptionsFlowHandler(OptionsFlow): async def async_step_user( self, user_input: dict[str, Any] | None = None - ) -> ConfigFlowResult: + ) -> ConfigFlowResult | None: """Handle the input of the plus-device MAC address.""" coordinator = self.config_entry.runtime_data errors: dict[str, str] = {} if user_input is not None: - valid = await validate_mac(user_input) - if not valid: + if validate_mac(user_input): try: - coordinator.api_stick.plus_pair_request(user_input) + # coordinator.api_stick.plus_pair_request(user_input) + LOGGER.debug("Fake call to api_stick.plus_pair_request with %s", user_input) except NodeError as exc: raise HomeAssistantError(f"Pairing of Plus-device {user_input} failed") from exc return None From ffb0bbc2b4330b2942723e319e5e53d5fc75ecef Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 2 Feb 2026 19:21:21 +0100 Subject: [PATCH 08/23] Disable unused --- custom_components/plugwise_usb/config_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index c8c4f760..6b30d517 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -191,7 +191,7 @@ async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult | None: """Handle the input of the plus-device MAC address.""" - coordinator = self.config_entry.runtime_data + # coordinator = self.config_entry.runtime_data errors: dict[str, str] = {} if user_input is not None: if validate_mac(user_input): From de0d0b2b1380cade1dcb86806438fc9640cd9c1a Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 3 Feb 2026 11:43:03 +0100 Subject: [PATCH 09/23] Add init to options_flow --- custom_components/plugwise_usb/config_flow.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index 6b30d517..3b642c69 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -187,16 +187,20 @@ def async_get_options_flow( class PlugwiseUSBOptionsFlowHandler(OptionsFlow): """Plugwise USB options flow.""" + def __init__(self, config_entry: ConfigEntry) -> None: + """Initialize options flow.""" + self.coordinator = self.config_entry.runtime_data + async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult | None: """Handle the input of the plus-device MAC address.""" - # coordinator = self.config_entry.runtime_data + errors: dict[str, str] = {} if user_input is not None: if validate_mac(user_input): try: - # coordinator.api_stick.plus_pair_request(user_input) + # self.coordinator.api_stick.plus_pair_request(user_input) LOGGER.debug("Fake call to api_stick.plus_pair_request with %s", user_input) except NodeError as exc: raise HomeAssistantError(f"Pairing of Plus-device {user_input} failed") from exc From 13338f4420052c2d967b64be3b5a50d57f56acf0 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 9 Feb 2026 13:18:23 +0100 Subject: [PATCH 10/23] OptionFlow updates: enter mac address, no error at wrong entry --- custom_components/plugwise_usb/config_flow.py | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index 3b642c69..5bef0bef 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -1,5 +1,6 @@ """Config flow for Plugwise USB integration.""" +from copy import deepcopy from typing import Any, Final from plugwise_usb import Stick @@ -8,7 +9,6 @@ from homeassistant.components import usb from homeassistant.config_entries import ( - SOURCE_USER, ConfigEntry, ConfigFlow, ConfigFlowResult, @@ -21,6 +21,7 @@ from homeassistant.exceptions import HomeAssistantError from .const import CONF_MANUAL_PATH, CONF_USB_PATH, DOMAIN, LOGGER, MANUAL_PATH +from .coordinator import PlugwiseUSBDataUpdateCoordinator from .util import validate_mac STICK_RECONF_SCHEMA = vol.Schema( @@ -28,6 +29,8 @@ vol.Required(CONF_USB_PATH): str, } ) +type PlugwiseUSBConfigEntry = ConfigEntry[PlugwiseUSBDataUpdateCoordinator] + CONF_ZIGBEE_MAC: Final[str] = "zigbee_mac" @@ -178,7 +181,7 @@ async def async_step_reconfigure( @staticmethod @callback def async_get_options_flow( - config_entry: ConfigEntry, + config_entry: PlugwiseUSBConfigEntry ) -> PlugwiseUSBOptionsFlowHandler: """Get the options flow for this handler.""" return PlugwiseUSBOptionsFlowHandler(config_entry) @@ -189,27 +192,30 @@ class PlugwiseUSBOptionsFlowHandler(OptionsFlow): def __init__(self, config_entry: ConfigEntry) -> None: """Initialize options flow.""" - self.coordinator = self.config_entry.runtime_data + pass + # self.data = deepcopy(dict(config_entry.data)) - async def async_step_user( + async def async_step_init( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult | None: """Handle the input of the plus-device MAC address.""" - + # coordinator = self.config_entry.runtime_data errors: dict[str, str] = {} if user_input is not None: - if validate_mac(user_input): + mac = user_input["zigbee_mac"] + if validate_mac(mac): try: - # self.coordinator.api_stick.plus_pair_request(user_input) - LOGGER.debug("Fake call to api_stick.plus_pair_request with %s", user_input) + # self.coordinator.api_stick.plus_pair_request(mac) + LOGGER.warning("Fake call to api_stick.plus_pair_request with %s", mac) except NodeError as exc: - raise HomeAssistantError(f"Pairing of Plus-device {user_input} failed") from exc - return None + raise HomeAssistantError(f"Pairing of Plus-device {mac} failed") from exc + return self.async_create_entry(title="", data=user_input) - errors["init"] = "invalid mac" + errors["init"] = "invalid_mac" return self.async_show_form( - step_id=SOURCE_USER, + step_id="init", data_schema=vol.Schema({vol.Required(CONF_ZIGBEE_MAC): str}), errors=errors, ) + From 76082da28822d1573ee882ed1ae091f069ef94b3 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 9 Feb 2026 13:19:05 +0100 Subject: [PATCH 11/23] Correct validate_mac() --- custom_components/plugwise_usb/util.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/custom_components/plugwise_usb/util.py b/custom_components/plugwise_usb/util.py index cdc829c5..863bb6dc 100644 --- a/custom_components/plugwise_usb/util.py +++ b/custom_components/plugwise_usb/util.py @@ -4,7 +4,6 @@ import re - def validate_mac(mac: str) -> bool: """Validate the supplied string is in a ZigBee MAC address format.""" try: @@ -13,8 +12,6 @@ def validate_mac(mac: str) -> bool: except TypeError: return False - try: - _ = int(mac, 16) - except ValueError: + if len(mac) != 16: return False - return True + return True \ No newline at end of file From 176052d87a8250ce2103293105432be789ce9649 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 9 Feb 2026 13:19:41 +0100 Subject: [PATCH 12/23] Update strings.json --- custom_components/plugwise_usb/strings.json | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/custom_components/plugwise_usb/strings.json b/custom_components/plugwise_usb/strings.json index aacf9855..8f4025f0 100644 --- a/custom_components/plugwise_usb/strings.json +++ b/custom_components/plugwise_usb/strings.json @@ -34,12 +34,16 @@ }, "options": { "step": { - "user": { + "init": { + "title": "Pair Plus-device", + "description": "Please enter the ZigBee MAC address:", "data": { - "mac": " ZigBee MAC" - }, - "description": "Pair Plus-device, please enter:" + "zigbee_mac": "16-bit MAC" + } } + }, + "error": { + "invalid_mac": "MAC is invalid, please retry" } }, "services": { @@ -255,3 +259,4 @@ } } } + From 9d4ef690a4d63f782381433d6aa29f651c4ba2f8 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Mon, 9 Feb 2026 13:36:44 +0100 Subject: [PATCH 13/23] Update __init__.py --- custom_components/plugwise_usb/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/custom_components/plugwise_usb/__init__.py b/custom_components/plugwise_usb/__init__.py index a54b4c0d..7573eec3 100644 --- a/custom_components/plugwise_usb/__init__.py +++ b/custom_components/plugwise_usb/__init__.py @@ -105,6 +105,8 @@ async def async_node_discovered(node_event: NodeEvent, mac: str) -> None: await api_stick.disconnect() raise ConfigEntryNotReady("No connected Plus-device found, pair with one first e.g. via Source") from exc + _LOGGER.info("Discovery of the Plugwise network coordinator has finished") + # Load platforms to allow them to register for node events await hass.config_entries.async_forward_entry_setups( config_entry, PLUGWISE_USB_PLATFORMS @@ -151,9 +153,11 @@ async def disable_production(call: ServiceCall) -> bool: while True: await asyncio.sleep(1) + _LOGGER.debug("Discovering network...") if api_stick.network_discovered: break + _LOGGER.debug("INIT done.") return True From e063cf9486104f8293666c9dd0f6d490edf263b4 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Tue, 10 Feb 2026 09:55:48 +0100 Subject: [PATCH 14/23] Fix error handling --- custom_components/plugwise_usb/config_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index 5bef0bef..a2dfaf3c 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -211,7 +211,7 @@ async def async_step_init( raise HomeAssistantError(f"Pairing of Plus-device {mac} failed") from exc return self.async_create_entry(title="", data=user_input) - errors["init"] = "invalid_mac" + errors[CONF_BASE] = "invalid_mac" return self.async_show_form( step_id="init", From 127fdd142bae83f66d6b6053362f083e7b9e88d0 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 13 Feb 2026 19:33:05 +0100 Subject: [PATCH 15/23] Link to v0.48.0a1, bump to v0.59.0a0 test-version --- custom_components/plugwise_usb/manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/plugwise_usb/manifest.json b/custom_components/plugwise_usb/manifest.json index ace55a6e..44c18f28 100644 --- a/custom_components/plugwise_usb/manifest.json +++ b/custom_components/plugwise_usb/manifest.json @@ -9,6 +9,6 @@ "iot_class": "local_polling", "issue_tracker": "https://github.com/plugwise/python-plugwise-usb/issues", "loggers": ["plugwise_usb"], - "requirements": ["plugwise-usb==0.47.8"], - "version": "0.59.3" + "requirements": ["plugwise-usb@git+https://github.com/plugwise/python-plugwise-usb@pair-plus#plugwise-usb==0.48.0a1"], + "version": "0.59.0a0" } From 66d6a289b3f8c3cecb2407d01c8ab2198929ea67 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 13 Feb 2026 19:36:11 +0100 Subject: [PATCH 16/23] Link to pair-plus-request() --- custom_components/plugwise_usb/config_flow.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index a2dfaf3c..d81536b4 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -192,21 +192,18 @@ class PlugwiseUSBOptionsFlowHandler(OptionsFlow): def __init__(self, config_entry: ConfigEntry) -> None: """Initialize options flow.""" - pass - # self.data = deepcopy(dict(config_entry.data)) + self.coordinator = self.config_entry.runtime_data async def async_step_init( self, user_input: dict[str, Any] | None = None ) -> ConfigFlowResult | None: """Handle the input of the plus-device MAC address.""" - # coordinator = self.config_entry.runtime_data errors: dict[str, str] = {} if user_input is not None: mac = user_input["zigbee_mac"] if validate_mac(mac): try: - # self.coordinator.api_stick.plus_pair_request(mac) - LOGGER.warning("Fake call to api_stick.plus_pair_request with %s", mac) + self.coordinator.api_stick.plus_pair_request(mac) except NodeError as exc: raise HomeAssistantError(f"Pairing of Plus-device {mac} failed") from exc return self.async_create_entry(title="", data=user_input) From dd540c18a9db4bba7daa9a5b4917115d1e1d166b Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 13 Feb 2026 19:38:30 +0100 Subject: [PATCH 17/23] Import SOURCE_USER --- custom_components/plugwise_usb/config_flow.py | 1 + 1 file changed, 1 insertion(+) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index d81536b4..041f826a 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -9,6 +9,7 @@ from homeassistant.components import usb from homeassistant.config_entries import ( + SOURCE_USER, ConfigEntry, ConfigFlow, ConfigFlowResult, From 985e638d7baa6b348ae72a3e0d341a812cb3e7d3 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 13 Feb 2026 19:39:24 +0100 Subject: [PATCH 18/23] Clean up --- custom_components/plugwise_usb/config_flow.py | 2 +- custom_components/plugwise_usb/util.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index 041f826a..87c73530 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -21,7 +21,7 @@ from homeassistant.data_entry_flow import FlowResult from homeassistant.exceptions import HomeAssistantError -from .const import CONF_MANUAL_PATH, CONF_USB_PATH, DOMAIN, LOGGER, MANUAL_PATH +from .const import CONF_MANUAL_PATH, CONF_USB_PATH, DOMAIN, MANUAL_PATH from .coordinator import PlugwiseUSBDataUpdateCoordinator from .util import validate_mac diff --git a/custom_components/plugwise_usb/util.py b/custom_components/plugwise_usb/util.py index 863bb6dc..e0aaadc1 100644 --- a/custom_components/plugwise_usb/util.py +++ b/custom_components/plugwise_usb/util.py @@ -4,6 +4,7 @@ import re + def validate_mac(mac: str) -> bool: """Validate the supplied string is in a ZigBee MAC address format.""" try: @@ -14,4 +15,4 @@ def validate_mac(mac: str) -> bool: if len(mac) != 16: return False - return True \ No newline at end of file + return True From ea05edf07ee905f51d3500eeb953c8faaed747ad Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 13 Feb 2026 19:47:29 +0100 Subject: [PATCH 19/23] Update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f9f1439..16a1f7f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.59.0(a0) + +- Test new feature: pairing of Plus-device (untested!!) + ## Ongoing - Improve raise-message for no paired Plus-device, via PR[#399](https://github.com/plugwise/plugwise_usb-beta/pull/399) From 5c246710adb6c0f2a17a15347d0e3421401e2de3 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 5 Sep 2026 12:20:10 +0200 Subject: [PATCH 20/23] Fix after rebase --- CHANGELOG.md | 2 +- custom_components/plugwise_usb/config_flow.py | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16a1f7f8..0ef7832b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v0.59.0(a0) +## v0.60.0(a0) - Test new feature: pairing of Plus-device (untested!!) diff --git a/custom_components/plugwise_usb/config_flow.py b/custom_components/plugwise_usb/config_flow.py index 87c73530..bf8ea620 100644 --- a/custom_components/plugwise_usb/config_flow.py +++ b/custom_components/plugwise_usb/config_flow.py @@ -1,6 +1,5 @@ """Config flow for Plugwise USB integration.""" -from copy import deepcopy from typing import Any, Final from plugwise_usb import Stick @@ -15,7 +14,6 @@ ConfigFlowResult, OptionsFlow, ) -from homeassistant.config_entries import SOURCE_USER, ConfigFlow, ConfigFlowResult from homeassistant.const import CONF_BASE from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult @@ -25,14 +23,15 @@ from .coordinator import PlugwiseUSBDataUpdateCoordinator from .util import validate_mac +type PlugwiseUSBConfigEntry = ConfigEntry[PlugwiseUSBDataUpdateCoordinator] + +CONF_ZIGBEE_MAC: Final[str] = "zigbee_mac" + STICK_RECONF_SCHEMA = vol.Schema( { vol.Required(CONF_USB_PATH): str, } ) -type PlugwiseUSBConfigEntry = ConfigEntry[PlugwiseUSBDataUpdateCoordinator] - -CONF_ZIGBEE_MAC: Final[str] = "zigbee_mac" @callback From d3b6f8e3e94d05269a796fff0174b58bfa473874 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 5 Sep 2026 15:01:44 +0200 Subject: [PATCH 21/23] Update CHANGELOG after rebase --- CHANGELOG.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ef7832b..8d4b8783 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,6 @@ ## v0.60.0(a0) - Test new feature: pairing of Plus-device (untested!!) - -## Ongoing - - Improve raise-message for no paired Plus-device, via PR[#399](https://github.com/plugwise/plugwise_usb-beta/pull/399) ## v0.59.3 From 7f874b8f97ce5cc2060ee93f4d9cf6a8bd2e6742 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 5 Sep 2026 18:27:48 +0200 Subject: [PATCH 22/23] Update translations --- .../plugwise_usb/translations/en.json | 14 ++++++++++++++ .../plugwise_usb/translations/nl.json | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/custom_components/plugwise_usb/translations/en.json b/custom_components/plugwise_usb/translations/en.json index ac3b0a02..cfa66bd4 100644 --- a/custom_components/plugwise_usb/translations/en.json +++ b/custom_components/plugwise_usb/translations/en.json @@ -222,6 +222,20 @@ } } }, + "options": { + "error": { + "invalid_mac": "MAC is invalid, please retry" + }, + "step": { + "init": { + "data": { + "zigbee_mac": "16-bit MAC" + }, + "description": "Please enter the ZigBee MAC address:", + "title": "Pair Plus-device" + } + } + }, "services": { "disable_production": { "description": "Enter the mac of the Node: (data = mac: 0123456789ABCDEF)", diff --git a/custom_components/plugwise_usb/translations/nl.json b/custom_components/plugwise_usb/translations/nl.json index 12148eb0..7d724e59 100644 --- a/custom_components/plugwise_usb/translations/nl.json +++ b/custom_components/plugwise_usb/translations/nl.json @@ -32,6 +32,20 @@ "stick_init": "Initaliseren van USB-stick mislukt" } }, + "options": { + "step": { + "init": { + "title": "Pair Plus-apparaat", + "description": "Voer het ZigBee MAC adres in:", + "data": { + "zigbee_mac": "16-bit MAC" + } + } + }, + "error": { + "invalid_mac": "Ongeldig MAC adres, voer een geldig adres in" + } + }, "services": { "enable_production":{ "name": "Zet productie-loggen aan", From 7ae1a807851ac567529e2d2f7cd16c27bbb369ad Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 5 Sep 2026 18:30:12 +0200 Subject: [PATCH 23/23] Clean up --- custom_components/plugwise_usb/util.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/custom_components/plugwise_usb/util.py b/custom_components/plugwise_usb/util.py index e0aaadc1..95fd108b 100644 --- a/custom_components/plugwise_usb/util.py +++ b/custom_components/plugwise_usb/util.py @@ -1,7 +1,5 @@ """Plugwise USB helper functions.""" -from __future__ import annotations - import re