Skip to content

Commit

Permalink
Add more helpers to miotdevice
Browse files Browse the repository at this point in the history
* rename old set_property to set_property_from_mapping
* add set_properties_from_dataclass (allows passing a mapping object with all wanted values at once)

```
device.set_properties_from_dataclass(GosundPlugStatus(state=True, some_other_property=123)
```

* new set_property helper which takes kwargs that are used automatically with the help of the class-given _MAPPING:

```
device.set_property(state=True)
```
  • Loading branch information
rytilahti committed Apr 18, 2020
1 parent 93fb155 commit 63d6dc0
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 12 deletions.
24 changes: 13 additions & 11 deletions miio/airpurifier_miot.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,12 @@ def status(self) -> AirPurifierMiotStatus:
@command(default_output=format_output("Powering on"))
def on(self):
"""Power on."""
return self.set_property(_MAPPING, "power", True)
return self.set_property_from_mapping(_MAPPING, "power", True)

@command(default_output=format_output("Powering off"))
def off(self):
"""Power off."""
return self.set_property(_MAPPING, "power", False)
return self.set_property_from_mapping(_MAPPING, "power", False)

@command(
click.argument("level", type=int),
Expand All @@ -309,7 +309,7 @@ def set_fan_level(self, level: int):
"""Set fan level."""
if level < 1 or level > 3:
raise AirPurifierMiotException("Invalid fan level: %s" % level)
return self.set_property(_MAPPING, "fan_level", level)
return self.set_property_from_mapping(_MAPPING, "fan_level", level)

@command(
click.argument("rpm", type=int),
Expand All @@ -323,7 +323,7 @@ def set_favorite_rpm(self, rpm: int):
"Invalid favorite motor speed: %s. Must be between 300 and 2300 and divisible by 10"
% rpm
)
return self.set_property(_MAPPING, "favorite_rpm", rpm)
return self.set_property_from_mapping(_MAPPING, "favorite_rpm", rpm)

@command(
click.argument("volume", type=int),
Expand All @@ -335,15 +335,15 @@ def set_volume(self, volume: int):
raise AirPurifierMiotException(
"Invalid volume: %s. Must be between 0 and 100" % volume
)
return self.set_property(_MAPPING, "buzzer_volume", volume)
return self.set_property_from_mapping(_MAPPING, "buzzer_volume", volume)

@command(
click.argument("mode", type=EnumType(OperationMode, False)),
default_output=format_output("Setting mode to '{mode.value}'"),
)
def set_mode(self, mode: OperationMode):
"""Set mode."""
return self.set_property(_MAPPING, "mode", mode.value)
return self.set_property_from_mapping(_MAPPING, "mode", mode.value)

@command(
click.argument("level", type=int),
Expand All @@ -356,15 +356,17 @@ def set_favorite_level(self, level: int):
if level < 0 or level > 14:
raise AirPurifierMiotException("Invalid favorite level: %s" % level)

return self.set_property(_MAPPING, "favorite_level", level)
return self.set_property_from_mapping(_MAPPING, "favorite_level", level)

@command(
click.argument("brightness", type=EnumType(LedBrightness, False)),
default_output=format_output("Setting LED brightness to {brightness}"),
)
def set_led_brightness(self, brightness: LedBrightness):
"""Set led brightness."""
return self.set_property(_MAPPING, "led_brightness", brightness.value)
return self.set_property_from_mapping(
_MAPPING, "led_brightness", brightness.value
)

@command(
click.argument("led", type=bool),
Expand All @@ -374,7 +376,7 @@ def set_led_brightness(self, brightness: LedBrightness):
)
def set_led(self, led: bool):
"""Turn led on/off."""
return self.set_property(_MAPPING, "led", led)
return self.set_property_from_mapping(_MAPPING, "led", led)

@command(
click.argument("buzzer", type=bool),
Expand All @@ -384,7 +386,7 @@ def set_led(self, led: bool):
)
def set_buzzer(self, buzzer: bool):
"""Set buzzer on/off."""
return self.set_property(_MAPPING, "buzzer", buzzer)
return self.set_property_from_mapping(_MAPPING, "buzzer", buzzer)

@command(
click.argument("lock", type=bool),
Expand All @@ -394,4 +396,4 @@ def set_buzzer(self, buzzer: bool):
)
def set_child_lock(self, lock: bool):
"""Set child lock on/off."""
return self.set_property(_MAPPING, "child_lock", lock)
return self.set_property_from_mapping(_MAPPING, "child_lock", lock)
50 changes: 49 additions & 1 deletion miio/miot_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,54 @@ def get_properties_for_dataclass(self, cls):

return cls(**response)

def set_property(self, **kwargs):
"""Helper to set properties using the device specific mapping."""
if getattr(self, "_MAPPING") is None:
raise DeviceException("Device class does not have _MAPPING")

return self.set_properties_from_dataclass(self._MAPPING(**kwargs))

def set_properties_from_dataclass(self, obj):
"""Set properties as defined in the given dataclass object."""
# TODO: this needs cleanup.
fields = obj.__dataclass_fields__
properties_to_set = []

for field_name in fields:
field_meta = fields[field_name].metadata

if "piid" not in field_meta:
continue

piid = field_meta["piid"]

siid = field_meta.get("siid", getattr(obj, "_siid", None))
if siid is None:
raise DeviceException(
f"no siid defined for {field_name} or for class {obj.__class__}"
)

value = obj.__getattribute__(field_name)
if value is None:
continue

property_set = {
"siid": siid,
"piid": piid,
"did": field_name,
"value": value,
}

properties_to_set.append(property_set)

if not properties_to_set:
raise DeviceException("No values to set!")

# TODO: handle splitting based on _max_properties

_LOGGER.debug("Going to set %s" % properties_to_set)
return self.send("set_properties", properties_to_set)

def get_properties_for_mapping(
self, property_mapping, *, max_properties=15
) -> list:
Expand All @@ -78,7 +126,7 @@ def get_properties_for_mapping(

return self.get_properties(properties, max_properties=max_properties)

def set_property(self, property_mapping, property_key: str, value):
def set_property_from_mapping(self, property_mapping, property_key: str, value):
"""Sets property value."""

return self.send(
Expand Down

0 comments on commit 63d6dc0

Please sign in to comment.