Skip to content

Commit f676151

Browse files
committed
fix: entity state (enable/disable) issues
1 parent c2b1741 commit f676151

6 files changed

Lines changed: 45 additions & 55 deletions

File tree

custom_components/mi_kettle_pro/button.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
AVAIL_EVENT_KEY_ENTRY_ID,
1212
AVAIL_EVENT_KEY_IS_CONTROL,
1313
AVAIL_EVENT,
14+
AVAIL_EVENT_KEY_AVAIL,
1415
)
1516
from .device_config import DEVICE_CONFIGS
1617
from .utils import gen_entity_id
@@ -71,13 +72,29 @@ async def async_added_to_hass(self) -> None:
7172
self._handle_status_update
7273
)
7374

75+
# Register availability event listener
76+
self._listener = self.hass.bus.async_listen(
77+
AVAIL_EVENT,
78+
self._handle_availability_changed
79+
)
80+
7481
async def async_will_remove_from_hass(self) -> None:
7582
"""Run when entity will be removed from hass."""
7683
if self._device_manager:
7784
self._device_manager.device_parser.unregister_status_callback(
7885
self._handle_status_update
7986
)
8087

88+
# Remove availability event listener
89+
if self._listener:
90+
self._listener()
91+
92+
def _handle_availability_changed(self, event) -> None:
93+
"""Handle availability change events."""
94+
if event.data.get(AVAIL_EVENT_KEY_ENTRY_ID) == self._entry.entry_id:
95+
self._attr_available = event.data.get(AVAIL_EVENT_KEY_AVAIL, False)
96+
self.hass.loop.call_soon_threadsafe(self.async_write_ha_state)
97+
8198
def _handle_status_update(self, status_data: dict) -> None:
8299
"""Handle status updates from Device manager."""
83100
if status_data:

custom_components/mi_kettle_pro/device/mikettle_pro.py

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@
4242
AVAIL_EVENT_KEY_AVAIL,
4343
AVAIL_EVENT,
4444
AVAIL_EVENT_KEY_IS_LOGIN,
45-
AVAIL_EVENT_KEY_IS_CONTROL,
4645
WARM_INDEX,
4746
HEAT_INDEX,
47+
CONF_HEAT_TEMPERATURE,
48+
CONF_WARM_TEMPERATURE,
4849
)
4950

5051
_LOGGER = logging.getLogger(__name__)
@@ -71,8 +72,6 @@ def __init__(
7172
self.poll_interval = poll_interval
7273
self.entry_id = entry_id
7374
self.entry = self.hass.config_entries.async_get_entry(self.entry_id)
74-
self.heat_temp_entity_id = gen_entity_id(self.entry, "number", "heat_temperature")
75-
self.warm_temp_entity_id = gen_entity_id(self.entry, "number", "warm_temperature")
7675
self.bt_interface = bt_interface
7776

7877
# connection state
@@ -656,31 +655,12 @@ def _async_disconnect(self, client: BleakClient | None = None) -> None:
656655

657656
async def _async_update_kettle_mode(self):
658657
"""Update kettle configuration, get temperature settings"""
659-
def _get_temp_by_entity_id(entity_id):
660-
temp_state = self.hass.states.get(entity_id)
661-
temperature = None
662-
# Parse temperature
663-
if temp_state and temp_state.state not in ("unknown", "unavailable"):
664-
try:
665-
temperature = int(temp_state.state)
666-
_LOGGER.debug(
667-
"Got temperature setting: temperature: %s, entity_id: %s",
668-
temperature, entity_id
669-
)
670-
except ValueError:
671-
_LOGGER.warning(
672-
"Invalid temperature value: %s, entity_id: %s",
673-
temp_state.state, entity_id
674-
)
675-
raise
676-
return temperature
677-
678658
try:
679659
# Get heating temperature
680-
heat_temperature = _get_temp_by_entity_id(self.heat_temp_entity_id)
660+
heat_temperature = self.entry.options[CONF_HEAT_TEMPERATURE]
681661

682662
# Get warming temperature
683-
warm_temperature = _get_temp_by_entity_id(self.warm_temp_entity_id)
663+
warm_temperature = self.entry.options[CONF_WARM_TEMPERATURE]
684664
_LOGGER.debug(
685665
"get temperature from entity, heat: %s, warm: %s",
686666
heat_temperature, warm_temperature
@@ -704,7 +684,7 @@ def _get_temp_by_entity_id(entity_id):
704684
)
705685

706686
except Exception as exc:
707-
_LOGGER.error("Failed to get temperature settings: %s", exc)
687+
_LOGGER.exception("Failed to get temperature settings: %s", exc)
708688
return None
709689

710690
def replace_mode_segment(self, current_data, mode_index, new_temperature, new_duration=None):
@@ -878,12 +858,12 @@ async def _monitor_for_temperature(self, target_temp, callback: Callable):
878858
async def heat_safe_check(self):
879859
mode = self.get_current_mode()
880860
if not mode >= 0:
881-
_LOGGER.error("turn off heating failed, mode: %s", mode)
861+
_LOGGER.error("Turn off heating failed, mode: %s", mode)
882862
return
883863
if mode == HEAT_INDEX:
884864
ret = await self.async_read_mode_config_by_index(mode)
885865
if not ret:
886-
_LOGGER.error("turn off heating failed, ret: %s", ret)
866+
_LOGGER.error("Turn off heating failed, ret: %s", ret)
887867
return
888868
target_temp = ret["temperature"]
889869
_LOGGER.debug("check if mode temperature reached, mode: %s, target_temp: %s", mode, target_temp)

custom_components/mi_kettle_pro/device_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def detection_callback(device, adv_data):
199199
_LOGGER.error("Advertisement scan failed: %s", exc)
200200
return None
201201
except Exception as exc:
202-
_LOGGER.error("Advertisement scan failed unexpected: %s", exc)
202+
_LOGGER.exception("Advertisement scan failed unexpected: %s", exc)
203203
return None
204204
finally:
205205
await scanner.stop()

custom_components/mi_kettle_pro/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
"requirements": ["bleak-retry-connector>=3.9.0", "bleak>=0.22.3"],
1313
"ssdp": [],
1414
"zeroconf": [],
15-
"version": "v0.2.0"
15+
"version": "v0.2.1"
1616
}

custom_components/mi_kettle_pro/number.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
MAX_WARM_TEMPERATURE,
2121
DEFAULT_HEAT_TEMPERATURE,
2222
DEFAULT_WARM_TEMPERATURE,
23-
AVAIL_EVENT_KEY_IS_CONTROL,
23+
AVAIL_EVENT,
24+
AVAIL_EVENT_KEY_ENTRY_ID,
25+
AVAIL_EVENT_KEY_AVAIL,
2426
)
2527
from .utils import gen_entity_id
2628
from .device_config import DEVICE_CONFIGS
@@ -68,10 +70,10 @@ def __init__(self, entry: ConfigEntry) -> None:
6870
"manufacturer": "Xiaomi",
6971
"model": "Mi Kettle Pro",
7072
}
71-
73+
self._listener = None
7274
# Debounce related attributes
7375
self._debounce_timer = None
74-
self._debounce_delay = 0.5
76+
self._debounce_delay = 0.8
7577
self._pending_value = None
7678

7779
# value
@@ -84,22 +86,16 @@ async def async_added_to_hass(self) -> None:
8486
device_manager_key = f"{self._entry.entry_id}_device_manager"
8587
self._device_manager = self.hass.data[DOMAIN].get(device_manager_key)
8688

87-
async def async_added_to_hass(self) -> None:
88-
"""Run when entity about to be added to hass."""
89-
device_manager_key = f"{self._entry.entry_id}_device_manager"
90-
self._device_manager = self.hass.data[DOMAIN].get(device_manager_key)
91-
92-
if self._device_manager:
93-
self._device_manager.device_parser.register_status_callback(
94-
self._handle_status_update
95-
)
89+
# Register availability event listener
90+
self._listener = self.hass.bus.async_listen(
91+
AVAIL_EVENT,
92+
self._handle_availability_changed
93+
)
9694

9795
async def async_will_remove_from_hass(self) -> None:
98-
"""Run when entity will be removed from hass."""
99-
if self._device_manager:
100-
self._device_manager.device_parser.unregister_status_callback(
101-
self._handle_status_update
102-
)
96+
# Remove availability event listener
97+
if self._listener:
98+
self._listener()
10399

104100
async def _async_debounced_set_value(self, value: int) -> None:
105101
"""Actual set value method after debounce"""
@@ -133,13 +129,11 @@ async def _async_apply_value(self, value: int) -> None:
133129
options=new_options
134130
)
135131

136-
def _handle_status_update(self, status_data: dict) -> None:
137-
"""Handle status updates from Device manager."""
138-
if status_data:
139-
self._attr_available = status_data.get(
140-
AVAIL_EVENT_KEY_IS_CONTROL, False
141-
)
142-
self.hass.loop.call_soon_threadsafe(self.async_write_ha_state)
132+
def _handle_availability_changed(self, event) -> None:
133+
"""Handle availability change events."""
134+
if event.data.get(AVAIL_EVENT_KEY_ENTRY_ID) == self._entry.entry_id:
135+
self._attr_available = event.data.get(AVAIL_EVENT_KEY_AVAIL, False)
136+
self.hass.loop.call_soon_threadsafe(self.async_write_ha_state)
143137

144138
class MiKettleProHeatTemperatureNumber(MiKettleProBaseNumber):
145139
"""Representation of a Mi Kettle Pro heat temperature number entity."""

custom_components/mi_kettle_pro/sensor.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,5 @@ def _handle_status_update(self, status_data: dict) -> None:
174174
"""Handle status updates from Bluetooth manager."""
175175
if status_data:
176176
action = status_data.get(self._status_key, "unknown")
177-
if action != "idle":
178-
self._attr_native_value = True
177+
self._attr_native_value = True if action != "idle" else False
179178
self.hass.loop.call_soon_threadsafe(self.async_write_ha_state)

0 commit comments

Comments
 (0)