Bump homematicip to 2.0.4 (#144096)

* Bump to 2.0.2 with all necessary changes

* bump to prerelease

* add addiional tests

* Bump to homematicip 2.0.3

* do not delete device

* Setup BRAND_SWITCH_MEASURING as light

* bump to 2.0.4

* refactor test_remove_obsolete_entities

* move test

* use const from homematicip lib
This commit is contained in:
hahn-th 2025-06-10 20:44:06 +02:00 committed by GitHub
parent 4d28992f2b
commit dbfecf99dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 54 additions and 27 deletions

View File

@ -112,6 +112,7 @@ class HomematicipHAP:
self.config_entry = config_entry self.config_entry = config_entry
self._ws_close_requested = False self._ws_close_requested = False
self._ws_connection_closed = asyncio.Event()
self._retry_task: asyncio.Task | None = None self._retry_task: asyncio.Task | None = None
self._tries = 0 self._tries = 0
self._accesspoint_connected = True self._accesspoint_connected = True
@ -218,6 +219,8 @@ class HomematicipHAP:
try: try:
await self.home.get_current_state_async() await self.home.get_current_state_async()
hmip_events = self.home.enable_events() hmip_events = self.home.enable_events()
self.home.set_on_connected_handler(self.ws_connected_handler)
self.home.set_on_disconnected_handler(self.ws_disconnected_handler)
tries = 0 tries = 0
await hmip_events await hmip_events
except HmipConnectionError: except HmipConnectionError:
@ -267,6 +270,18 @@ class HomematicipHAP:
"Reset connection to access point id %s", self.config_entry.unique_id "Reset connection to access point id %s", self.config_entry.unique_id
) )
async def ws_connected_handler(self) -> None:
"""Handle websocket connected."""
_LOGGER.debug("WebSocket connection to HomematicIP established")
if self._ws_connection_closed.is_set():
await self.get_state()
self._ws_connection_closed.clear()
async def ws_disconnected_handler(self) -> None:
"""Handle websocket disconnection."""
_LOGGER.warning("WebSocket connection to HomematicIP closed")
self._ws_connection_closed.set()
async def get_hap( async def get_hap(
self, self,
hass: HomeAssistant, hass: HomeAssistant,
@ -290,6 +305,7 @@ class HomematicipHAP:
raise HmipcConnectionError from err raise HmipcConnectionError from err
home.on_update(self.async_update) home.on_update(self.async_update)
home.on_create(self.async_create_entity) home.on_create(self.async_create_entity)
hass.loop.create_task(self.async_connect()) hass.loop.create_task(self.async_connect())
return home return home

View File

@ -4,16 +4,16 @@ from __future__ import annotations
from typing import Any from typing import Any
from homematicip.base.enums import OpticalSignalBehaviour, RGBColorState from homematicip.base.enums import DeviceType, OpticalSignalBehaviour, RGBColorState
from homematicip.base.functionalChannels import NotificationLightChannel from homematicip.base.functionalChannels import NotificationLightChannel
from homematicip.device import ( from homematicip.device import (
BrandDimmer, BrandDimmer,
BrandSwitchMeasuring,
BrandSwitchNotificationLight, BrandSwitchNotificationLight,
Dimmer, Dimmer,
DinRailDimmer3, DinRailDimmer3,
FullFlushDimmer, FullFlushDimmer,
PluggableDimmer, PluggableDimmer,
SwitchMeasuring,
WiredDimmer3, WiredDimmer3,
) )
from packaging.version import Version from packaging.version import Version
@ -44,9 +44,12 @@ async def async_setup_entry(
hap = config_entry.runtime_data hap = config_entry.runtime_data
entities: list[HomematicipGenericEntity] = [] entities: list[HomematicipGenericEntity] = []
for device in hap.home.devices: for device in hap.home.devices:
if isinstance(device, BrandSwitchMeasuring): if (
isinstance(device, SwitchMeasuring)
and getattr(device, "deviceType", None) == DeviceType.BRAND_SWITCH_MEASURING
):
entities.append(HomematicipLightMeasuring(hap, device)) entities.append(HomematicipLightMeasuring(hap, device))
elif isinstance(device, BrandSwitchNotificationLight): if isinstance(device, BrandSwitchNotificationLight):
device_version = Version(device.firmwareVersion) device_version = Version(device.firmwareVersion)
entities.append(HomematicipLight(hap, device)) entities.append(HomematicipLight(hap, device))

View File

@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/homematicip_cloud", "documentation": "https://www.home-assistant.io/integrations/homematicip_cloud",
"iot_class": "cloud_push", "iot_class": "cloud_push",
"loggers": ["homematicip"], "loggers": ["homematicip"],
"requirements": ["homematicip==2.0.1.1"] "requirements": ["homematicip==2.0.4"]
} }

View File

@ -11,12 +11,10 @@ from homematicip.base.functionalChannels import (
FunctionalChannel, FunctionalChannel,
) )
from homematicip.device import ( from homematicip.device import (
BrandSwitchMeasuring,
EnergySensorsInterface, EnergySensorsInterface,
FloorTerminalBlock6, FloorTerminalBlock6,
FloorTerminalBlock10, FloorTerminalBlock10,
FloorTerminalBlock12, FloorTerminalBlock12,
FullFlushSwitchMeasuring,
HeatingThermostat, HeatingThermostat,
HeatingThermostatCompact, HeatingThermostatCompact,
HeatingThermostatEvo, HeatingThermostatEvo,
@ -26,9 +24,9 @@ from homematicip.device import (
MotionDetectorOutdoor, MotionDetectorOutdoor,
MotionDetectorPushButton, MotionDetectorPushButton,
PassageDetector, PassageDetector,
PlugableSwitchMeasuring,
PresenceDetectorIndoor, PresenceDetectorIndoor,
RoomControlDeviceAnalog, RoomControlDeviceAnalog,
SwitchMeasuring,
TemperatureDifferenceSensor2, TemperatureDifferenceSensor2,
TemperatureHumiditySensorDisplay, TemperatureHumiditySensorDisplay,
TemperatureHumiditySensorOutdoor, TemperatureHumiditySensorOutdoor,
@ -143,14 +141,7 @@ async def async_setup_entry(
), ),
): ):
entities.append(HomematicipIlluminanceSensor(hap, device)) entities.append(HomematicipIlluminanceSensor(hap, device))
if isinstance( if isinstance(device, SwitchMeasuring):
device,
(
PlugableSwitchMeasuring,
BrandSwitchMeasuring,
FullFlushSwitchMeasuring,
),
):
entities.append(HomematicipPowerSensor(hap, device)) entities.append(HomematicipPowerSensor(hap, device))
entities.append(HomematicipEnergySensor(hap, device)) entities.append(HomematicipEnergySensor(hap, device))
if isinstance(device, (WeatherSensor, WeatherSensorPlus, WeatherSensorPro)): if isinstance(device, (WeatherSensor, WeatherSensorPlus, WeatherSensorPro)):

View File

@ -4,20 +4,19 @@ from __future__ import annotations
from typing import Any from typing import Any
from homematicip.base.enums import DeviceType
from homematicip.device import ( from homematicip.device import (
BrandSwitch2, BrandSwitch2,
BrandSwitchMeasuring,
DinRailSwitch, DinRailSwitch,
DinRailSwitch4, DinRailSwitch4,
FullFlushInputSwitch, FullFlushInputSwitch,
FullFlushSwitchMeasuring,
HeatingSwitch2, HeatingSwitch2,
MultiIOBox, MultiIOBox,
OpenCollector8Module, OpenCollector8Module,
PlugableSwitch, PlugableSwitch,
PlugableSwitchMeasuring,
PrintedCircuitBoardSwitch2, PrintedCircuitBoardSwitch2,
PrintedCircuitBoardSwitchBattery, PrintedCircuitBoardSwitchBattery,
SwitchMeasuring,
WiredSwitch8, WiredSwitch8,
) )
from homematicip.group import ExtendedLinkedSwitchingGroup, SwitchingGroup from homematicip.group import ExtendedLinkedSwitchingGroup, SwitchingGroup
@ -43,12 +42,10 @@ async def async_setup_entry(
if isinstance(group, (ExtendedLinkedSwitchingGroup, SwitchingGroup)) if isinstance(group, (ExtendedLinkedSwitchingGroup, SwitchingGroup))
] ]
for device in hap.home.devices: for device in hap.home.devices:
if isinstance(device, BrandSwitchMeasuring): if (
# BrandSwitchMeasuring inherits PlugableSwitchMeasuring isinstance(device, SwitchMeasuring)
# This entity is implemented in the light platform and will and getattr(device, "deviceType", None) != DeviceType.BRAND_SWITCH_MEASURING
# not be added in the switch platform ):
pass
elif isinstance(device, (PlugableSwitchMeasuring, FullFlushSwitchMeasuring)):
entities.append(HomematicipSwitchMeasuring(hap, device)) entities.append(HomematicipSwitchMeasuring(hap, device))
elif isinstance(device, WiredSwitch8): elif isinstance(device, WiredSwitch8):
entities.extend( entities.extend(

2
requirements_all.txt generated
View File

@ -1170,7 +1170,7 @@ home-assistant-frontend==20250531.0
home-assistant-intents==2025.5.28 home-assistant-intents==2025.5.28
# homeassistant.components.homematicip_cloud # homeassistant.components.homematicip_cloud
homematicip==2.0.1.1 homematicip==2.0.4
# homeassistant.components.horizon # homeassistant.components.horizon
horimote==0.4.1 horimote==0.4.1

View File

@ -1016,7 +1016,7 @@ home-assistant-frontend==20250531.0
home-assistant-intents==2025.5.28 home-assistant-intents==2025.5.28
# homeassistant.components.homematicip_cloud # homeassistant.components.homematicip_cloud
homematicip==2.0.1.1 homematicip==2.0.4
# homeassistant.components.remember_the_milk # homeassistant.components.remember_the_milk
httplib2==0.20.4 httplib2==0.20.4

View File

@ -231,3 +231,23 @@ async def test_auth_create_exception(hass: HomeAssistant, simple_mock_auth) -> N
), ),
): ):
assert not await hmip_auth.get_auth(hass, HAPID, HAPPIN) assert not await hmip_auth.get_auth(hass, HAPID, HAPPIN)
async def test_get_state_after_disconnect(
hass: HomeAssistant, hmip_config_entry: MockConfigEntry, simple_mock_home
) -> None:
"""Test get state after disconnect."""
hass.config.components.add(DOMAIN)
hap = HomematicipHAP(hass, hmip_config_entry)
assert hap
with patch.object(hap, "get_state") as mock_get_state:
assert not hap._ws_connection_closed.is_set()
await hap.ws_connected_handler()
mock_get_state.assert_not_called()
await hap.ws_disconnected_handler()
assert hap._ws_connection_closed.is_set()
await hap.ws_connected_handler()
mock_get_state.assert_called_once()