import logging from typing import Any, Dict, List import click from miio.click_common import EnumType, command, format_output from miio.miot_device import MiotDevice from .status import OperatingMode, PetWaterDispenserStatus _LOGGER = logging.getLogger(__name__) MODEL_MMGG_PET_WATERER_S1 = "mmgg.pet_waterer.s1" MODEL_MMGG_PET_WATERER_S4 = "mmgg.pet_waterer.s4" SUPPORTED_MODELS: List[str] = [MODEL_MMGG_PET_WATERER_S1, MODEL_MMGG_PET_WATERER_S4] _MAPPING: Dict[str, Dict[str, int]] = { # https://home.miot-spec.com/spec/mmgg.pet_waterer.s1 # https://home.miot-spec.com/spec/mmgg.pet_waterer.s4 "cotton_left_time": {"siid": 5, "piid": 1}, "reset_cotton_life": {"siid": 5, "aiid": 1}, "reset_clean_time": {"siid": 6, "aiid": 1}, "fault": {"siid": 2, "piid": 1}, "filter_left_time": {"siid": 3, "piid": 1}, "indicator_light": {"siid": 4, "piid": 1}, "lid_up_flag": {"siid": 7, "piid": 4}, # missing on mmgg.pet_waterer.s4 "location": {"siid": 9, "piid": 2}, "mode": {"siid": 2, "piid": 3}, "no_water_flag": {"siid": 7, "piid": 1}, "no_water_time": {"siid": 7, "piid": 2}, "on": {"siid": 2, "piid": 2}, "pump_block_flag": {"siid": 7, "piid": 3}, "remain_clean_time": {"siid": 6, "piid": 1}, "reset_filter_life": {"siid": 3, "aiid": 1}, "reset_device": {"siid": 8, "aiid": 1}, "timezone": {"siid": 9, "piid": 1}, } MIOT_MAPPING = {model: _MAPPING for model in SUPPORTED_MODELS} class PetWaterDispenser(MiotDevice): """Main class representing the Pet Waterer / Pet Drinking Fountain / Smart Pet Water Dispenser.""" _mappings = MIOT_MAPPING @command( default_output=format_output( "", "On: {result.is_on}\n" "Mode: {result.mode}\n" "LED on: {result.is_led_on}\n" "Lid up: {result.is_lid_up}\n" "No water: {result.is_no_water}\n" "Time without water: {result.no_water_minutes}\n" "Pump blocked: {result.is_pump_blocked}\n" "Error detected: {result.is_error_detected}\n" "Days before cleaning left: {result.before_cleaning_days}\n" "Cotton filter live left: {result.cotton_left_days}\n" "Sponge filter live left: {result.sponge_filter_left_days}\n" "Location: {result.location}\n" "Timezone: {result.timezone}\n", ) ) def status(self) -> PetWaterDispenserStatus: """Retrieve properties.""" data = { prop["did"]: prop["value"] if prop["code"] == 0 else None for prop in self.get_properties_for_mapping() } _LOGGER.debug(data) return PetWaterDispenserStatus(data) @command(default_output=format_output("Turning device on")) def on(self) -> List[Dict[str, Any]]: """Turn device on.""" return self.set_property("on", True) @command(default_output=format_output("Turning device off")) def off(self) -> List[Dict[str, Any]]: """Turn device off.""" return self.set_property("on", False) @command( click.argument("led", type=bool), default_output=format_output( lambda led: "Turning LED on" if led else "Turning LED off" ), ) def set_led(self, led: bool) -> List[Dict[str, Any]]: """Toggle indicator light on/off.""" if led: return self.set_property("indicator_light", True) return self.set_property("indicator_light", False) @command( click.argument("mode", type=EnumType(OperatingMode)), default_output=format_output('Changing mode to "{mode.name}"'), ) def set_mode(self, mode: OperatingMode) -> List[Dict[str, Any]]: """Switch operation mode.""" return self.set_property("mode", mode.value) @command(default_output=format_output("Resetting sponge filter")) def reset_sponge_filter(self) -> Dict[str, Any]: """Reset sponge filter.""" return self.call_action("reset_filter_life") @command(default_output=format_output("Resetting cotton filter")) def reset_cotton_filter(self) -> Dict[str, Any]: """Reset cotton filter.""" return self.call_action("reset_cotton_life") @command(default_output=format_output("Resetting all filters")) def reset_all_filters(self) -> List[Dict[str, Any]]: """Reset all filters [cotton, sponge].""" return [self.reset_cotton_filter(), self.reset_sponge_filter()] @command(default_output=format_output("Resetting cleaning time")) def reset_cleaning_time(self) -> Dict[str, Any]: """Reset cleaning time counter.""" return self.call_action("reset_clean_time") @command(default_output=format_output("Resetting device")) def reset(self) -> Dict[str, Any]: """Reset device.""" return self.call_action("reset_device") @command( click.argument("timezone", type=click.IntRange(-12, 12)), default_output=format_output('Changing timezone to "{timezone}"'), ) def set_timezone(self, timezone: int) -> List[Dict[str, Any]]: """Change timezone.""" return self.set_property("timezone", timezone) @command( click.argument("location", type=str), default_output=format_output('Changing location to "{location}"'), ) def set_location(self, location: str) -> List[Dict[str, Any]]: """Change location.""" return self.set_property("location", location)