From b8c5ee85a9260201782b70451420af6ef7d225f4 Mon Sep 17 00:00:00 2001 From: skddyj Date: Thu, 6 Mar 2025 15:35:06 +0800 Subject: [PATCH 1/8] fix:upgrade paho-mqtt version to 2.1.0 --- custom_components/bemfa/manifest.json | 2 +- custom_components/bemfa/mqtt.py | 2 +- hacs.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/custom_components/bemfa/manifest.json b/custom_components/bemfa/manifest.json index c2aca07..1364e72 100644 --- a/custom_components/bemfa/manifest.json +++ b/custom_components/bemfa/manifest.json @@ -10,7 +10,7 @@ "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", "zeroconf": [] 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/hacs.json b/hacs.json index abd1f00..273caf6 100644 --- a/hacs.json +++ b/hacs.json @@ -2,5 +2,5 @@ "name": "bemfa", "render_readme": true, "country": "CN", - "homeassistant": "2022.5.5" + "homeassistant": "2025.3.0" } From c181f97c4bb1934ed26b0cfc3a81ca2216ae7225 Mon Sep 17 00:00:00 2001 From: skddyj Date: Thu, 6 Mar 2025 15:46:36 +0800 Subject: [PATCH 2/8] update version --- custom_components/bemfa/manifest.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/custom_components/bemfa/manifest.json b/custom_components/bemfa/manifest.json index 1364e72..d6cafb5 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==2.1.0"], + "requirements": [ + "paho-mqtt==2.1.0" + ], "ssdp": [], - "version": "1.4.0", + "version": "1.4.1", "zeroconf": [] } \ No newline at end of file From 426a5a2cc5ba8beb58415bbb2ba9d02716d4e507 Mon Sep 17 00:00:00 2001 From: skddyj Date: Fri, 13 Jun 2025 09:41:43 +0800 Subject: [PATCH 3/8] fix:fix some deprecated attr --- custom_components/bemfa/const.py | 2 +- custom_components/bemfa/manifest.json | 2 +- custom_components/bemfa/sync_light.py | 16 ++++++++-------- custom_components/bemfa/sync_switch.py | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) 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 d6cafb5..cfd38f3 100644 --- a/custom_components/bemfa/manifest.json +++ b/custom_components/bemfa/manifest.json @@ -14,6 +14,6 @@ "paho-mqtt==2.1.0" ], "ssdp": [], - "version": "1.4.1", + "version": "1.4.2", "zeroconf": [] } \ No newline at end of file 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_switch.py b/custom_components/bemfa/sync_switch.py index de8fc8f..8b45c10 100644 --- a/custom_components/bemfa/sync_switch.py +++ b/custom_components/bemfa/sync_switch.py @@ -4,7 +4,7 @@ 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 @@ -20,7 +20,7 @@ SERVICE_RETURN_TO_BASE, SERVICE_START, SERVICE_STOP, - STATE_CLEANING, + VacuumActivity, VacuumEntityFeature, ) from homeassistant.const import ( @@ -29,7 +29,7 @@ SERVICE_TURN_ON, SERVICE_UNLOCK, SERVICE_LOCK, - STATE_LOCKED, + LockState, STATE_ON, STATE_PLAYING, ) @@ -120,7 +120,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 +148,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 +193,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 ) From 044a0513705c5639daab5504ef95d1245d74e7d5 Mon Sep 17 00:00:00 2001 From: skddyj Date: Fri, 13 Jun 2025 10:11:32 +0800 Subject: [PATCH 4/8] fix:fix LockState import problem --- custom_components/bemfa/sync_switch.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/custom_components/bemfa/sync_switch.py b/custom_components/bemfa/sync_switch.py index 8b45c10..4e8f311 100644 --- a/custom_components/bemfa/sync_switch.py +++ b/custom_components/bemfa/sync_switch.py @@ -29,10 +29,12 @@ SERVICE_TURN_ON, SERVICE_UNLOCK, SERVICE_LOCK, - LockState, STATE_ON, STATE_PLAYING, ) +from homeassistant.lock import ( + LockState, +) from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN from homeassistant.util.read_only_dict import ReadOnlyDict from .const import MSG_OFF, MSG_ON, TopicSuffix From 59e7854187d7a2c28da5a523a3c1dfe2203ecefd Mon Sep 17 00:00:00 2001 From: skddyj Date: Fri, 13 Jun 2025 10:15:24 +0800 Subject: [PATCH 5/8] fix:fix LockState import problem --- custom_components/bemfa/sync_switch.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/custom_components/bemfa/sync_switch.py b/custom_components/bemfa/sync_switch.py index 4e8f311..3f31665 100644 --- a/custom_components/bemfa/sync_switch.py +++ b/custom_components/bemfa/sync_switch.py @@ -8,7 +8,7 @@ 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 @@ -32,9 +32,6 @@ STATE_ON, STATE_PLAYING, ) -from homeassistant.lock import ( - LockState, -) from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN from homeassistant.util.read_only_dict import ReadOnlyDict from .const import MSG_OFF, MSG_ON, TopicSuffix From b1b4cc0d31628269f1d9af79e01e3624449000c7 Mon Sep 17 00:00:00 2001 From: skddyj Date: Fri, 5 Dec 2025 11:22:49 +0800 Subject: [PATCH 6/8] fix:cannot import name area_entities from homeassistant.helpers.template --- custom_components/bemfa/manifest.json | 2 +- custom_components/bemfa/sync_sensor.py | 23 +++++++++++++++++++++-- hacs.json | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/custom_components/bemfa/manifest.json b/custom_components/bemfa/manifest.json index cfd38f3..f0f89ad 100644 --- a/custom_components/bemfa/manifest.json +++ b/custom_components/bemfa/manifest.json @@ -14,6 +14,6 @@ "paho-mqtt==2.1.0" ], "ssdp": [], - "version": "1.4.2", + "version": "1.4.3", "zeroconf": [] } \ No newline at end of file diff --git a/custom_components/bemfa/sync_sensor.py b/custom_components/bemfa/sync_sensor.py index 1ddb28e..1e07ff2 100644 --- a/custom_components/bemfa/sync_sensor.py +++ b/custom_components/bemfa/sync_sensor.py @@ -14,7 +14,7 @@ SelectSelectorConfig, SelectSelectorMode, ) -from homeassistant.helpers.template import area_entities +# from homeassistant.helpers.template import area_entities from .utils import has_key from .const import ( OPTIONS_CO2, @@ -57,7 +57,26 @@ def generate_details_schema(self) -> dict[str, Any]: co2_sensors: dict[str, str] = {} # filter entities in our area - a_entities = area_entities(self._hass, self._entity_id.split(".")[1]) + # a_entities = area_entities(self._hass, self._entity_id.split(".")[1]) + area_id = self._entity_id.split(".")[1] + + area_reg = area_registry.async_get(self._hass) + device_reg = self._hass.helpers.device_registry.async_get(self._hass) + entity_reg = self._hass.helpers.entity_registry.async_get(self._hass) + + # 获取该 area 下所有 device_id + area_devices = [ + device.id + for device in device_reg.devices.values() + if device.area_id == area_id + ] + + # 获取这些设备下的所有实体 + a_entities = { + entity.entity_id + for entity in entity_reg.entities.values() + if entity.device_id in area_devices + } for state in self._hass.states.async_all(SENSOR_DOMAIN): if state.entity_id not in a_entities: diff --git a/hacs.json b/hacs.json index 273caf6..650669b 100644 --- a/hacs.json +++ b/hacs.json @@ -2,5 +2,5 @@ "name": "bemfa", "render_readme": true, "country": "CN", - "homeassistant": "2025.3.0" + "homeassistant": "2025.12.0" } From f885e575084cb610ac420c8de5a4b6743cff396f Mon Sep 17 00:00:00 2001 From: skddyj Date: Fri, 5 Dec 2025 14:37:05 +0800 Subject: [PATCH 7/8] fix:cannot import name area_entities from homeassistant.helpers.template --- custom_components/bemfa/sync_sensor.py | 49 +++++++++++++++----------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/custom_components/bemfa/sync_sensor.py b/custom_components/bemfa/sync_sensor.py index 1e07ff2..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.""" @@ -57,26 +83,7 @@ def generate_details_schema(self) -> dict[str, Any]: co2_sensors: dict[str, str] = {} # filter entities in our area - # a_entities = area_entities(self._hass, self._entity_id.split(".")[1]) - area_id = self._entity_id.split(".")[1] - - area_reg = area_registry.async_get(self._hass) - device_reg = self._hass.helpers.device_registry.async_get(self._hass) - entity_reg = self._hass.helpers.entity_registry.async_get(self._hass) - - # 获取该 area 下所有 device_id - area_devices = [ - device.id - for device in device_reg.devices.values() - if device.area_id == area_id - ] - - # 获取这些设备下的所有实体 - a_entities = { - entity.entity_id - for entity in entity_reg.entities.values() - if entity.device_id in area_devices - } + a_entities = area_entities(self._hass, self._entity_id.split(".")[1]) for state in self._hass.states.async_all(SENSOR_DOMAIN): if state.entity_id not in a_entities: From 34b799e6001bda74ec7d2b288cccafdb090562ae Mon Sep 17 00:00:00 2001 From: s94949494 <149304472+s94949494@users.noreply.github.com> Date: Sun, 18 Jan 2026 00:01:34 +0800 Subject: [PATCH 8/8] Fix color temperature calculation in sync_light.py Fix color temperature calculation --- custom_components/bemfa/sync_light.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/custom_components/bemfa/sync_light.py b/custom_components/bemfa/sync_light.py index d5a0612..258db7d 100644 --- a/custom_components/bemfa/sync_light.py +++ b/custom_components/bemfa/sync_light.py @@ -45,7 +45,7 @@ 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_KELVIN] + lambda state, attributes: 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 @@ -76,8 +76,8 @@ def _msg_resolvers( { ATTR_BRIGHTNESS_PCT: msg[1], ATTR_COLOR_TEMP_KELVIN: min( - max(1000000 // msg[2], attributes[ATTR_MAX_COLOR_TEMP_KELVIN]), - attributes[ATTR_MIN_COLOR_TEMP_KELVIN], + max(msg[2], attributes[ATTR_MIN_COLOR_TEMP_KELVIN]), + attributes[ATTR_MAX_COLOR_TEMP_KELVIN], ), } if len(msg) > 2