platypush/platypush/plugins/switchbot/_setters.py

158 lines
4.2 KiB
Python

# pylint: disable=too-few-public-methods
from abc import ABC, abstractmethod
from typing import Any, Dict, Optional, Type
from platypush.context import get_plugin
from platypush.entities import Entity
from ._constants import DeviceType
class EntitySetter(ABC):
"""
Base class for entity setters.
The purpose of entity setters is to map property/values passed to
:meth:`platypush.plugins.switchbot.SwitchbotPlugin.set_value` to native
Switchbot device commands.
"""
def __init__(self, entity: Entity):
self.entity = entity
self.device_id, self.property = self._plugin._split_device_id_and_property(
self.entity.id
)
@abstractmethod
def _set(
self,
value: Any,
*args: Any,
property: Optional[str] = None, # pylint: disable=redefined-builtin
**kwargs: Any,
):
raise NotImplementedError()
def __call__(
self,
value: Any,
*args: Any,
property: Optional[str] = None, # pylint: disable=redefined-builtin
**kwargs: Any,
):
return self._set(value, *args, property=property, **kwargs)
@property
def _plugin(self):
return get_plugin('switchbot')
class EntitySetterWithBinaryState(EntitySetter):
"""
Base setter for entities with a binary on/off state.
"""
def _set(
self,
value: Any,
*_: Any,
property: Optional[str] = None, # pylint: disable=redefined-builtin
**__: Any,
):
if property == 'state':
action = self._plugin.on if value else self._plugin.off
return action(self.device_id)
return None
class EntitySetterWithValueAsMethod(EntitySetter):
"""
This mapper maps the value passed to
:meth:`platypush.plugins.switchbot.SwitchbotPlugin.set_value` to plugin
actions.
In this case, the action value has a 1-1 mapping with the name of the
associated plugin action.
"""
def _set(self, value: Any, *_: Any, **__: Any):
method = getattr(self._plugin, value, None)
assert (
method
), f'No such action available for device "{self.device_id}": "{value}"'
return method(self.device_id)
class CurtainEntitySetter(EntitySetter):
"""
Curtain entity setter.
"""
def _set(self, value: Any, *_: Any, **__: Any):
return self._plugin.set_curtain_position(self.device_id, int(value))
class HumidifierEntitySetter(EntitySetterWithBinaryState):
"""
Humidifier entity setter.
"""
def _set(
self,
value: Any,
*args: Any,
property: Optional[str] = None, # pylint: disable=redefined-builtin
**kwargs: Any,
):
if property == 'state':
return super()._set(value, *args, property=property, **kwargs)
if property == 'child_lock':
action = self._plugin.lock if value else self._plugin.unlock
return action(self.device_id)
if property in {'auto', 'nebulization_efficiency'}:
return self._plugin.set_humidifier_efficiency(self.device_id, value)
return None
class PlugEntitySetter(EntitySetterWithBinaryState):
"""
Plug entity setter.
"""
class LightEntitySetter(EntitySetter):
"""
Light entity setter.
"""
def _set(
self,
value: Any,
*_: Any,
property: Optional[str] = None, # pylint: disable=redefined-builtin
**__: Any,
):
assert property, 'No light property specified'
return self._plugin.set_curtain_position(self.device_id, int(value))
# A static map of device types -> entity setters functors.
entity_setters: Dict[DeviceType, Type[EntitySetter]] = {
DeviceType.BOT: EntitySetterWithValueAsMethod,
DeviceType.CEILING_LIGHT: LightEntitySetter,
DeviceType.CEILING_LIGHT_PRO: LightEntitySetter,
DeviceType.COLOR_BULB: LightEntitySetter,
DeviceType.CURTAIN: CurtainEntitySetter,
DeviceType.HUMIDIFIER: HumidifierEntitySetter,
DeviceType.LOCK: EntitySetterWithValueAsMethod,
DeviceType.PLUG: PlugEntitySetter,
DeviceType.PLUG_MINI_US: PlugEntitySetter,
DeviceType.PLUG_MINI_JP: PlugEntitySetter,
DeviceType.STRIP_LIGHT: LightEntitySetter,
}