Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

## Versions from 0.4x

### v0.55.10 - 2025-08-29

- Final fix for unavailable buttons via plugwise_usb [v0.44.13](https://github.com/plugwise/python-plugwise-usb/releases/tag/v0.44.13)
- Add debug-logging per platform and per entity

### v0.55.9 - 2025-08-25

- Add select for Scan sensitivity
- Add button for Scan light calibration
- Fix disabled buttons for all non-plus devices
- Shorten/correct logger-messages to use `node_duc.node.name`
- Link to plugwise_usb [v0.44.12](https://github.com/plugwise/python-plugwise-usb/releases/tag/v0.44.12)

### v0.55.8 - 2025-08-15

Expand Down
23 changes: 12 additions & 11 deletions custom_components/plugwise_usb/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,16 @@ async def async_add_binary_sensor(node_event: NodeEvent, mac: str) -> None:
return
entities: list[PlugwiseUSBEntity] = []
if (node_duc := config_entry.runtime_data[NODES].get(mac)) is not None:
_LOGGER.debug(
"Add binary_sensor entities for node %s", node_duc.node.name
)
entities.extend(
[
PlugwiseUSBBinarySensor(node_duc, entity_description)
for entity_description in BINARY_SENSOR_TYPES
if entity_description.node_feature in node_duc.node.features
]
)
for entity_description in BINARY_SENSOR_TYPES:
if entity_description.node_feature not in node_duc.node.features:
continue
entities.append(PlugwiseUSBBinarySensor(node_duc, entity_description))
_LOGGER.debug(
"Add %s binary sensor for node %s",
entity_description.translation_key,
node_duc.node.name,
)

if entities:
async_add_entities(entities)

Expand All @@ -105,7 +105,8 @@ async def async_add_binary_sensor(node_event: NodeEvent, mac: str) -> None:
for mac, node in api_stick.nodes.items():
if node.is_loaded:
await async_add_binary_sensor(NodeEvent.LOADED, mac)

else:
_LOGGER.debug("Adding binary_sensor(s) for node %s failed, not loaded", mac)

async def async_unload_entry(
_hass: HomeAssistant,
Expand Down
30 changes: 13 additions & 17 deletions custom_components/plugwise_usb/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.const import EntityCategory, Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import NODES, STICK, UNSUB_NODE_LOADED
Expand Down Expand Up @@ -58,7 +58,7 @@ class PlugwiseButtonEntityDescription(
translation_key="calibrate_light",
entity_category=EntityCategory.CONFIG,
async_button_fn="scan_calibrate_light",
node_feature=NodeFeature.MOTION,
node_feature=NodeFeature.MOTION_CONFIG,
),
)

Expand All @@ -76,14 +76,15 @@ async def async_add_button(node_event: NodeEvent, mac: str) -> None:
return
entities: list[PlugwiseUSBEntity] = []
if (node_duc := config_entry.runtime_data[NODES].get(mac)) is not None:
_LOGGER.debug("Add button entities for node %s", node_duc.node.name)
entities.extend(
[
PlugwiseUSBButtonEntity(node_duc, entity_description)
for entity_description in BUTTON_TYPES
if entity_description.node_feature in node_duc.node.features
]
)
for entity_description in BUTTON_TYPES:
if entity_description.node_feature not in node_duc.node.features:
continue
entities.append(PlugwiseUSBButtonEntity(node_duc, entity_description))
_LOGGER.debug(
"Add %s button for node %s",
entity_description.translation_key,
node_duc.node.name,
)
if entities:
async_add_entities(entities)

Expand All @@ -102,6 +103,8 @@ async def async_add_button(node_event: NodeEvent, mac: str) -> None:
for mac, node in api_stick.nodes.items():
if node.is_loaded:
await async_add_button(NodeEvent.LOADED, mac)
else:
_LOGGER.debug("Adding button(s) for node %s failed, not loaded", mac)


async def async_unload_entry(
Expand All @@ -126,13 +129,6 @@ def __init__(
node_duc.node, entity_description.async_button_fn
)

@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""

async def async_press(self) -> None:
"""Button was pressed."""
await self.async_button_fn()

async def async_added_to_hass(self):
"""Subscribe for push updates."""
6 changes: 3 additions & 3 deletions custom_components/plugwise_usb/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@

UNDO_UPDATE_LISTENER: Final[str] = "undo_update_listener"

PLUGWISE_USB_PLATFORMS: Final[list[str]] = [
PLUGWISE_USB_PLATFORMS: Final[list[Platform]] = [
Platform.BINARY_SENSOR,
Platform.BUTTON,
Platform.EVENT,
Platform.NUMBER,
Platform.SELECT,
Platform.SENSOR,
Platform.SWITCH,
Platform.BUTTON,
Platform.EVENT,
]
CONF_USB_PATH: Final[str] = "usb_path"
SERVICE_DISABLE_PRODUCTION: Final[str] = "disable_production"
Expand Down
4 changes: 3 additions & 1 deletion custom_components/plugwise_usb/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ def __init__(
@property
def available(self) -> bool:
"""Return if entity is available."""
return self.node_duc.node.available and super().available
available = self.node_duc.node.available and super().available
_LOGGER.debug("Entity %s | available = %s", self.entity_description.key, available)
return available

@property
def device_info(self) -> DeviceInfo:
Expand Down
21 changes: 12 additions & 9 deletions custom_components/plugwise_usb/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,15 @@ async def async_add_event(node_event: NodeEvent, mac: str) -> None:
return
entities: list[PlugwiseUSBEntity] = []
if (node_duc := config_entry.runtime_data[NODES].get(mac)) is not None:
_LOGGER.debug("Add event entities for node %s", node_duc.node.name)
entities.extend(
[
PlugwiseUSBEventEntity(node_duc, entity_description)
for entity_description in EVENT_TYPES
if entity_description.node_feature in node_duc.node.features
]
)
for entity_description in EVENT_TYPES:
if entity_description.node_feature not in node_duc.node.features:
continue
entities.append(PlugwiseUSBEventEntity(node_duc, entity_description))
_LOGGER.debug(
"Add %s event for node %s",
entity_description.translation_key,
node_duc.node.name,
)
if entities:
async_add_entities(entities)

Expand All @@ -109,9 +110,11 @@ async def async_add_event(node_event: NodeEvent, mac: str) -> None:
for mac, node in api_stick.nodes.items():
if node.is_loaded:
await async_add_event(NodeEvent.LOADED, mac)

else:
_LOGGER.debug("Adding event(s) for node %s failed, not loaded", mac)

async def async_unload_entry(
_hass: HomeAssistant,
config_entry: PlugwiseUSBConfigEntry,
) -> None:
"""Unload a config entry."""
Expand Down
4 changes: 2 additions & 2 deletions custom_components/plugwise_usb/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["plugwise_usb"],
"requirements": ["plugwise-usb==0.44.12"],
"version": "0.55.9"
"requirements": ["plugwise-usb==0.44.13"],
"version": "0.55.10"
}
21 changes: 12 additions & 9 deletions custom_components/plugwise_usb/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,15 @@ async def async_add_number(node_event: NodeEvent, mac: str) -> None:
return
entities: list[PlugwiseUSBEntity] = []
if (node_duc := config_entry.runtime_data[NODES].get(mac)) is not None:
_LOGGER.debug("Add number entities for node %s", node_duc.node.name)
entities.extend(
[
PlugwiseUSBNumberEntity(node_duc, entity_description)
for entity_description in NUMBER_TYPES
if entity_description.node_feature in node_duc.node.features
]
)
for entity_description in NUMBER_TYPES:
if entity_description.node_feature not in node_duc.node.features:
continue
entities.append(PlugwiseUSBNumberEntity(node_duc, entity_description))
_LOGGER.debug(
"Add %s number for node %s",
entity_description.translation_key,
node_duc.node.name,
)
if entities:
async_add_entities(entities)

Expand All @@ -139,9 +140,11 @@ async def async_add_number(node_event: NodeEvent, mac: str) -> None:
for mac, node in api_stick.nodes.items():
if node.is_loaded:
await async_add_number(NodeEvent.LOADED, mac)

else:
_LOGGER.debug("Adding number(s) for node %s failed, not loaded", mac)

async def async_unload_entry(
_hass: HomeAssistant,
config_entry: PlugwiseUSBConfigEntry,
) -> None:
"""Unload a config entry."""
Expand Down
20 changes: 11 additions & 9 deletions custom_components/plugwise_usb/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,15 @@ async def async_add_select(node_event: NodeEvent, mac: str) -> None:
return
entities: list[PlugwiseUSBEntity] = []
if (node_duc := config_entry.runtime_data[NODES].get(mac)) is not None:
_LOGGER.debug("Add select entities for node %s", node_duc.node.name)
entities.extend(
[
PlugwiseUSBSelectEntity(node_duc, entity_description)
for entity_description in SELECT_TYPES
if entity_description.node_feature in node_duc.node.features
]
)
for entity_description in SELECT_TYPES:
if entity_description.node_feature not in node_duc.node.features:
continue
entities.append(PlugwiseUSBSelectEntity(node_duc, entity_description))
_LOGGER.debug(
"Add %s select for node %s",
entity_description.translation_key,
node_duc.node.name,
)
if entities:
async_add_entities(entities)

Expand All @@ -83,7 +84,8 @@ async def async_add_select(node_event: NodeEvent, mac: str) -> None:
for mac, node in api_stick.nodes.items():
if node.is_loaded:
await async_add_select(NodeEvent.LOADED, mac)

else:
_LOGGER.debug("Adding select(s) for node %s failed, not loaded", mac)

async def async_unload_entry(
_hass: HomeAssistant,
Expand Down
24 changes: 11 additions & 13 deletions custom_components/plugwise_usb/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,22 +172,19 @@ async def async_setup_entry(

async def async_add_sensor(node_event: NodeEvent, mac: str) -> None:
"""Initialize DUC for sensor."""
_LOGGER.debug("async_add_sensor | %s | node_event=%s", mac, node_event)
if node_event != NodeEvent.LOADED:
return
entities: list[PlugwiseUSBEntity] = []
if (node_duc := config_entry.runtime_data[NODES].get(mac)) is not None:
_LOGGER.debug("Add sensor entities for node %s", node_duc.node.name)
entities.extend(
[
PlugwiseUSBSensorEntity(node_duc, entity_description)
for entity_description in SENSOR_TYPES
if entity_description.node_feature in node_duc.node.features
]
)
else:
_LOGGER.debug("async_add_sensor | %s | GET MAC FAILED", mac)

for entity_description in SENSOR_TYPES:
if entity_description.node_feature not in node_duc.node.features:
continue
entities.append(PlugwiseUSBSensorEntity(node_duc, entity_description))
_LOGGER.debug(
"Add %s sensor for node %s",
entity_description.translation_key,
node_duc.node.name,
)
if entities:
async_add_entities(entities)

Expand All @@ -206,7 +203,8 @@ async def async_add_sensor(node_event: NodeEvent, mac: str) -> None:
for mac, node in api_stick.nodes.items():
if node.is_loaded:
await async_add_sensor(NodeEvent.LOADED, mac)

else:
_LOGGER.debug("Adding sensor(s) for node %s failed, not loaded", mac)

async def async_unload_entry(
_hass: HomeAssistant,
Expand Down
20 changes: 11 additions & 9 deletions custom_components/plugwise_usb/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,15 @@ async def async_add_switch(node_event: NodeEvent, mac: str) -> None:
return
entities: list[PlugwiseUSBEntity] = []
if (node_duc := config_entry.runtime_data[NODES].get(mac)) is not None:
_LOGGER.debug("Add switch entities for node %s", node_duc.node.name)
entities.extend(
[
PlugwiseUSBSwitchEntity(node_duc, entity_description)
for entity_description in SWITCH_TYPES
if entity_description.node_feature in node_duc.node.features
]
)
for entity_description in SWITCH_TYPES:
if entity_description.node_feature not in node_duc.node.features:
continue
entities.append(PlugwiseUSBSwitchEntity(node_duc, entity_description))
_LOGGER.debug(
"Add %s switch for node %s",
entity_description.translation_key,
node_duc.node.name,
)
if entities:
async_add_entities(entities)

Expand All @@ -112,7 +113,8 @@ async def async_add_switch(node_event: NodeEvent, mac: str) -> None:
for mac, node in api_stick.nodes.items():
if node.is_loaded:
await async_add_switch(NodeEvent.LOADED, mac)

else:
_LOGGER.debug("Adding switch(es) for node %s failed, not loaded", mac)

async def async_unload_entry(
_hass: HomeAssistant,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "plugwise_usb-beta"
version = "0.55.9"
version = "0.55.10"
description = "Plugwise USB custom_component (BETA)"
readme = "README.md"
requires-python = ">=3.13"
Expand Down
Loading