Skip to content

Commit

Permalink
Merge branch 'refs/heads/master' into async-cloud
Browse files Browse the repository at this point in the history
# Conflicts:
#	custom_components/xiaomi_miot/__init__.py
  • Loading branch information
al-one committed May 17, 2024
2 parents 552953d + 3238b6f commit 3452a22
Show file tree
Hide file tree
Showing 23 changed files with 540 additions and 261 deletions.
17 changes: 3 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ This component has added support for configuration reloading (to avoid having to
- 🚰 [water-purifier](https://home.miot-spec.com/s/waterpuri) / [kettle](https://home.miot-spec.com/s/kettle)
- ♻️ [air-purifier](https://home.miot-spec.com/s/airpurifier) / [air-fresh](https://home.miot-spec.com/s/airfresh) / [hood](https://home.miot-spec.com/s/hood)
- 🌡 [temperature-humidity-sensor](https://home.miot-spec.com/s/sensor_ht) / [submersion-sensor](https://home.miot-spec.com/s/flood) / [smoke-sensor](https://home.miot-spec.com/s/sensor_smoke)
- 🥘 [cooker](https://home.miot-spec.com/s/cooker) / [pressure-cooker](https://home.miot-spec.com/s/pre_cooker)
- 🥘 [cooker](https://home.miot-spec.com/s/cooker) / [pressure-cooker](https://home.miot-spec.com/s/pre_cooker) / [electric-steamer](https://home.miot-spec.com/s/esteamer)
- 🍲 [induction-cooker](https://home.miot-spec.com/s/ihcooker) / [oven](https://home.miot-spec.com/s/oven) / [microwave](https://home.miot-spec.com/s/microwave)
- 🍗 [air-fryer](https://home.miot-spec.com/s/fryer) / [multifunction-cooking-pot](https://home.miot-spec.com/s/mfcp)
- 🍵 [health-pot](https://home.miot-spec.com/s/health_pot) / ☕️ [coffee-machine](https://home.miot-spec.com/s/coffee)
Expand Down Expand Up @@ -238,6 +238,8 @@ This component has added support for configuration reloading (to avoid having to

## Services

> Since the HA support service response has been for some time, this component no longer triggers events starting from v0.7.18.

#### [`xiaomi_miot.set_property`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.set_property)
```yaml
service: xiaomi_miot.set_property
Expand Down Expand Up @@ -268,11 +270,8 @@ data:
- siid: 3
piid: 2
update_entity: true # Update to entity state attributes
throw: true # Throw result to HA notifications
```

> With [event](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.got_miot_properties`

#### [`xiaomi_miot.call_action`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.call_action)
```yaml
service: xiaomi_miot.call_action
Expand All @@ -283,11 +282,8 @@ data:
params:
- 18 # piid: 1 - work-mode
- '{"selects":[[7,1,0,2,1]]}' # piid: 10 - clean-extend-data
throw: true # throw result to HA notifications
```

> With [event](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.call_miot_action`

#### [`xiaomi_miot.send_command`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.send_command)
```yaml
service: xiaomi_miot.send_command
Expand All @@ -296,11 +292,8 @@ data:
method: set_power
params:
- on
throw: true # throw result to HA notifications
```

> With [event](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.send_miio_command`

#### [`xiaomi_miot.get_token`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.get_token)
```yaml
service: xiaomi_miot.get_token
Expand Down Expand Up @@ -332,8 +325,6 @@ data:
username: 80001234 # Xiaomi Account ID / Email / Phone
```

> With [event](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.renew_devices`

#### [`xiaomi_miot.request_xiaomi_api`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.request_xiaomi_api)
```yaml
service: xiaomi_miot.request_xiaomi_api
Expand All @@ -347,8 +338,6 @@ data:
- model: brand.device.model
```

> With [event](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.request_xiaomi_api`

> [More services](https://github.com/al-one/hass-xiaomi-miot/blob/master/custom_components/xiaomi_miot/services.yaml)


Expand Down
17 changes: 3 additions & 14 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ xiaomi_miot:
- 🚰 [净水器](https://home.miot-spec.com/s/waterpuri) / [饮水机](https://home.miot-spec.com/s/kettle)
- ♻️ [空气净化器](https://home.miot-spec.com/s/airpurifier) / [新风机](https://home.miot-spec.com/s/airfresh) / [油烟机](https://home.miot-spec.com/s/hood)
- 🌡 [温湿度传感器](https://home.miot-spec.com/s/sensor_ht) / [水侵传感器](https://home.miot-spec.com/s/flood) / [烟雾传感器](https://home.miot-spec.com/s/sensor_smoke)
- 🥘 [电饭煲](https://home.miot-spec.com/s/cooker) / [压力锅](https://home.miot-spec.com/s/pre_cooker)
- 🥘 [电饭煲](https://home.miot-spec.com/s/cooker) / [压力锅](https://home.miot-spec.com/s/pre_cooker) / [电蒸锅](https://home.miot-spec.com/s/esteamer)
- 🍲 [电磁炉](https://home.miot-spec.com/s/ihcooker) / [烤箱](https://home.miot-spec.com/s/oven) / [微波炉](https://home.miot-spec.com/s/microwave)
- 🍗 [空气炸锅](https://home.miot-spec.com/s/fryer) / [多功能锅](https://home.miot-spec.com/s/mfcp)
- 🍵 [养生壶](https://home.miot-spec.com/s/health_pot) / ☕️ [咖啡机](https://home.miot-spec.com/s/coffee)
Expand Down Expand Up @@ -275,6 +275,8 @@ xiaomi_miot:
<a name="services"></a>
## 服务

> 由于HA支持服务响应已经有一段时间了,本组件自v0.7.18开始不再触发事件。

#### [`xiaomi_miot.set_property`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.set_property)
```yaml
service: xiaomi_miot.set_property
Expand Down Expand Up @@ -305,11 +307,8 @@ data:
- siid: 3
piid: 2
update_entity: true # 更新实体状态属性
throw: true # 在HA通知中显示结果
```

> 触发[事件](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.got_miot_properties`

#### [`xiaomi_miot.call_action`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.call_action)
```yaml
service: xiaomi_miot.call_action
Expand All @@ -320,11 +319,8 @@ data:
params:
- 18 # piid: 1 - work-mode
- '{"selects":[[7,1,0,2,1]]}' # piid: 10 - clean-extend-data
throw: true # 在HA通知中显示结果
```

> 触发[事件](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.call_miot_action`

#### [`xiaomi_miot.send_command`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.send_command)
```yaml
service: xiaomi_miot.send_command
Expand All @@ -333,11 +329,8 @@ data:
method: set_power
params:
- on
throw: true # 在HA通知中显示结果
```

> 触发[事件](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.send_miio_command`

#### [`xiaomi_miot.get_token`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.get_token)
```yaml
service: xiaomi_miot.get_token
Expand Down Expand Up @@ -369,8 +362,6 @@ data:
username: 80001234 # 小米账号ID/登录邮箱/手机号
```

> 触发[事件](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.renew_devices`

#### [`xiaomi_miot.request_xiaomi_api`](https://my.home-assistant.io/redirect/developer_call_service/?service=xiaomi_miot.request_xiaomi_api)
```yaml
service: xiaomi_miot.request_xiaomi_api
Expand All @@ -384,8 +375,6 @@ data:
- model: brand.device.model
```

> 触发[事件](https://my.home-assistant.io/redirect/developer_events/) `xiaomi_miot.request_xiaomi_api`

> 查看[更多服务](https://github.com/al-one/hass-xiaomi-miot/blob/master/custom_components/xiaomi_miot/services.yaml)


Expand Down
114 changes: 14 additions & 100 deletions custom_components/xiaomi_miot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.helpers.reload import async_integration_yaml_config
from homeassistant.helpers.service import async_register_admin_service
import homeassistant.helpers.device_registry as dr
import homeassistant.helpers.config_validation as cv

Expand Down Expand Up @@ -96,7 +97,7 @@
{
vol.Required('method'): cv.string,
vol.Optional('params', default=[]): cv.ensure_list,
vol.Optional('throw', default=False): cv.boolean,
vol.Optional('throw', default=False): cv.boolean, # Deprecated
vol.Optional('return_result', default=True): cv.boolean,
},
),
Expand Down Expand Up @@ -519,10 +520,6 @@ async def async_get_token(call) -> ServiceResponse:
cnt += 1
if not lst:
lst = [f'Not Found "{nam}" in {cnt} devices.']
msg = '\n\n'.join(map(lambda vv: f'{vv}', lst))
persistent_notification.async_create(
hass, msg, 'Miot device', f'{DOMAIN}-debug',
)
return {
'list': lst,
}
Expand All @@ -545,11 +542,6 @@ async def async_renew_devices(call):
continue
dvs = await cld.async_renew_devices()
cnt = len(dvs)
hass.bus.async_fire(f'{DOMAIN}.renew_devices', {
CONF_USERNAME: cld.username,
'user_id': cld.user_id,
'device_count': cnt,
})
_LOGGER.info('Renew xiaomi devices for %s. Got %s devices.', cld.username, cnt)
return True

Expand All @@ -572,7 +564,8 @@ async def _handle_reload_config(service):
]
await asyncio.gather(*reload_tasks)

hass.helpers.service.async_register_admin_service(
async_register_admin_service(
hass,
DOMAIN,
SERVICE_RELOAD,
_handle_reload_config,
Expand Down Expand Up @@ -1014,19 +1007,6 @@ def send_miio_command(self, method, params=None, **kwargs):
except DeviceException as ex:
self.logger.error('%s: Send miio command: %s(%s) failed: %s', self.name_model, method, params, ex)
return False
self.hass.bus.async_fire(f'{DOMAIN}.send_miio_command', {
ATTR_ENTITY_ID: self.entity_id,
'method': method,
'params': params,
'result': result,
})
if kwargs.get('throw'):
persistent_notification.create(
self.hass,
f'{result}',
'Miio command result',
f'{DOMAIN}-debug',
)
ret = result == self._success_result
if kwargs.get('return_result'):
return result
Expand Down Expand Up @@ -1825,24 +1805,11 @@ async def async_get_properties(self, mapping, update_entity=False, throw=False,
return
result = MiotResults(results, mapping)
attrs = result.to_attributes(self._state_attrs)
self.hass.bus.async_fire(f'{DOMAIN}.got_miot_properties', {
ATTR_ENTITY_ID: self.entity_id,
'mapping': mapping,
'attrs': attrs,
'result': results,
})
self.logger.info('%s: Get miot properties: %s', self.name_model, results)

if attrs and update_entity:
await self.async_update_attrs(attrs, update_subs=True)
self.async_write_ha_state()
if throw:
persistent_notification.create(
self.hass,
f'{results}',
'Miot properties',
f'{DOMAIN}-debug',
)
self.schedule_update_ha_state()
return attrs

def set_property(self, field, value):
Expand Down Expand Up @@ -1925,14 +1892,7 @@ def set_miot_property(self, siid, piid, value, did=None, **kwargs):
pass
elif prop := srv.properties.get(piid):
self._state_attrs[prop.full_name] = value
self.async_write_ha_state()
if kwargs.get('throw'):
persistent_notification.create(
self.hass,
f'{ret.result}',
'Set miot property result',
f'{DOMAIN}-debug',
)
self.schedule_update_ha_state()
return ret

async def async_set_miot_property(self, siid, piid, value, did=None, **kwargs):
Expand Down Expand Up @@ -1966,6 +1926,8 @@ def miot_action(self, siid, aiid, params=None, did=None, **kwargs):
mca = self.miot_cloud_action
if self.custom_config_bool('auto_cloud') and not self._local_state:
mca = self.xiaomi_cloud
elif not self.miot_device:
mca = self.xiaomi_cloud
try:
if m2m and self._miio2miot.has_setter(siid, aiid=aiid):
result = self._miio2miot.call_action(self.miot_device, siid, aiid, params)
Expand All @@ -1984,27 +1946,12 @@ def miot_action(self, siid, aiid, params=None, did=None, **kwargs):
self.logger.warning('%s: Call miot action %s failed: %s, result: %s', self.name_model, pms, exc, result)
ret = eno == self._success_code
if ret:
self.hass.bus.async_fire(f'{DOMAIN}.call_miot_action', {
ATTR_ENTITY_ID: self.entity_id,
'did': did,
'siid': siid,
'aiid': aiid,
'params': params,
'result': result,
})
self._vars['delay_update'] = dly
self.logger.debug('%s: Call miot action %s, result: %s', self.name_model, pms, result)
else:
self._state_attrs['miot_action_error'] = MiotSpec.spec_error(eno)
self.logger.info('%s: Call miot action %s failed: %s', self.name_model, pms, result)
self._state_attrs['miot_action_result'] = result
if kwargs.get('throw'):
persistent_notification.create(
self.hass,
f'{result}',
'Miot action result',
f'{DOMAIN}-debug',
)
return result if ret else ret

async def async_miot_action(self, siid, aiid, params=None, did=None, **kwargs):
Expand Down Expand Up @@ -2172,36 +2119,16 @@ async def async_get_device_data(self, key, did=None, throw=False, **kwargs):
mic = self.xiaomi_cloud
if not isinstance(mic, MiotCloud):
return None
result = await self.hass.async_add_executor_job(
partial(mic.get_user_device_data, did, key, raw=True, **kwargs)
)
persistent_notification.async_create(
self.hass,
f'{result}',
f'Xiaomi device data: {self.name}',
f'{DOMAIN}-debug',
)
if throw:
raise Warning(f'Xiaomi device data for {self.name}: {result}')
else:
_LOGGER.debug('%s: Xiaomi device data: %s', self.name_model, result)
result = await self.async_get_user_device_data(did, key, raw=True, **kwargs)
_LOGGER.info('%s: Xiaomi device data: %s', self.name_model, result)
return result

async def async_get_bindkey(self, did=None, throw=False):
async def async_get_bindkey(self, did=None):
mic = self.xiaomi_cloud
if not isinstance(mic, MiotCloud):
return None
result = await mic.async_get_beaconkey(did or self.miot_did)
persistent_notification.async_create(
self.hass,
f'{result}',
f'Xiaomi device bindkey: {self.name}',
f'{DOMAIN}-debug',
)
if throw:
raise Warning(f'Xiaomi device bindkey for {self.name}: {result}')
else:
_LOGGER.warning('%s: Xiaomi device bindkey/beaconkey: %s', self.name_model, result)
_LOGGER.info('%s: Xiaomi device bindkey/beaconkey: %s', self.name_model, result)
return result

async def async_request_xiaomi_api(self, api, data=None, method='POST', crypt=True, **kwargs):
Expand All @@ -2214,19 +2141,6 @@ async def async_request_xiaomi_api(self, api, data=None, method='POST', crypt=Tr
pms = kwargs.pop('params', None)
dat = data or pms
result = await mic.async_request_api(api, data=dat, method=method, crypt=crypt, **kwargs)
self.hass.bus.async_fire(f'{DOMAIN}.request_xiaomi_api', {
ATTR_ENTITY_ID: self.entity_id,
'api': api,
'data': dat,
'result': result,
})
if kwargs.get('throw'):
persistent_notification.async_create(
self.hass,
f'{result}',
f'Xiaomi Api: {api}',
f'{DOMAIN}-debug',
)
_LOGGER.debug('Xiaomi Api %s: %s', api, result)
return result

Expand Down Expand Up @@ -2462,7 +2376,7 @@ async def async_added_to_hass(self):
def update_from_parent(self):
self.update()
if self.platform:
self.async_write_ha_state()
self.schedule_update_ha_state()

def update(self, data=None):
attrs = self.parent_attributes
Expand Down Expand Up @@ -2499,7 +2413,7 @@ def update_attrs(self, attrs: dict, update_parent=True):
getattr(self._parent, 'update_attrs')(attrs or {}, update_parent=False)
if self.hass and self.platform:
# don't set state before added to hass
self.async_write_ha_state()
self.schedule_update_ha_state()
return self._state_attrs

def call_parent(self, method, *args, **kwargs):
Expand Down
2 changes: 1 addition & 1 deletion custom_components/xiaomi_miot/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,5 @@ def press(self):
**self._press_kwargs,
}
if ret := self._press_action(**kws):
self.async_write_ha_state()
self.schedule_update_ha_state()
return ret
2 changes: 1 addition & 1 deletion custom_components/xiaomi_miot/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def get_stream_address(self, **kwargs):
self._url_expiration = now + 60 * 4.5
if self._prop_stream_address:
self._last_url = self._prop_stream_address.from_dict(odt)
self.async_write_ha_state()
self.schedule_update_ha_state()
self.async_check_stream_address(self._last_url)
if not kwargs.get('scheduled') or self.custom_config('keep_streaming'):
self._schedule_stream_refresh()
Expand Down
2 changes: 0 additions & 2 deletions custom_components/xiaomi_miot/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,6 @@ def __init__(self, config: dict, miot_service: MiotService):
self._supported_features |= ClimateEntityFeature.FAN_MODE
if self._prop_horizontal_swing or self._prop_vertical_swing:
self._supported_features |= ClimateEntityFeature.SWING_MODE
if self._prop_heater and miot_service.name in ['air_conditioner', 'air_condition_outlet']:
self._supported_features |= ClimateEntityFeature.AUX_HEAT

self._power_modes = []
if miot_service.get_property('heat_level'):
Expand Down
Loading

0 comments on commit 3452a22

Please sign in to comment.