Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
ad9c439
Link to plugwise v1.6.0a0
bouwew Nov 18, 2024
eeacb17
Update some test-fixtures
bouwew Nov 18, 2024
fde2739
Update relevant test-asserts
bouwew Nov 18, 2024
519aa20
Let select also process zones
bouwew Nov 18, 2024
d747959
Improve sensor.py
bouwew Nov 18, 2024
be38ea3
Fix select
bouwew Nov 18, 2024
cf67069
Fix zone select/sensor naming
bouwew Nov 18, 2024
43ad931
Fix
bouwew Nov 18, 2024
7bc9fb8
Try pass all as entity
bouwew Nov 18, 2024
e834584
Fix test-assert
bouwew Nov 18, 2024
41351f4
Link to plugwise v1.6.0a1
bouwew Nov 19, 2024
a335933
Adapt to a1
bouwew Nov 19, 2024
e16f73e
Update test-fixtures
bouwew Nov 19, 2024
f7a4c9f
Adapt test-code
bouwew Nov 19, 2024
4bab650
Adapt api-call
bouwew Nov 19, 2024
eb922dc
More adapting
bouwew Nov 19, 2024
2490f9f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 19, 2024
eb0acef
Link to plugwise v1.6.0a2
bouwew Nov 21, 2024
ff210dd
Update test-fixtures
bouwew Nov 21, 2024
555c53b
Adapt testcode
bouwew Nov 21, 2024
d500b8b
Adapt code
bouwew Nov 21, 2024
d916b8e
Fixes
bouwew Nov 22, 2024
480c137
Improve climate
bouwew Nov 22, 2024
4e6f23b
Update more test-fixtures
bouwew Nov 22, 2024
c1fbbc0
Fixes
bouwew Nov 22, 2024
44d9138
Fix mypy error
bouwew Nov 23, 2024
9d0ba93
Save updated snapshot
bouwew Nov 23, 2024
44f61cf
Mypy error alternative solution
bouwew Nov 23, 2024
365cd41
Typing fix
bouwew Nov 23, 2024
de65290
Update CHANGELOG
bouwew Nov 23, 2024
a67ae3f
Bump to v0.55.0a0 test-version
bouwew Nov 23, 2024
ec50927
Clean up
bouwew Nov 23, 2024
2f9c929
Update README.md
bouwew Nov 23, 2024
0a8f02b
Update fixtures
bouwew Nov 25, 2024
c344118
Link to plugwise v1.6.0a3, bumpt to a2
bouwew Nov 25, 2024
b75199d
Re-adapt testcode
bouwew Nov 25, 2024
1313e7d
Improve testcode
bouwew Nov 25, 2024
eaf9e37
Fix coordinator code
bouwew Nov 25, 2024
144dcf6
Fix comments
bouwew Nov 26, 2024
6dd371a
Fixture updates
bouwew Nov 26, 2024
a9d0ed1
Code updates
bouwew Nov 26, 2024
bd942ec
Fix climate processing for added thermostat
bouwew Nov 26, 2024
14e05c8
Save updated diagnostics assert-file
bouwew Nov 26, 2024
e3c1304
Fixes
bouwew Nov 26, 2024
444b690
Improve
bouwew Nov 26, 2024
cf85dd8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 26, 2024
886d986
Link to plugwise v1.6.0, bump to v0.55.0 release-version
bouwew Nov 26, 2024
0e49f5a
Add BREAKING message to CHANGELOG
bouwew Nov 26, 2024
f944cf2
Improve CHANGELOG
bouwew Nov 26, 2024
38c44dc
Extend CHANGELOG
bouwew Nov 26, 2024
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Versions from 0.40 and up

## v0.55.0

- **BREAKING change for Adam**: the existing device-based climate entities will be replaced by new zone-based climate entities, most likely with a different name.
- New Feature: implement zone-based climate entities for Adam, solving HA Core Issue [130597](https://github.com/home-assistant/core/issues/130597).
- Also new: add the provided zone sensors.
- Link to plugwise [v1.6.0](https://github.com/plugwise/python-plugwise/releases/tag/v1.6.0).

## v0.54.3

- Bugfix for #768 via plugwise [v1.5.2](https://github.com/plugwise/python-plugwise/releases/tag/v1.5.2).
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Our [Changelog](CHANGELOG.MD) is available as a [separate file](CHANGELOG.md) in
### What do we support (in short)?

- Thermostats
- Adam (firmware 2.x and 3.x) and the accompanying Lisa's, Tom's, Floor's, Koen's and Plugs.
- Adam (firmware 2.x and 3.x) and the accompanying Anna, Jip's, Lisa's, Tom's, Floor's and Plugs (Koen via a Plug). From v0.55.0 zones with one or more thermostats are represented as a single and separate climate-entity in HA.
- Anna (firmware 1.x, 3.x and 4.x)
- Notifications for both types
- Power-related
Expand All @@ -70,6 +70,7 @@ As such we ask USB users, who are tied in with the `custom_component` as there i
### What can I expect in HA Core from this component

- `binary_sensor` and `sensor`: A number of sensoric values depending on your hardware: outdoor temperature, Anna's illuminance, Tom's valve position, Plug's and Circle/Stealth's power-values, P1 power- and gas-values, Plugwise Notifications.
- `button`: A reboot-button is available for the Gateways that support this function.
- `climate`: A (number of) thermostat(s) visible in HA, including temperature, presets and heating-demand status, per thermostat. Also, setting of temperature, preset and switching the active schedule on and off. Cooling is only supported in combination with an Anna (fw 3.1 and 4.0).
- `number`: Numerical indication on boiler setpoints.
- `select`: Input selector to choose the active schedule.
Expand Down
22 changes: 18 additions & 4 deletions custom_components/plugwise/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,18 @@ def _add_entities() -> None:
return

entities: list[PlugwiseClimateEntity] = []
gateway_name = coordinator.data.gateway[SMILE_NAME]
for device_id in coordinator.new_devices:
device = coordinator.data.devices[device_id]
if device[DEV_CLASS] in MASTER_THERMOSTATS:
if gateway_name == "Adam":
if device[DEV_CLASS] == "climate":
entities.append(
PlugwiseClimateEntity(
coordinator, device_id, homekit_enabled
) # pw-beta homekit emulation
)
LOGGER.debug("Add climate %s", device[ATTR_NAME])
elif device[DEV_CLASS] in MASTER_THERMOSTATS:
entities.append(
PlugwiseClimateEntity(
coordinator, device_id, homekit_enabled
Expand Down Expand Up @@ -118,6 +127,11 @@ def __init__(
super().__init__(coordinator, device_id)

self._homekit_enabled = homekit_enabled # pw-beta homekit emulation

self._location = device_id
if (location := self.device.get(LOCATION)) is not None:
self._location = location

gateway_id: str = coordinator.data.gateway[GATEWAY_ID]
self.gateway_data = coordinator.data.devices[gateway_id]

Expand Down Expand Up @@ -273,7 +287,7 @@ async def async_set_temperature(self, **kwargs: Any) -> None:
if mode := kwargs.get(ATTR_HVAC_MODE):
await self.async_set_hvac_mode(mode)

await self.coordinator.api.set_temperature(self.device[LOCATION], data)
await self.coordinator.api.set_temperature(self._location, data)

@plugwise_command
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
Expand All @@ -286,7 +300,7 @@ async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:

if hvac_mode != HVACMode.OFF:
await self.coordinator.api.set_schedule_state(
self.device[LOCATION],
self._location,
STATE_ON if hvac_mode == HVACMode.AUTO else STATE_OFF,
)

Expand All @@ -310,4 +324,4 @@ async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
@plugwise_command
async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set the preset mode."""
await self.coordinator.api.set_preset(self.device[LOCATION], preset_mode)
await self.coordinator.api.set_preset(self._location, preset_mode)
1 change: 0 additions & 1 deletion custom_components/plugwise/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
CONF_HOMEKIT_EMULATION: Final = "homekit_emulation" # pw-beta options
CONF_REFRESH_INTERVAL: Final = "refresh_interval" # pw-beta options
CONF_MANUAL_PATH: Final = "Enter Manually"
DEVICES: Final = "devices"
GATEWAY: Final = "gateway"
LOCATION: Final = "location"
MAC_ADDRESS: Final = "mac_address"
Expand Down
6 changes: 3 additions & 3 deletions custom_components/plugwise/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ async def _connect(self) -> None:
version = await self.api.connect()
self._connected = isinstance(version, Version)
if self._connected:
self.api.get_all_devices()
self.api.get_all_gateway_entities()
self.update_interval = DEFAULT_SCAN_INTERVAL.get(
self.api.smile_type, timedelta(seconds=60)
) # pw-beta options scan-interval
Expand All @@ -91,7 +91,7 @@ async def _connect(self) -> None:

async def _async_update_data(self) -> PlugwiseData:
"""Fetch data from Plugwise."""
data = PlugwiseData({}, {})
data = PlugwiseData(devices={}, gateway={})
try:
if not self._connected:
await self._connect()
Expand Down Expand Up @@ -148,7 +148,7 @@ async def async_remove_devices(self, data: PlugwiseData, entry: ConfigEntry) ->
device_entry.id, remove_config_entry_id=entry.entry_id
)
LOGGER.debug(
"Removed %s device %s %s from device_registry",
"Removed %s device/zone %s %s from device_registry",
DOMAIN,
device_entry.model,
identifier[1],
Expand Down
2 changes: 1 addition & 1 deletion custom_components/plugwise/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ async def async_get_config_entry_diagnostics(
"""Return diagnostics for a config entry."""
coordinator = entry.runtime_data
return {
"gateway": coordinator.data.gateway,
"devices": coordinator.data.devices,
"gateway": coordinator.data.gateway,
}
6 changes: 3 additions & 3 deletions custom_components/plugwise/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

from plugwise.constants import DeviceData
from plugwise.constants import GwEntityData

from homeassistant.const import ATTR_NAME, ATTR_VIA_DEVICE, CONF_HOST
from homeassistant.helpers.device_registry import (
Expand Down Expand Up @@ -82,15 +82,15 @@ def __init__(
def available(self) -> bool:
"""Return if entity is available."""
return (
# Upstream: Do not change the AVAILABLE line below: some Plugwise devices
# Upstream: Do not change the AVAILABLE line below: some Plugwise devices and zones
# Upstream: do not provide their availability-status!
self._dev_id in self.coordinator.data.devices
and (AVAILABLE not in self.device or self.device[AVAILABLE] is True)
and super().available
)

@property
def device(self) -> DeviceData:
def device(self) -> GwEntityData:
"""Return data for this device."""
return self.coordinator.data.devices[self._dev_id]

Expand Down
4 changes: 2 additions & 2 deletions custom_components/plugwise/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["plugwise"],
"requirements": ["plugwise==1.5.2"],
"version": "0.54.3",
"requirements": ["plugwise==1.6.0"],
"version": "0.55.0",
"zeroconf": ["_plugwise._tcp.local."]
}
11 changes: 8 additions & 3 deletions custom_components/plugwise/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def _add_entities() -> None:
LOGGER.debug(
"Add %s %s selector", device["name"], description.translation_key
)

async_add_entities(entities)

_add_entities()
Expand All @@ -124,8 +125,12 @@ def __init__(
) -> None:
"""Initialise the selector."""
super().__init__(coordinator, device_id)
self.entity_description = entity_description
self._attr_unique_id = f"{device_id}-{entity_description.key}"
self.entity_description = entity_description

self._location = device_id
if (location := self.device.get(LOCATION)) is not None:
self._location = location

@property
def current_option(self) -> str:
Expand All @@ -141,10 +146,10 @@ def options(self) -> list[str]:
async def async_select_option(self, option: str) -> None:
"""Change to the selected entity option.

self.device[LOCATION] and STATE_ON are required for the thermostat-schedule select.
Location ID and STATE_ON are required for the thermostat-schedule select.
"""
await self.coordinator.api.set_select(
self.entity_description.key, self.device[LOCATION], option, STATE_ON
self.entity_description.key, self._location, option, STATE_ON
)
LOGGER.debug(
"Set %s to %s was successful",
Expand Down
1 change: 1 addition & 0 deletions custom_components/plugwise/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ def _add_entities() -> None:
LOGGER.debug(
"Add %s %s sensor", device["name"], description.translation_key or description.key
)

async_add_entities(entities)

_add_entities()
Expand Down
14 changes: 7 additions & 7 deletions tests/components/plugwise/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def mock_smile_adam() -> Generator[MagicMock]:
smile = smile_mock.return_value

smile.async_update.return_value = PlugwiseData(
all_data["gateway"], all_data["devices"]
all_data["devices"], all_data["gateway"]
)
smile.connect.return_value = Version("3.0.15")
smile.gateway_id = "fe799307f1624099878210aa0b9f1475"
Expand All @@ -129,7 +129,7 @@ def mock_smile_adam_heat_cool(chosen_env: str) -> Generator[MagicMock]:
smile = smile_mock.return_value

smile.async_update.return_value = PlugwiseData(
all_data["gateway"], all_data["devices"]
all_data["devices"], all_data["gateway"]
)
smile.connect.return_value = Version("3.6.4")
smile.gateway_id = "da224107914542988a88561b4452b0f6"
Expand All @@ -155,7 +155,7 @@ def mock_smile_adam_4() -> Generator[MagicMock]:
smile = smile_mock.return_value

smile.async_update.return_value = PlugwiseData(
all_data["gateway"], all_data["devices"]
all_data["devices"], all_data["gateway"]
)
smile.connect.return_value = Version("3.2.8")
smile.gateway_id = "b5c2386c6f6342669e50fe49dd05b188"
Expand All @@ -180,7 +180,7 @@ def mock_smile_anna(chosen_env: str) -> Generator[MagicMock]:
smile = smile_mock.return_value

smile.async_update.return_value = PlugwiseData(
all_data["gateway"], all_data["devices"]
all_data["devices"], all_data["gateway"]
)
smile.connect.return_value = Version("4.0.15")
smile.gateway_id = "015ae9ea3f964e668e490fa39da3870b"
Expand All @@ -205,7 +205,7 @@ def mock_smile_p1(chosen_env: str, gateway_id: str) -> Generator[MagicMock]:
smile = smile_mock.return_value

smile.async_update.return_value = PlugwiseData(
all_data["gateway"], all_data["devices"]
all_data["devices"], all_data["gateway"]
)
smile.connect.return_value = Version("4.4.2")
smile.gateway_id = gateway_id
Expand All @@ -231,7 +231,7 @@ def mock_smile_legacy_anna() -> Generator[MagicMock]:
smile = smile_mock.return_value

smile.async_update.return_value = PlugwiseData(
all_data["gateway"], all_data["devices"]
all_data["devices"], all_data["gateway"]
)
smile.connect.return_value = Version("1.8.22")
smile.gateway_id = "0000aaaa0000aaaa0000aaaa0000aa00"
Expand All @@ -257,7 +257,7 @@ def mock_stretch() -> Generator[MagicMock]:
smile = smile_mock.return_value

smile.async_update.return_value = PlugwiseData(
all_data["gateway"], all_data["devices"]
all_data["devices"], all_data["gateway"]
)
smile.connect.return_value = Version("3.1.11")
smile.gateway_id = "259882df3c05415b99c2d962534ce820"
Expand Down
Loading
Loading