Source code for miio.integrations.philips.light.philips_moonlight

import logging
from collections import defaultdict
from typing import Any, Dict, List, Tuple

import click

from miio import Device, DeviceStatus
from miio.click_common import command, format_output
from miio.utils import int_to_rgb

_LOGGER = logging.getLogger(__name__)


[docs] class PhilipsMoonlightStatus(DeviceStatus): """Container for status reports from Xiaomi Philips Zhirui Bedside Lamp.""" def __init__(self, data: Dict[str, Any]) -> None: """Response of a Moonlight (philips.light.moonlight): {'pow': 'off', 'sta': 0, 'bri': 1, 'rgb': 16741971, 'cct': 1, 'snm': 0, 'spr': 0, 'spt': 15, 'wke': 0, 'bl': 1, 'ms': 1, 'mb': 1, 'wkp': [0, 24, 0]} """ self.data = data @property def power(self) -> str: return self.data["pow"] @property def is_on(self) -> bool: return self.power == "on" @property def brightness(self) -> int: return self.data["bri"] @property def color_temperature(self) -> int: return self.data["cct"] @property def rgb(self) -> Tuple[int, int, int]: """Return color in RGB.""" return int_to_rgb(int(self.data["rgb"])) @property def scene(self) -> int: return self.data["snm"] @property def sleep_assistant(self) -> int: """Example values: 0: Unknown 1: Unknown 2: Sleep assistant enabled 3: Awake """ return self.data["sta"] @property def sleep_off_time(self) -> int: return self.data["spr"] @property def total_assistant_sleep_time(self) -> int: return self.data["spt"] @property def brand_sleep(self) -> bool: # sp_sleep_open? return self.data["ms"] == 1 @property def brand(self) -> bool: # sp_xm_bracelet? return self.data["mb"] == 1 @property def wake_up_time(self) -> List[int]: # Example: [weekdays?, hour, minute] return self.data["wkp"]
[docs] class PhilipsMoonlight(Device): """Main class representing Xiaomi Philips Zhirui Bedside Lamp. Not yet implemented features/methods: add_mb # Add miband get_band_period # Bracelet work time get_mb_rssi # Miband RSSI get_mb_mac # Miband MAC address enable_mibs set_band_period miIO.bleStartSearchBand miIO.bleGetNearbyBandList enable_sub_voice # Sub voice control? enable_voice # Voice control skip_breath set_sleep_time set_wakeup_time en_sleep en_wakeup go_night # Night light / read mode get_wakeup_time enable_bl # Night light """ _supported_models = ["philips.light.moonlight"]
[docs] @command( default_output=format_output( "", "Power: {result.power}\n" "Brightness: {result.brightness}\n" "Color temperature: {result.color_temperature}\n" "RGB: {result.rgb}\n" "Scene: {result.scene}\n", ) ) def status(self) -> PhilipsMoonlightStatus: """Retrieve properties.""" properties = [ "pow", "sta", "bri", "rgb", "cct", "snm", "spr", "spt", "wke", "bl", "ms", "mb", "wkp", ] values = self.get_properties(properties) return PhilipsMoonlightStatus( defaultdict(lambda: None, zip(properties, values)) )
[docs] @command(default_output=format_output("Powering on")) def on(self): """Power on.""" return self.send("set_power", ["on"])
[docs] @command(default_output=format_output("Powering off")) def off(self): """Power off.""" return self.send("set_power", ["off"])
[docs] @command( click.argument("rgb", default=[255] * 3, type=click.Tuple([int, int, int])), default_output=format_output("Setting color to {rgb}"), ) def set_rgb(self, rgb: Tuple[int, int, int]): """Set color in RGB.""" for color in rgb: if color < 0 or color > 255: raise ValueError("Invalid color: %s" % color) return self.send("set_rgb", [*rgb])
[docs] @command( click.argument("level", type=int), default_output=format_output("Setting brightness to {level}"), ) def set_brightness(self, level: int): """Set brightness level.""" if level < 1 or level > 100: raise ValueError("Invalid brightness: %s" % level) return self.send("set_bright", [level])
[docs] @command( click.argument("level", type=int), default_output=format_output("Setting color temperature to {level}"), ) def set_color_temperature(self, level: int): """Set Correlated Color Temperature.""" if level < 1 or level > 100: raise ValueError("Invalid color temperature: %s" % level) return self.send("set_cct", [level])
[docs] @command( click.argument("brightness", type=int), click.argument("cct", type=int), default_output=format_output( "Setting brightness to {brightness} and color temperature to {cct}" ), ) def set_brightness_and_color_temperature(self, brightness: int, cct: int): """Set brightness level and the correlated color temperature.""" if brightness < 1 or brightness > 100: raise ValueError("Invalid brightness: %s" % brightness) if cct < 1 or cct > 100: raise ValueError("Invalid color temperature: %s" % cct) return self.send("set_bricct", [brightness, cct])
[docs] @command( click.argument("brightness", type=int), click.argument("rgb", default=[255] * 3, type=click.Tuple([int, int, int])), default_output=format_output( "Setting brightness to {brightness} and color to {rgb}" ), ) def set_brightness_and_rgb(self, brightness: int, rgb: Tuple[int, int, int]): """Set brightness level and the color.""" if brightness < 1 or brightness > 100: raise ValueError("Invalid brightness: %s" % brightness) for color in rgb: if color < 0 or color > 255: raise ValueError("Invalid color: %s" % color) return self.send("set_brirgb", [*rgb, brightness])
[docs] @command( click.argument("number", type=int), default_output=format_output("Setting fixed scene to {number}"), ) def set_scene(self, number: int): """Set scene number.""" if number < 1 or number > 6: raise ValueError("Invalid fixed scene number: %s" % number) if number == 6: return self.send("go_night") return self.send("apply_fixed_scene", [number])