Skip to content

Commit

Permalink
♻️ improve for entity state
Browse files Browse the repository at this point in the history
  • Loading branch information
al-one committed Dec 13, 2024
1 parent 4371fa5 commit f89d76f
Show file tree
Hide file tree
Showing 19 changed files with 82 additions and 77 deletions.
4 changes: 2 additions & 2 deletions custom_components/xiaomi_miot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ def parent_entity(self):

@property
def parent_attributes(self):
return self._parent.state_attrs or {}
return self.device.props or {}

@property
def extra_state_attributes(self):
Expand Down Expand Up @@ -1606,7 +1606,7 @@ def update_with_properties(self):
prop = self._miot_service.get_property(p) or self._miot_service.spec.get_property(p)
if not prop:
continue
val = prop.from_dict(self.parent_attributes)
val = prop.from_device(self.device)
if not prop.range_valid(val):
val = None
self._extra_attrs[prop.name] = val
Expand Down
4 changes: 2 additions & 2 deletions custom_components/xiaomi_miot/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ async def async_update(self):
def update_state(self):
sta = None
if self._prop_mode:
val = self._prop_mode.from_dict(self._state_attrs)
val = self._prop_mode.from_device(self.device)
des = self._prop_mode.list_description(val) if val is not None else None
if des is not None:
des = f'{des}'.lower()
Expand All @@ -89,7 +89,7 @@ def update_state(self):
elif 'sleep' in des:
sta = AlarmControlPanelState.ARMED_NIGHT
if self._is_mgl03:
if val := self._state_attrs.get('arming.alarm'):
if self.device.props.get('arming.alarm'):
sta = AlarmControlPanelState.TRIGGERED
if hasattr(self, '_attr_alarm_state'):
self._attr_alarm_state = sta
Expand Down
2 changes: 1 addition & 1 deletion custom_components/xiaomi_miot/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ async def async_added_to_hass(self):
def is_on(self):
ret = self._state
if self._prop_state:
val = self._prop_state.from_dict(self._state_attrs)
val = self._prop_state.from_device(self.device)
if val is None:
pass
elif self._prop_state.name in ['no_motion_duration', 'nobody_time']:
Expand Down
4 changes: 2 additions & 2 deletions custom_components/xiaomi_miot/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ async def async_update(self):
@property
def is_on(self):
if self._prop_power:
return self._state_attrs.get(self._prop_power.full_name) and True
return self._prop_power.from_device(self.device) and True
return True

async def stream_source(self, **kwargs):
Expand Down Expand Up @@ -553,7 +553,7 @@ def get_motion_image_address(self, **kwargs):
@property
def motion_detection_enabled(self):
if self._prop_motion_tracking:
return self._prop_motion_tracking.from_dict(self._state_attrs)
return self._prop_motion_tracking.from_device(self.device)
return None

def enable_motion_detection(self):
Expand Down
34 changes: 17 additions & 17 deletions custom_components/xiaomi_miot/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,21 +268,21 @@ async def async_update(self):
def is_on(self):
ret = None
if self._prop_power and not ret:
ret = self._prop_power.from_dict(self._state_attrs) and True
ret = self._prop_power.from_device(self.device) and True
if self._prop_fan_power and not ret:
ret = self._prop_fan_power.from_dict(self._state_attrs) and True
ret = self._prop_fan_power.from_device(self.device) and True
if ret is not None:
return ret
for m in self._power_modes:
p = self._miot_service.bool_property(m)
if not p:
continue
if self._state_attrs.get(p.full_name):
if p.from_device(self.device):
return True
if self._prop_mode:
off = self._hvac_modes.get(HVACMode.OFF, {}).get('value')
if off is not None:
return off != self._prop_mode.from_dict(self._state_attrs)
return off != self._prop_mode.from_device(self.device)
power = self._state_attrs.get('power')
if power is not None:
return not not power
Expand Down Expand Up @@ -347,7 +347,7 @@ def turn_off(self, **kwargs):
def state(self):
sta = self.hvac_mode
if sta is None and self._prop_mode:
val = self._prop_mode.from_dict(self._state_attrs)
val = self._prop_mode.from_device(self.device)
if val is not None:
sta = self._prop_mode.list_description(val)
if sta:
Expand All @@ -359,7 +359,7 @@ def hvac_mode(self):
if not self.is_on:
return HVACMode.OFF
if self._prop_mode:
acm = self._prop_mode.from_dict(self._state_attrs)
acm = self._prop_mode.from_device(self.device)
try:
acm = -1 if acm is None else int(acm or 0)
except TypeError:
Expand Down Expand Up @@ -411,7 +411,7 @@ def preset_mode(self):
if not self.is_on:
return HVACMode.OFF
if self._preset_modes and self._prop_mode:
acm = self._prop_mode.from_dict(self._state_attrs)
acm = self._prop_mode.from_device(self.device)
acm = -1 if acm is None else acm
return self._preset_modes.get(acm)
return None
Expand Down Expand Up @@ -471,7 +471,7 @@ def current_temperature(self):
if ATTR_CURRENT_TEMPERATURE in self._state_attrs:
return float(self._state_attrs[ATTR_CURRENT_TEMPERATURE] or 0)
if self._prop_temperature:
return float(self._prop_temperature.from_dict(self._state_attrs) or 0)
return float(self._prop_temperature.from_device(self.device) or 0)
return None

@property
Expand All @@ -489,7 +489,7 @@ def max_temp(self):
@property
def target_temperature(self):
if self._prop_target_temp:
val = float(self._prop_target_temp.from_dict(self._state_attrs) or 0)
val = float(self._prop_target_temp.from_device(self.device) or 0)
if val:
self._prev_target_temp = val
elif self._prev_target_temp:
Expand Down Expand Up @@ -534,13 +534,13 @@ def current_humidity(self):
if ATTR_CURRENT_HUMIDITY in self._state_attrs:
return float(self._state_attrs[ATTR_CURRENT_HUMIDITY] or 0)
if self._prop_humidity:
return int(self._prop_humidity.from_dict(self._state_attrs) or 0)
return int(self._prop_humidity.from_device(self.device) or 0)
return None

@property
def target_humidity(self):
if self._prop_target_humi:
return int(self._prop_target_humi.from_dict(self._state_attrs) or 0)
return int(self._prop_target_humi.from_device(self.device) or 0)
return None

@property
Expand All @@ -564,7 +564,7 @@ def set_humidity(self, humidity):
def fan_mode(self):
des = None
if self._prop_fan_level:
val = self._prop_fan_level.from_dict(self._state_attrs)
val = self._prop_fan_level.from_device(self.device)
if val is not None:
des = self._prop_fan_level.list_description(val)
if des is not None:
Expand Down Expand Up @@ -593,9 +593,9 @@ def swing_mode(self):
val = 0
pvs = self._prop_vertical_swing
phs = self._prop_horizontal_swing
if pvs and pvs.from_dict(self._state_attrs, False):
if pvs and pvs.from_device(self.device, False):
val |= 1
if phs and phs.from_dict(self._state_attrs, False):
if phs and phs.from_device(self.device, False):
val |= 2
return SwingModes(val).name

Expand Down Expand Up @@ -634,7 +634,7 @@ def set_swing_mode(self, swing_mode: str):
if self._prop_horizontal_swing:
swm[self._prop_horizontal_swing.full_name] = hor
for mk, mv in swm.items():
old = self._state_attrs.get(mk, None)
old = self.device.props.get(mk, None)
if old is None or mv is None:
continue
if mv == old:
Expand All @@ -646,7 +646,7 @@ def set_swing_mode(self, swing_mode: str):
def is_aux_heat(self):
"""Return true if aux heater."""
if self._prop_heater:
return self._prop_heater.from_dict(self._state_attrs) and self.hvac_mode in [
return self._prop_heater.from_device(self.device) and self.hvac_mode in [
HVACMode.AUTO,
HVACMode.HEAT,
HVACMode.HEAT_COOL,
Expand Down Expand Up @@ -714,7 +714,7 @@ def turn_off(self, **kwargs):
@property
def preset_mode(self):
if self._prop_speed:
val = self._prop_speed.from_dict(self._state_attrs)
val = self._prop_speed.from_device(self.device)
if val is not None:
return self._prop_speed.list_description(val)
return self._parent.fan_mode
Expand Down
6 changes: 3 additions & 3 deletions custom_components/xiaomi_miot/core/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,9 @@ async def _update():
continue
if not isinstance(entity, BasicEntity):
continue
if not hasattr(entity, 'async_update'):
if not hasattr(entity, 'async_update_from_device'):
continue
await entity.async_update()
await entity.async_update_from_device()
return result
return _update

Expand Down Expand Up @@ -610,7 +610,7 @@ async def async_write(self, payload: dict):
method = data.get('method')

if method == 'update_status':
result = await self.update_miot_status()
result = await self.update_main_status()

if method == 'set_properties':
params = data.get('params', [])
Expand Down
4 changes: 4 additions & 0 deletions custom_components/xiaomi_miot/core/miot_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,10 @@ def translation_keys(self):
def from_dict(self, dat: dict, default=None):
return dat.get(self.full_name, default)

def from_device(self, device, default=None):
props = getattr(device, 'props', {}) if device else {}
return self.from_dict(props, default)

def description_to_dict(self, dat: dict):
if not self.value_list:
return None
Expand Down
14 changes: 7 additions & 7 deletions custom_components/xiaomi_miot/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ async def async_update(self):
if not self._available:
return
if prop_reverse := self._miot_service.get_property('motor_reverse'):
if prop_reverse.from_dict(self._state_attrs):
if prop_reverse.from_device(self.device):
if self.custom_config_bool('auto_position_reverse'):
self._position_reverse = True

Expand All @@ -121,7 +121,7 @@ def current_cover_position(self):
pos = -1
if self._prop_current_position:
try:
cur = round(self._prop_current_position.from_dict(self._state_attrs), 2)
cur = round(self._prop_current_position.from_device(self.device), 2)
except (TypeError, ValueError):
cur = None
if cur is None:
Expand Down Expand Up @@ -149,7 +149,7 @@ def current_cover_position(self):
if pos < 0:
# If the motor controller is stopped, generate fake middle position
if self._prop_status:
sta = int(self._prop_status.from_dict(self._state_attrs) or -1)
sta = int(self._prop_status.from_device(self.device) or -1)
if sta in self._prop_status.list_search('Stopped'):
return 50
return None
Expand All @@ -167,7 +167,7 @@ def target_cover_position(self):
pos = None
if not self._prop_target_position:
return pos
pos = self._prop_target_position.from_dict(self._state_attrs)
pos = self._prop_target_position.from_device(self.device)
if pos is None:
return pos
pos = int(pos)
Expand Down Expand Up @@ -199,7 +199,7 @@ def is_closed(self):
pos = self.custom_config_number('closed_position', 1)
return cur <= pos
if self._prop_status:
sta = int(self._prop_status.from_dict(self._state_attrs) or -1)
sta = int(self._prop_status.from_device(self.device) or -1)
cvs = self.custom_config_list('closed_status') or []
if cvs:
return sta in cvs or f'{sta}' in cvs
Expand All @@ -209,14 +209,14 @@ def is_closed(self):
def is_closing(self):
if not self._prop_status:
return None
sta = int(self._prop_status.from_dict(self._state_attrs) or -1)
sta = int(self._prop_status.from_device(self.device) or -1)
return sta in self._prop_status.list_search(*self._close_texts)

@property
def is_opening(self):
if not self._prop_status:
return None
sta = int(self._prop_status.from_dict(self._state_attrs) or -1)
sta = int(self._prop_status.from_device(self.device) or -1)
return sta in self._prop_status.list_search(*self._open_texts)

def motor_control(self, open_cover=True, **kwargs):
Expand Down
8 changes: 4 additions & 4 deletions custom_components/xiaomi_miot/device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ async def async_update(self):
return

if prop := self._miot_service.get_property('latitude'):
self._attr_latitude = prop.from_dict(self._state_attrs)
self._attr_latitude = prop.from_device(self.device)
if prop := self._miot_service.get_property('longitude'):
self._attr_longitude = prop.from_dict(self._state_attrs)
self._attr_longitude = prop.from_device(self.device)
if prop := self._miot_service.get_property('current_address'):
self._attr_location_name = prop.from_dict(self._state_attrs)
self._attr_location_name = prop.from_device(self.device)
await self.transform_coord()

async def transform_coord(self, default=None):
Expand Down Expand Up @@ -174,7 +174,7 @@ def battery_level(self):
for srv in sls:
prop = srv.get_property('battery_level')
if prop:
return prop.from_dict(self._state_attrs)
return prop.from_device(self.device)
return None


Expand Down
12 changes: 6 additions & 6 deletions custom_components/xiaomi_miot/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def speed(self):
if not self.is_on:
return SPEED_OFF
if self._prop_speed:
spd = int(self._prop_speed.from_dict(self._state_attrs, 0))
spd = int(self._prop_speed.from_device(self.device, 0))
return self._prop_speed.list_description(spd)
return None

Expand Down Expand Up @@ -215,7 +215,7 @@ def speed_count(self):
def percentage(self):
"""Return the current speed as a percentage."""
if self._prop_percentage:
val = self._prop_percentage.from_dict(self._state_attrs)
val = self._prop_percentage.from_device(self.device)
if val is not None:
return val
lst = [v for v in self.speed_list if v not in OFF_SPEED_VALUES]
Expand All @@ -241,7 +241,7 @@ def set_percentage(self, percentage: int):
def preset_mode(self):
"""Return the current preset mode, e.g., auto, smart, interval, favorite."""
if self._prop_mode:
val = self._prop_mode.from_dict(self._state_attrs)
val = self._prop_mode.from_device(self.device)
if val is not None:
return self._prop_mode.list_description(val)
return None
Expand Down Expand Up @@ -504,7 +504,7 @@ def update(self, data=None):
@property
def is_on(self):
if self._prop_power:
return self._prop_power.from_dict(self._state_attrs) and True
return self._prop_power.from_device(self.device) and True
if self._parent.is_on is False:
return False
sta = self._state_attrs.get(self._attr)
Expand Down Expand Up @@ -554,7 +554,7 @@ def set_speed(self, speed: str):
def percentage(self):
"""Return the current speed as a percentage."""
if self._miot_property.value_range:
val = self._miot_property.from_dict(self._state_attrs)
val = self._miot_property.from_device(self.device)
if val is not None:
return round(val / self._miot_property.range_max() * 100, 2)
return super().percentage
Expand All @@ -578,7 +578,7 @@ def set_percentage(self, percentage: int):

@property
def preset_mode(self):
val = self._miot_property.from_dict(self._state_attrs)
val = self._miot_property.from_device(self.device)
if val is not None:
return self._miot_property.list_description(val)
return None
Expand Down
6 changes: 3 additions & 3 deletions custom_components/xiaomi_miot/humidifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ async def async_update(self):
return

if self._prop_humidity:
self._attr_current_humidity = int(self._prop_humidity.from_dict(self._state_attrs) or 0)
self._attr_current_humidity = int(self._prop_humidity.from_device(self.device) or 0)

if self._prop_target_humi:
num = int(self._prop_target_humi.from_dict(self._state_attrs) or 0)
num = int(self._prop_target_humi.from_device(self.device) or 0)
if fac := self._vars.get('target_humidity_ratio'):
num = round(num * fac)
self._attr_target_humidity = num
Expand Down Expand Up @@ -160,7 +160,7 @@ def mode(self):
return MODE_OFF
if not self._prop_mode:
return None
val = self._prop_mode.from_dict(self._state_attrs)
val = self._prop_mode.from_device(self.device)
if val is None:
return None
return self._prop_mode.list_description(val)
Expand Down
Loading

0 comments on commit f89d76f

Please sign in to comment.