diff --git a/custom_components/xiaomi_home/notify.py b/custom_components/xiaomi_home/notify.py index e07a146..9b7f238 100644 --- a/custom_components/xiaomi_home/notify.py +++ b/custom_components/xiaomi_home/notify.py @@ -47,7 +47,7 @@ Notify entities for Xiaomi Home. """ from __future__ import annotations import logging -from typing import Optional +from typing import Any, Optional from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant @@ -83,6 +83,7 @@ async def async_setup_entry( class Notify(MIoTActionEntity, NotifyEntity): """Notify entities for Xiaomi Home.""" + # pylint: disable=unused-argument def __init__(self, miot_device: MIoTDevice, spec: MIoTSpecAction) -> None: """Initialize the Notify.""" @@ -97,37 +98,66 @@ class Notify(MIoTActionEntity, NotifyEntity): self, message: str, title: Optional[str] = None ) -> None: """Send a message.""" - del title if not message: _LOGGER.error( 'action exec failed, %s(%s), empty action params', self.name, self.entity_id) return + in_list: Any = None try: - in_list: list = yaml.parse_yaml(message) + # YAML will convert yes, no, on, off, true, false to the bool type, + # and if it is a string, quotation marks need to be added. + in_list = yaml.parse_yaml(content=message) except HomeAssistantError: _LOGGER.error( 'action exec failed, %s(%s), invalid action params format, %s', self.name, self.entity_id, message) return - - if not isinstance(in_list, list): + if len(self.spec.in_) == 1 and not isinstance(in_list, list): in_list = [in_list] - if not isinstance(in_list, list) or len(in_list) != len(self.spec.in_): _LOGGER.error( 'action exec failed, %s(%s), invalid action params, %s', self.name, self.entity_id, message) return - in_value: list[dict] = [] for index, prop in enumerate(self.spec.in_): - if type(in_list[index]).__name__ != prop.format_: - _LOGGER.error( - 'action exec failed, %s(%s), invalid params item, ' - 'which item(%s) in the list must be %s, %s', - self.name, self.entity_id, prop.description_trans, - prop.format_, message) - return - in_value.append({'piid': prop.iid, 'value': in_list[index]}) - return await self.action_async(in_list=in_value) + if ( + prop.format_ == 'str' + and isinstance(in_list[index], (bool, int, float, str)) + ): + in_value.append( + {'piid': prop.iid, 'value': str(in_list[index])}) + continue + if ( + prop.format_ == 'bool' + and isinstance(in_list[index], (bool, int)) + ): + # yes, no, on, off, true, false and other bool types will also + # be parsed as 0 and 1 of int. + in_value.append( + {'piid': prop.iid, 'value': bool(in_list[index])}) + continue + if ( + prop.format_ == 'float' + and isinstance(in_list[index], (int, float)) + ): + in_value.append( + {'piid': prop.iid, 'value': in_list[index]}) + continue + if ( + prop.format_ == 'int' + and isinstance(in_list[index], int) + ): + in_value.append( + {'piid': prop.iid, 'value': in_list[index]}) + continue + # Invalid params type, raise error. + _LOGGER.error( + 'action exec failed, %s(%s), invalid params item, ' + 'which item(%s) in the list must be %s, %s type was %s, %s', + self.name, self.entity_id, prop.description_trans, + prop.format_, in_list[index], type( + in_list[index]).__name__, message) + return + await self.action_async(in_list=in_value) diff --git a/custom_components/xiaomi_home/text.py b/custom_components/xiaomi_home/text.py index ad32a1c..0687f50 100644 --- a/custom_components/xiaomi_home/text.py +++ b/custom_components/xiaomi_home/text.py @@ -47,7 +47,7 @@ Text entities for Xiaomi Home. """ from __future__ import annotations import logging -from typing import Optional +from typing import Any, Optional from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant @@ -120,9 +120,9 @@ class ActionText(MIoTActionEntity, TextEntity): async def async_set_value(self, value: str) -> None: if not value: return - in_list: list = None + in_list: Any = None try: - in_list = yaml.parse_yaml(value) + in_list = yaml.parse_yaml(content=value) except HomeAssistantError as e: _LOGGER.error( 'action exec failed, %s(%s), invalid action params format, %s', @@ -130,10 +130,8 @@ class ActionText(MIoTActionEntity, TextEntity): raise ValueError( f'action exec failed, {self.name}({self.entity_id}), ' f'invalid action params format, {value}') from e - - if not isinstance(in_list, list): + if len(self.spec.in_) == 1 and not isinstance(in_list, list): in_list = [in_list] - if not isinstance(in_list, list) or len(in_list) != len(self.spec.in_): _LOGGER.error( 'action exec failed, %s(%s), invalid action params, %s', @@ -143,16 +141,48 @@ class ActionText(MIoTActionEntity, TextEntity): f'invalid action params, {value}') in_value: list[dict] = [] for index, prop in enumerate(self.spec.in_): - if type(in_list[index]).__name__ != prop.format_: - logging.error( - 'action exec failed, %s(%s), invalid params item, which ' - 'item(%s) in the list must be %s, %s', self.name, - self.entity_id, prop.description_trans, prop.format_, value) - raise ValueError( - f'action exec failed, {self.name}({self.entity_id}), ' - f'invalid params item, which item({prop.description_trans})' - f' in the list must be {prop.format_}, {value}') - in_value.append({'piid': prop.iid, 'value': in_list[index]}) + if ( + prop.format_ == 'str' + and isinstance(in_list[index], (bool, int, float, str)) + ): + in_value.append( + {'piid': prop.iid, 'value': str(in_list[index])}) + continue + if ( + prop.format_ == 'bool' + and isinstance(in_list[index], (bool, int)) + ): + # yes, no, on, off, true, false and other bool types will also + # be parsed as 0 and 1 of int. + in_value.append( + {'piid': prop.iid, 'value': bool(in_list[index])}) + continue + if ( + prop.format_ == 'float' + and isinstance(in_list[index], (int, float)) + ): + in_value.append( + {'piid': prop.iid, 'value': in_list[index]}) + continue + if ( + prop.format_ == 'int' + and isinstance(in_list[index], int) + ): + in_value.append( + {'piid': prop.iid, 'value': in_list[index]}) + continue + # Invalid params type, raise error. + _LOGGER.error( + 'action exec failed, %s(%s), invalid params item, ' + 'which item(%s) in the list must be %s, %s type was %s, %s', + self.name, self.entity_id, prop.description_trans, + prop.format_, in_list[index], type( + in_list[index]).__name__, value) + raise ValueError( + f'action exec failed, {self.name}({self.entity_id}), ' + f'invalid params item, which item({prop.description_trans}) ' + f'in the list must be {prop.format_}, {in_list[index]} type ' + f'was {type(in_list[index]).__name__}, {value}') self._attr_native_value = value if await self.action_async(in_list=in_value):