diff --git a/custom_components/bemfa/const.py b/custom_components/bemfa/const.py index a833fff..776f8b3 100644 --- a/custom_components/bemfa/const.py +++ b/custom_components/bemfa/const.py @@ -2,7 +2,7 @@ from typing import Final -from homeassistant.backports.enum import StrEnum +from enum import StrEnum DOMAIN: Final = "bemfa" diff --git a/custom_components/bemfa/manifest.json b/custom_components/bemfa/manifest.json index c2aca07..f0f89ad 100644 --- a/custom_components/bemfa/manifest.json +++ b/custom_components/bemfa/manifest.json @@ -10,8 +10,10 @@ "homekit": {}, "iot_class": "cloud_push", "issue_tracker": "https://github.com/larry-wong/bemfa/issues", - "requirements": ["paho-mqtt==1.6.1"], + "requirements": [ + "paho-mqtt==2.1.0" + ], "ssdp": [], - "version": "1.4.0", + "version": "1.4.3", "zeroconf": [] } \ No newline at end of file diff --git a/custom_components/bemfa/mqtt.py b/custom_components/bemfa/mqtt.py index e75f650..00f5033 100644 --- a/custom_components/bemfa/mqtt.py +++ b/custom_components/bemfa/mqtt.py @@ -38,7 +38,7 @@ def __init__( self._hass = hass # Init MQTT connection - self._mqttc = mqtt.Client(uid, mqtt.MQTTv311) + self._mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, uid, mqtt.MQTTv311) self._topic_to_sync: dict[str, Sync] = {} diff --git a/custom_components/bemfa/sync_light.py b/custom_components/bemfa/sync_light.py index 9573792..d5a0612 100644 --- a/custom_components/bemfa/sync_light.py +++ b/custom_components/bemfa/sync_light.py @@ -6,9 +6,9 @@ from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, - ATTR_COLOR_TEMP, - ATTR_MAX_MIREDS, - ATTR_MIN_MIREDS, + ATTR_COLOR_TEMP_KELVIN, + ATTR_MIN_COLOR_TEMP_KELVIN, + ATTR_MAX_COLOR_TEMP_KELVIN, ATTR_RGB_COLOR, ATTR_SUPPORTED_COLOR_MODES, DOMAIN, @@ -45,8 +45,8 @@ def _msg_generators( lambda state, attributes: round(attributes[ATTR_BRIGHTNESS] / 2.55) if has_key(attributes, ATTR_BRIGHTNESS) else "", - lambda state, attributes: 1000000 // attributes[ATTR_COLOR_TEMP] - if has_key(attributes, ATTR_COLOR_TEMP) + lambda state, attributes: 1000000 // attributes[ATTR_COLOR_TEMP_KELVIN] + if has_key(attributes, ATTR_COLOR_TEMP_KELVIN) else attributes[ATTR_RGB_COLOR][0] * 256 * 256 + attributes[ATTR_RGB_COLOR][1] * 256 + attributes[ATTR_RGB_COLOR][2] @@ -75,9 +75,9 @@ def _msg_resolvers( SERVICE_TURN_ON if msg[0] == MSG_ON else SERVICE_TURN_OFF, { ATTR_BRIGHTNESS_PCT: msg[1], - ATTR_COLOR_TEMP: min( - max(1000000 // msg[2], attributes[ATTR_MIN_MIREDS]), - attributes[ATTR_MAX_MIREDS], + ATTR_COLOR_TEMP_KELVIN: min( + max(1000000 // msg[2], attributes[ATTR_MAX_COLOR_TEMP_KELVIN]), + attributes[ATTR_MIN_COLOR_TEMP_KELVIN], ), } if len(msg) > 2 diff --git a/custom_components/bemfa/sync_sensor.py b/custom_components/bemfa/sync_sensor.py index 1ddb28e..4e06e7d 100644 --- a/custom_components/bemfa/sync_sensor.py +++ b/custom_components/bemfa/sync_sensor.py @@ -8,13 +8,14 @@ from homeassistant.const import ATTR_DEVICE_CLASS from homeassistant.core import HomeAssistant from homeassistant.helpers import area_registry +from homeassistant.helpers import entity_registry +from homeassistant.helpers import device_registry from homeassistant.helpers.selector import ( SelectOptionDict, SelectSelector, SelectSelectorConfig, SelectSelectorMode, ) -from homeassistant.helpers.template import area_entities from .utils import has_key from .const import ( OPTIONS_CO2, @@ -29,6 +30,31 @@ _LOGGING = logging.getLogger(__name__) +def area_entities(hass: HomeAssistant, area_name_or_id: str) -> set[str]: + ar_reg = area_registry.async_get(hass) + area = ar_reg.async_get_area(area_name_or_id) + if area is None: + for a in ar_reg.async_list_areas(): + if a.name == area_name_or_id: + area = a + break + if area is None: + return set() + area_id = area.id + ent_reg = entity_registry.async_get(hass) + dev_reg = device_registry.async_get(hass) + result: set[str] = set() + for entry in list(ent_reg.entities.values()): + if entry.area_id == area_id: + result.add(entry.entity_id) + continue + if entry.device_id is not None: + device = dev_reg.async_get(entry.device_id) + if device is not None and device.area_id == area_id: + result.add(entry.entity_id) + return result + + @SYNC_TYPES.register("sensor") class Sensor(Sync): """Sync a hass area to bemfa sensor device.""" diff --git a/custom_components/bemfa/sync_switch.py b/custom_components/bemfa/sync_switch.py index de8fc8f..3f31665 100644 --- a/custom_components/bemfa/sync_switch.py +++ b/custom_components/bemfa/sync_switch.py @@ -4,11 +4,11 @@ from collections.abc import Mapping, Callable from typing import Any from homeassistant.components.automation import DOMAIN as AUTOMATION_DOMAIN -from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN, STATE_IDLE +from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN, CameraState from homeassistant.components.group import DOMAIN as GROUP_DOMAIN from homeassistant.components.humidifier import DOMAIN as HUMIDIFIER_DOMAIN from homeassistant.components.input_boolean import DOMAIN as INPUT_BOOLEAN_DOMAIN -from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN +from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN, LockState from homeassistant.components.media_player import DOMAIN as MEDIA_PLAYER_DOMAIN from homeassistant.components.remote import DOMAIN as REMOTE_DOMAIN from homeassistant.components.scene import DOMAIN as SCENE_DOMAIN @@ -20,7 +20,7 @@ SERVICE_RETURN_TO_BASE, SERVICE_START, SERVICE_STOP, - STATE_CLEANING, + VacuumActivity, VacuumEntityFeature, ) from homeassistant.const import ( @@ -29,7 +29,6 @@ SERVICE_TURN_ON, SERVICE_UNLOCK, SERVICE_LOCK, - STATE_LOCKED, STATE_ON, STATE_PLAYING, ) @@ -120,7 +119,7 @@ def _supported_domain() -> str: def _msg_generator( self, ) -> Callable[[str, ReadOnlyDict[Mapping[str, Any]]], str | int]: - return lambda state, attributes: MSG_OFF if state == STATE_IDLE else MSG_ON + return lambda state, attributes: MSG_OFF if state == CameraState.IDLE else MSG_ON @SYNC_TYPES.register("media_player") @@ -148,7 +147,7 @@ def _supported_domain() -> str: def _msg_generator( self, ) -> Callable[[str, ReadOnlyDict[Mapping[str, Any]]], str | int]: - return lambda state, attributes: MSG_OFF if state == STATE_LOCKED else MSG_ON + return lambda state, attributes: MSG_OFF if state == LockState.LOCKED else MSG_ON def _service_names(self) -> tuple[str, str]: return (SERVICE_UNLOCK, SERVICE_LOCK) @@ -193,7 +192,7 @@ def _msg_generator( ) -> Callable[[str, ReadOnlyDict[Mapping[str, Any]]], str | int]: return ( lambda state, attributes: MSG_ON - if state in [STATE_ON, STATE_CLEANING] + if state in [STATE_ON, VacuumActivity.CLEANING] else MSG_OFF ) diff --git a/hacs.json b/hacs.json index abd1f00..650669b 100644 --- a/hacs.json +++ b/hacs.json @@ -2,5 +2,5 @@ "name": "bemfa", "render_readme": true, "country": "CN", - "homeassistant": "2022.5.5" + "homeassistant": "2025.12.0" }