diff --git a/.readthedocs.yml b/.readthedocs.yml index cf2cf491f..4e8633331 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -13,4 +13,5 @@ python: - docs sphinx: - configuration: docs/conf.py + configuration: docs/conf.py + fail_on_warning: true diff --git a/docs/conf.py b/docs/conf.py index dcf2b1180..d4e3be1a1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -188,6 +188,8 @@ apidoc_output_dir = "api" apidoc_excluded_paths = ["tests", "**/test_*", "**/tests"] apidoc_separate_modules = True +apidoc_toc_file = False + autodoc_member_order = "groupwise" autodoc_inherit_docstrings = True autodoc_default_options = {"inherited-members": True} diff --git a/docs/contributing.rst b/docs/contributing.rst index 7b1ef2827..d5c342cf7 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -115,10 +115,11 @@ Development checklist --------------------- 1. All device classes are derived from either :class:`miio.device.Device` (for MiIO) - or :class:`miio.miot_device.MiotDevice` (for MiOT) (:ref:`Minimal example`). + or :class:`miio.miot_device.MiotDevice` (for MiOT) (:ref:`minimal_example`). 2. All commands and their arguments should be decorated with `@command` decorator, which will make them accessible to `miiocli` (:ref:`miiocli`). -3. All implementations must define :ref:`Device._supported_models` variable in the class +3. All implementations must either include a model-keyed ``_mappings`` list (for MiOT), + or define ``Device._supported_models`` variable in the class (for MiIO). listing the known models (as reported by `info()`). 4. Status containers is derived from `DeviceStatus` class and all properties should have type annotations for their return values. @@ -127,6 +128,8 @@ Development checklist will be generated automatically. +.. _minimal_example: + Minimal example ~~~~~~~~~~~~~~~ @@ -134,6 +137,8 @@ Minimal example Add or link to an example. +.. _miiocli: + miiocli integration ~~~~~~~~~~~~~~~~~~~ diff --git a/docs/legacy_token_extraction.rst b/docs/legacy_token_extraction.rst index 5e29f68b9..7af4a8975 100644 --- a/docs/legacy_token_extraction.rst +++ b/docs/legacy_token_extraction.rst @@ -1,3 +1,5 @@ +:orphan: + .. _legacy_token_extraction: Legacy methods for obtaining tokens diff --git a/docs/push_server.rst b/docs/push_server.rst index 8102d4707..be64c4a3c 100644 --- a/docs/push_server.rst +++ b/docs/push_server.rst @@ -9,7 +9,7 @@ and calling the registered callbacks accordingly. .. note:: While the eventing has been so far tested only on gateway devices, other devices that allow scene definitions on the - mobile app may potentially support this functionality. See :ref:`how to obtain event information` for details + mobile app may potentially support this functionality. See :ref:`how to obtain event information` for details how to check if your target device supports this functionality. @@ -189,7 +189,7 @@ to retrieve the necessary information for that event. Most times this information will be enough, however the :class:`miio.EventInfo` class allows for additional information. For example, on Zigbee sub-devices you also need to define `source_sid` and `source_model`, -see :ref:`button press <_button_press_example>` for an example. +see :ref:`button press ` for an example. See the :class:`PushServer.EventInfo` for more detailed documentation. diff --git a/miio/airqualitymonitor_miot.py b/miio/airqualitymonitor_miot.py index 05bd39c9e..ba36f55c4 100644 --- a/miio/airqualitymonitor_miot.py +++ b/miio/airqualitymonitor_miot.py @@ -87,26 +87,25 @@ class DisplayTemperatureUnitCGDN1(enum.Enum): class AirQualityMonitorCGDN1Status(DeviceStatus): - """ - Container of air quality monitor CGDN1 status. - - { - 'humidity': 34, - 'pm25': 18, - 'pm10': 21, - 'temperature': 22.8, - 'co2': 468, - 'battery': 37, - 'charging_state': 0, - 'voltage': 3564, - 'start_time': 0, - 'end_time': 0, - 'monitoring_frequency': 1, - 'screen_off': 300, - 'device_off': 60, - 'temperature_unit': 'c' - } - + """Container of air quality monitor CGDN1 status. + + Example:: + { + 'humidity': 34, + 'pm25': 18, + 'pm10': 21, + 'temperature': 22.8, + 'co2': 468, + 'battery': 37, + 'charging_state': 0, + 'voltage': 3564, + 'start_time': 0, + 'end_time': 0, + 'monitoring_frequency': 1, + 'screen_off': 300, + 'device_off': 60, + 'temperature_unit': 'c' + } """ def __init__(self, data): diff --git a/miio/device.py b/miio/device.py index f4d2a34ff..fc199353a 100644 --- a/miio/device.py +++ b/miio/device.py @@ -232,7 +232,7 @@ def get_properties( :param list properties: List of properties to query from the device. :param int max_properties: Number of properties that can be requested at once. - :return List of property values. + :return: List of property values. """ _props = properties.copy() values = [] diff --git a/miio/extract_tokens.py b/miio/extract_tokens.py index 7b8576bd4..019d63370 100644 --- a/miio/extract_tokens.py +++ b/miio/extract_tokens.py @@ -54,13 +54,13 @@ def read_android_yeelight(db) -> Iterator[DeviceConfig]: class BackupDatabaseReader: """Main class for reading backup files. - Example: - .. code-block:: python + Example:: + .. code-block:: python - r = BackupDatabaseReader() - devices = r.read_tokens("/tmp/database.sqlite") - for dev in devices: - print("Got %s with token %s" % (dev.ip, dev.token) + r = BackupDatabaseReader() + devices = r.read_tokens("/tmp/database.sqlite") + for dev in devices: + print("Got %s with token %s" % (dev.ip, dev.token) """ def __init__(self, dump_raw=False): diff --git a/miio/huizuo.py b/miio/huizuo.py index 46c2d7cac..0d184e163 100644 --- a/miio/huizuo.py +++ b/miio/huizuo.py @@ -192,7 +192,8 @@ def heat_level(self) -> Optional[int]: class Huizuo(MiotDevice): """A basic support for Huizuo Lamps. - Example: response of a Huizuo Pisces For Bedroom (huayi.light.pis123) + Example response of a Huizuo Pisces For Bedroom (huayi.light.pis123):: + {'id': 1, 'result': [ {'did': '', 'siid': 2, 'piid': 1, 'code': 0, 'value': False}, {'did': '', 'siid': 2, 'piid': 2, 'code': 0, 'value': 94}, @@ -200,14 +201,15 @@ class Huizuo(MiotDevice): ] } - Explanation (line-by-line): + Explanation (line-by-line):: + power = '{"siid":2,"piid":1}' values = true,false brightless(%) = '{"siid":2,"piid":2}' values = 1-100 color temperature(Kelvin) = '{"siid":2,"piid":3}' values = 3000-6400 - This is basic response for all HUIZUO lamps + This is basic response for all HUIZUO lamps. Also some models supports additional properties, like for Fan or Heating management. - If your device does't support some properties, the 'None' will be returned + If your device does't support some properties, the 'None' will be returned. """ mapping = _MAPPING diff --git a/miio/integrations/airpurifier/zhimi/airpurifier_miot.py b/miio/integrations/airpurifier/zhimi/airpurifier_miot.py index 2baec9af1..bb2394ce7 100644 --- a/miio/integrations/airpurifier/zhimi/airpurifier_miot.py +++ b/miio/integrations/airpurifier/zhimi/airpurifier_miot.py @@ -272,32 +272,32 @@ class LedBrightness(enum.Enum): class AirPurifierMiotStatus(DeviceStatus): """Container for status reports from the air purifier. - Mi Air Purifier 3/3H (zhimi.airpurifier.mb3) response (MIoT format) - - [ - {'did': 'power', 'siid': 2, 'piid': 2, 'code': 0, 'value': True}, - {'did': 'fan_level', 'siid': 2, 'piid': 4, 'code': 0, 'value': 1}, - {'did': 'mode', 'siid': 2, 'piid': 5, 'code': 0, 'value': 2}, - {'did': 'humidity', 'siid': 3, 'piid': 7, 'code': 0, 'value': 38}, - {'did': 'temperature', 'siid': 3, 'piid': 8, 'code': 0, 'value': 22.299999}, - {'did': 'aqi', 'siid': 3, 'piid': 6, 'code': 0, 'value': 2}, - {'did': 'filter_life_remaining', 'siid': 4, 'piid': 3, 'code': 0, 'value': 45}, - {'did': 'filter_hours_used', 'siid': 4, 'piid': 5, 'code': 0, 'value': 1915}, - {'did': 'buzzer', 'siid': 5, 'piid': 1, 'code': 0, 'value': False}, - {'did': 'buzzer_volume', 'siid': 5, 'piid': 2, 'code': -4001}, - {'did': 'led_brightness', 'siid': 6, 'piid': 1, 'code': 0, 'value': 1}, - {'did': 'led', 'siid': 6, 'piid': 6, 'code': 0, 'value': True}, - {'did': 'child_lock', 'siid': 7, 'piid': 1, 'code': 0, 'value': False}, - {'did': 'favorite_level', 'siid': 10, 'piid': 10, 'code': 0, 'value': 2}, - {'did': 'favorite_rpm', 'siid': 10, 'piid': 7, 'code': 0, 'value': 770}, - {'did': 'motor_speed', 'siid': 10, 'piid': 8, 'code': 0, 'value': 769}, - {'did': 'use_time', 'siid': 12, 'piid': 1, 'code': 0, 'value': 6895800}, - {'did': 'purify_volume', 'siid': 13, 'piid': 1, 'code': 0, 'value': 222564}, - {'did': 'average_aqi', 'siid': 13, 'piid': 2, 'code': 0, 'value': 2}, - {'did': 'filter_rfid_tag', 'siid': 14, 'piid': 1, 'code': 0, 'value': '81:6b:3f:32:84:4b:4'}, - {'did': 'filter_rfid_product_id', 'siid': 14, 'piid': 3, 'code': 0, 'value': '0:0:31:31'}, - {'did': 'app_extra', 'siid': 15, 'piid': 1, 'code': 0, 'value': 0} - ] + Mi Air Purifier 3/3H (zhimi.airpurifier.mb3) response (MIoT format):: + + [ + {'did': 'power', 'siid': 2, 'piid': 2, 'code': 0, 'value': True}, + {'did': 'fan_level', 'siid': 2, 'piid': 4, 'code': 0, 'value': 1}, + {'did': 'mode', 'siid': 2, 'piid': 5, 'code': 0, 'value': 2}, + {'did': 'humidity', 'siid': 3, 'piid': 7, 'code': 0, 'value': 38}, + {'did': 'temperature', 'siid': 3, 'piid': 8, 'code': 0, 'value': 22.299999}, + {'did': 'aqi', 'siid': 3, 'piid': 6, 'code': 0, 'value': 2}, + {'did': 'filter_life_remaining', 'siid': 4, 'piid': 3, 'code': 0, 'value': 45}, + {'did': 'filter_hours_used', 'siid': 4, 'piid': 5, 'code': 0, 'value': 1915}, + {'did': 'buzzer', 'siid': 5, 'piid': 1, 'code': 0, 'value': False}, + {'did': 'buzzer_volume', 'siid': 5, 'piid': 2, 'code': -4001}, + {'did': 'led_brightness', 'siid': 6, 'piid': 1, 'code': 0, 'value': 1}, + {'did': 'led', 'siid': 6, 'piid': 6, 'code': 0, 'value': True}, + {'did': 'child_lock', 'siid': 7, 'piid': 1, 'code': 0, 'value': False}, + {'did': 'favorite_level', 'siid': 10, 'piid': 10, 'code': 0, 'value': 2}, + {'did': 'favorite_rpm', 'siid': 10, 'piid': 7, 'code': 0, 'value': 770}, + {'did': 'motor_speed', 'siid': 10, 'piid': 8, 'code': 0, 'value': 769}, + {'did': 'use_time', 'siid': 12, 'piid': 1, 'code': 0, 'value': 6895800}, + {'did': 'purify_volume', 'siid': 13, 'piid': 1, 'code': 0, 'value': 222564}, + {'did': 'average_aqi', 'siid': 13, 'piid': 2, 'code': 0, 'value': 2}, + {'did': 'filter_rfid_tag', 'siid': 14, 'piid': 1, 'code': 0, 'value': '81:6b:3f:32:84:4b:4'}, + {'did': 'filter_rfid_product_id', 'siid': 14, 'piid': 3, 'code': 0, 'value': '0:0:31:31'}, + {'did': 'app_extra', 'siid': 15, 'piid': 1, 'code': 0, 'value': 0} + ] """ def __init__(self, data: Dict[str, Any], model: str) -> None: diff --git a/miio/integrations/humidifier/deerma/airhumidifier_jsqs.py b/miio/integrations/humidifier/deerma/airhumidifier_jsqs.py index f8ab1177d..db6865465 100644 --- a/miio/integrations/humidifier/deerma/airhumidifier_jsqs.py +++ b/miio/integrations/humidifier/deerma/airhumidifier_jsqs.py @@ -47,21 +47,21 @@ class OperationMode(enum.Enum): class AirHumidifierJsqsStatus(DeviceStatus): """Container for status reports from the air humidifier. - Xiaomi Mi Smart Humidifer S (deerma.humidifier.[jsqs, jsq5]) respone (MIoT format) - - [ - {'did': 'power', 'siid': 2, 'piid': 1, 'code': 0, 'value': True}, - {'did': 'fault', 'siid': 2, 'piid': 2, 'code': 0, 'value': 0}, - {'did': 'mode', 'siid': 2, 'piid': 5, 'code': 0, 'value': 1}, - {'did': 'target_humidity', 'siid': 2, 'piid': 6, 'code': 0, 'value': 50}, - {'did': 'relative_humidity', 'siid': 3, 'piid': 1, 'code': 0, 'value': 40}, - {'did': 'temperature', 'siid': 3, 'piid': 7, 'code': 0, 'value': 22.7}, - {'did': 'buzzer', 'siid': 5, 'piid': 1, 'code': 0, 'value': False}, - {'did': 'led_light', 'siid': 6, 'piid': 1, 'code': 0, 'value': True}, - {'did': 'water_shortage_fault', 'siid': 7, 'piid': 1, 'code': 0, 'value': False}, - {'did': 'tank_filed', 'siid': 7, 'piid': 2, 'code': 0, 'value': False}, - {'did': 'overwet_protect', 'siid': 7, 'piid': 3, 'code': 0, 'value': False} - ] + Xiaomi Mi Smart Humidifer S (deerma.humidifier.[jsqs, jsq5]) response (MIoT format):: + + [ + {'did': 'power', 'siid': 2, 'piid': 1, 'code': 0, 'value': True}, + {'did': 'fault', 'siid': 2, 'piid': 2, 'code': 0, 'value': 0}, + {'did': 'mode', 'siid': 2, 'piid': 5, 'code': 0, 'value': 1}, + {'did': 'target_humidity', 'siid': 2, 'piid': 6, 'code': 0, 'value': 50}, + {'did': 'relative_humidity', 'siid': 3, 'piid': 1, 'code': 0, 'value': 40}, + {'did': 'temperature', 'siid': 3, 'piid': 7, 'code': 0, 'value': 22.7}, + {'did': 'buzzer', 'siid': 5, 'piid': 1, 'code': 0, 'value': False}, + {'did': 'led_light', 'siid': 6, 'piid': 1, 'code': 0, 'value': True}, + {'did': 'water_shortage_fault', 'siid': 7, 'piid': 1, 'code': 0, 'value': False}, + {'did': 'tank_filed', 'siid': 7, 'piid': 2, 'code': 0, 'value': False}, + {'did': 'overwet_protect', 'siid': 7, 'piid': 3, 'code': 0, 'value': False} + ] """ def __init__(self, data: Dict[str, Any]) -> None: diff --git a/miio/integrations/humidifier/zhimi/airhumidifier_miot.py b/miio/integrations/humidifier/zhimi/airhumidifier_miot.py index 6cce08a6c..a7e529a86 100644 --- a/miio/integrations/humidifier/zhimi/airhumidifier_miot.py +++ b/miio/integrations/humidifier/zhimi/airhumidifier_miot.py @@ -70,28 +70,28 @@ class PressedButton(enum.Enum): class AirHumidifierMiotStatus(DeviceStatus): """Container for status reports from the air humidifier. - Xiaomi Smartmi Evaporation Air Humidifier 2 (zhimi.humidifier.ca4) respone (MIoT format) - - [ - {'did': 'power', 'siid': 2, 'piid': 1, 'code': 0, 'value': True}, - {'did': 'fault', 'siid': 2, 'piid': 2, 'code': 0, 'value': 0}, - {'did': 'mode', 'siid': 2, 'piid': 5, 'code': 0, 'value': 0}, - {'did': 'target_humidity', 'siid': 2, 'piid': 6, 'code': 0, 'value': 50}, - {'did': 'water_level', 'siid': 2, 'piid': 7, 'code': 0, 'value': 127}, - {'did': 'dry', 'siid': 2, 'piid': 8, 'code': 0, 'value': False}, - {'did': 'use_time', 'siid': 2, 'piid': 9, 'code': 0, 'value': 5140816}, - {'did': 'button_pressed', 'siid': 2, 'piid': 10, 'code': 0, 'value': 2}, - {'did': 'speed_level', 'siid': 2, 'piid': 11, 'code': 0, 'value': 790}, - {'did': 'temperature', 'siid': 3, 'piid': 7, 'code': 0, 'value': 22.7}, - {'did': 'fahrenheit', 'siid': 3, 'piid': 8, 'code': 0, 'value': 72.8}, - {'did': 'humidity', 'siid': 3, 'piid': 9, 'code': 0, 'value': 39}, - {'did': 'buzzer', 'siid': 4, 'piid': 1, 'code': 0, 'value': False}, - {'did': 'led_brightness', 'siid': 5, 'piid': 2, 'code': 0, 'value': 2}, - {'did': 'child_lock', 'siid': 6, 'piid': 1, 'code': 0, 'value': False}, - {'did': 'actual_speed', 'siid': 7, 'piid': 1, 'code': 0, 'value': 0}, - {'did': 'power_time', 'siid': 7, 'piid': 3, 'code': 0, 'value': 18520}, - {'did': 'clean_mode', 'siid': 7, 'piid': 5, 'code': 0, 'value': True} - ] + Xiaomi Smartmi Evaporation Air Humidifier 2 (zhimi.humidifier.ca4) respone (MIoT format):: + + [ + {'did': 'power', 'siid': 2, 'piid': 1, 'code': 0, 'value': True}, + {'did': 'fault', 'siid': 2, 'piid': 2, 'code': 0, 'value': 0}, + {'did': 'mode', 'siid': 2, 'piid': 5, 'code': 0, 'value': 0}, + {'did': 'target_humidity', 'siid': 2, 'piid': 6, 'code': 0, 'value': 50}, + {'did': 'water_level', 'siid': 2, 'piid': 7, 'code': 0, 'value': 127}, + {'did': 'dry', 'siid': 2, 'piid': 8, 'code': 0, 'value': False}, + {'did': 'use_time', 'siid': 2, 'piid': 9, 'code': 0, 'value': 5140816}, + {'did': 'button_pressed', 'siid': 2, 'piid': 10, 'code': 0, 'value': 2}, + {'did': 'speed_level', 'siid': 2, 'piid': 11, 'code': 0, 'value': 790}, + {'did': 'temperature', 'siid': 3, 'piid': 7, 'code': 0, 'value': 22.7}, + {'did': 'fahrenheit', 'siid': 3, 'piid': 8, 'code': 0, 'value': 72.8}, + {'did': 'humidity', 'siid': 3, 'piid': 9, 'code': 0, 'value': 39}, + {'did': 'buzzer', 'siid': 4, 'piid': 1, 'code': 0, 'value': False}, + {'did': 'led_brightness', 'siid': 5, 'piid': 2, 'code': 0, 'value': 2}, + {'did': 'child_lock', 'siid': 6, 'piid': 1, 'code': 0, 'value': False}, + {'did': 'actual_speed', 'siid': 7, 'piid': 1, 'code': 0, 'value': 0}, + {'did': 'power_time', 'siid': 7, 'piid': 3, 'code': 0, 'value': 18520}, + {'did': 'clean_mode', 'siid': 7, 'piid': 5, 'code': 0, 'value': True} + ] """ def __init__(self, data: Dict[str, Any]) -> None: diff --git a/miio/integrations/vacuum/dreame/dreamevacuum_miot.py b/miio/integrations/vacuum/dreame/dreamevacuum_miot.py index 78b6053e2..515d39da4 100644 --- a/miio/integrations/vacuum/dreame/dreamevacuum_miot.py +++ b/miio/integrations/vacuum/dreame/dreamevacuum_miot.py @@ -211,35 +211,36 @@ def _get_cleaning_mode_enum_class(model): class DreameVacuumStatus(DeviceStatusContainer): """Container for status reports from the dreame vacuum. - Dreame vacuum respone - { - 'battery_level': 100, - 'brush_left_time': 260, - 'brush_left_time2': 200, - 'brush_life_level': 90, - 'brush_life_level2': 90, - 'charging_state': 1, - 'cleaning_area': 22, - 'cleaning_mode': 2, - 'cleaning_time': 17, - 'device_fault': 0, - 'device_status': 6, - 'filter_left_time': 120, - 'filter_life_level': 40, - 'first_clean_time': 1620154830, - 'operating_mode': 6, - 'start_time': '22:00', - 'stop_time': '08:00', - 'timer_enable': True, - 'timezone': 'Europe/Berlin', - 'total_clean_area': 205, - 'total_clean_time': 186, - 'total_clean_times': 21, - 'voice_package': 'DR0', - 'volume': 65, - 'water_box_carriage_status': 0, - 'water_flow': 3 - } + Dreame vacuum example response:: + + { + 'battery_level': 100, + 'brush_left_time': 260, + 'brush_left_time2': 200, + 'brush_life_level': 90, + 'brush_life_level2': 90, + 'charging_state': 1, + 'cleaning_area': 22, + 'cleaning_mode': 2, + 'cleaning_time': 17, + 'device_fault': 0, + 'device_status': 6, + 'filter_left_time': 120, + 'filter_life_level': 40, + 'first_clean_time': 1620154830, + 'operating_mode': 6, + 'start_time': '22:00', + 'stop_time': '08:00', + 'timer_enable': True, + 'timezone': 'Europe/Berlin', + 'total_clean_area': 205, + 'total_clean_time': 186, + 'total_clean_times': 21, + 'voice_package': 'DR0', + 'volume': 65, + 'water_box_carriage_status': 0, + 'water_flow': 3 + } """ def __init__(self, data, model): diff --git a/miio/integrations/vacuum/mijia/g1vacuum.py b/miio/integrations/vacuum/mijia/g1vacuum.py index 8253da1cd..d042e11d8 100644 --- a/miio/integrations/vacuum/mijia/g1vacuum.py +++ b/miio/integrations/vacuum/mijia/g1vacuum.py @@ -136,24 +136,27 @@ class G1Status(DeviceStatus): def __init__(self, data): """Response (MIoT format) of a Mijia Vacuum G1 (mijia.vacuum.v2) - [ - {'did': 'battery', 'siid': 3, 'piid': 1, 'code': 0, 'value': 100}, - {'did': 'charge_state', 'siid': 3, 'piid': 2, 'code': 0, 'value': 2}, - {'did': 'error_code', 'siid': 2, 'piid': 2, 'code': 0, 'value': 0}, - {'did': 'state', 'siid': 2, 'piid': 1, 'code': 0, 'value': 5}, - {'did': 'fan_speed', 'siid': 2, 'piid': 6, 'code': 0, 'value': 1}, - {'did': 'operating_mode', 'siid': 2, 'piid': 4, 'code': 0, 'value': 1}, - {'did': 'mop_state', 'siid': 16, 'piid': 1, 'code': 0, 'value': 0}, - {'did': 'water_level', 'siid': 2, 'piid': 5, 'code': 0, 'value': 2}, - {'did': 'main_brush_life_level', 'siid': 14, 'piid': 1, 'code': 0, 'value': 99}, - {'did': 'main_brush_time_left', 'siid': 14, 'piid': 2, 'code': 0, 'value': 17959} - {'did': 'side_brush_life_level', 'siid': 15, 'piid': 1, 'code': 0, 'value': 0 }, - {'did': 'side_brush_time_left', 'siid': 15, 'piid': 2', 'code': 0, 'value': 0}, - {'did': 'filter_life_level', 'siid': 11, 'piid': 1, 'code': 0, 'value': 99}, - {'did': 'filter_time_left', 'siid': 11, 'piid': 2, 'code': 0, 'value': 8959}, - {'did': 'clean_area', 'siid': 9, 'piid': 1, 'code': 0, 'value': 0}, - {'did': 'clean_time', 'siid': 9, 'piid': 2, 'code': 0, 'value': 0} - ]""" + Example:: + + [ + {'did': 'battery', 'siid': 3, 'piid': 1, 'code': 0, 'value': 100}, + {'did': 'charge_state', 'siid': 3, 'piid': 2, 'code': 0, 'value': 2}, + {'did': 'error_code', 'siid': 2, 'piid': 2, 'code': 0, 'value': 0}, + {'did': 'state', 'siid': 2, 'piid': 1, 'code': 0, 'value': 5}, + {'did': 'fan_speed', 'siid': 2, 'piid': 6, 'code': 0, 'value': 1}, + {'did': 'operating_mode', 'siid': 2, 'piid': 4, 'code': 0, 'value': 1}, + {'did': 'mop_state', 'siid': 16, 'piid': 1, 'code': 0, 'value': 0}, + {'did': 'water_level', 'siid': 2, 'piid': 5, 'code': 0, 'value': 2}, + {'did': 'main_brush_life_level', 'siid': 14, 'piid': 1, 'code': 0, 'value': 99}, + {'did': 'main_brush_time_left', 'siid': 14, 'piid': 2, 'code': 0, 'value': 17959} + {'did': 'side_brush_life_level', 'siid': 15, 'piid': 1, 'code': 0, 'value': 0 }, + {'did': 'side_brush_time_left', 'siid': 15, 'piid': 2', 'code': 0, 'value': 0}, + {'did': 'filter_life_level', 'siid': 11, 'piid': 1, 'code': 0, 'value': 99}, + {'did': 'filter_time_left', 'siid': 11, 'piid': 2, 'code': 0, 'value': 8959}, + {'did': 'clean_area', 'siid': 9, 'piid': 1, 'code': 0, 'value': 0}, + {'did': 'clean_time', 'siid': 9, 'piid': 2, 'code': 0, 'value': 0} + ] + """ self.data = data @property @@ -248,12 +251,13 @@ def clean_time(self) -> timedelta: class G1CleaningSummary(DeviceStatus): """Container for cleaning summary from Mijia Vacuum G1. - Response (MIoT format) of a Mijia Vacuum G1 (mijia.vacuum.v2) + Response (MIoT format) of a Mijia Vacuum G1 (mijia.vacuum.v2):: + [ - {'did': 'total_clean_area', 'siid': 9, 'piid': 3, 'code': 0, 'value': 0}, - {'did': 'total_clean_time', 'siid': 9, 'piid': 4, 'code': 0, 'value': 0}, - {'did': 'total_clean_count', 'siid': 9, 'piid': 5, 'code': 0, 'value': 0} - ] + {'did': 'total_clean_area', 'siid': 9, 'piid': 3, 'code': 0, 'value': 0}, + {'did': 'total_clean_time', 'siid': 9, 'piid': 4, 'code': 0, 'value': 0}, + {'did': 'total_clean_count', 'siid': 9, 'piid': 5, 'code': 0, 'value': 0} + ] """ def __init__(self, data) -> None: diff --git a/miio/integrations/vacuum/roidmi/roidmivacuum_miot.py b/miio/integrations/vacuum/roidmi/roidmivacuum_miot.py index aa1828d5e..d69ccdb60 100644 --- a/miio/integrations/vacuum/roidmi/roidmivacuum_miot.py +++ b/miio/integrations/vacuum/roidmi/roidmivacuum_miot.py @@ -180,46 +180,46 @@ class RoidmiVacuumStatus(DeviceStatus): def __init__(self, data): """ - Response (MIoT format) of a Roidme Eve Plus (roidmi.vacuum.v60) - [ - {'did': 'battery_level', 'siid': 3, 'piid': 1}, - {'did': 'charging_state', 'siid': 3, 'piid': 2}, - {'did': 'error_code', 'siid': 2, 'piid': 2}, - {'did': 'state', 'siid': 2, 'piid': 1}, - {'did': 'filter_life_level', 'siid': 10, 'piid': 1}, - {'did': 'filter_left_minutes', 'siid': 10, 'piid': 2}, - {'did': 'main_brush_left_minutes', 'siid': 11, 'piid': 1}, - {'did': 'main_brush_life_level', 'siid': 11, 'piid': 2}, - {'did': 'side_brushes_left_minutes', 'siid': 12, 'piid': 1}, - {'did': 'side_brushes_life_level', 'siid': 12, 'piid': 2}, - {'did': 'sensor_dirty_time_left_minutes', 'siid': 15, 'piid': 1}, - {'did': 'sensor_dirty_remaning_level', 'siid': 15, 'piid': 2}, - {'did': 'sweep_mode', 'siid': 14, 'piid': 1}, - {'did': 'fanspeed_mode', 'siid': 2, 'piid': 4}, - {'did': 'sweep_type', 'siid': 2, 'piid': 8} - {'did': 'path_mode', 'siid': 13, 'piid': 8}, - {'did': 'mop_present', 'siid': 8, 'piid': 1}, - {'did': 'work_station_freq', 'siid': 8, 'piid': 2}, - {'did': 'timing', 'siid': 8, 'piid': 6}, - {'did': 'clean_area', 'siid': 8, 'piid': 7}, - {'did': 'auto_boost', 'siid': 8, 'piid': 9}, - {'did': 'forbid_mode', 'siid': 8, 'piid': 10}, - {'did': 'water_level', 'siid': 8, 'piid': 11}, - {'did': 'total_clean_time_sec', 'siid': 8, 'piid': 13}, - {'did': 'total_clean_areas', 'siid': 8, 'piid': 14}, - {'did': 'clean_counts', 'siid': 8, 'piid': 18}, - {'did': 'clean_time_sec', 'siid': 8, 'piid': 19}, - {'did': 'double_clean', 'siid': 8, 'piid': 20}, - {'did': 'led_switch', 'siid': 8, 'piid': 22} - {'did': 'lidar_collision', 'siid': 8, 'piid': 23}, - {'did': 'station_key', 'siid': 8, 'piid': 24}, - {'did': 'station_led', 'siid': 8, 'piid': 25}, - {'did': 'current_audio', 'siid': 8, 'piid': 26}, - {'did': 'station_type', 'siid': 8, 'piid': 29}, - {'did': 'volume', 'siid': 9, 'piid': 1}, - {'did': 'mute', 'siid': 9, 'piid': 2} - ] - + Response (MIoT format) of a Roidme Eve Plus (roidmi.vacuum.v60):: + + [ + {'did': 'battery_level', 'siid': 3, 'piid': 1}, + {'did': 'charging_state', 'siid': 3, 'piid': 2}, + {'did': 'error_code', 'siid': 2, 'piid': 2}, + {'did': 'state', 'siid': 2, 'piid': 1}, + {'did': 'filter_life_level', 'siid': 10, 'piid': 1}, + {'did': 'filter_left_minutes', 'siid': 10, 'piid': 2}, + {'did': 'main_brush_left_minutes', 'siid': 11, 'piid': 1}, + {'did': 'main_brush_life_level', 'siid': 11, 'piid': 2}, + {'did': 'side_brushes_left_minutes', 'siid': 12, 'piid': 1}, + {'did': 'side_brushes_life_level', 'siid': 12, 'piid': 2}, + {'did': 'sensor_dirty_time_left_minutes', 'siid': 15, 'piid': 1}, + {'did': 'sensor_dirty_remaning_level', 'siid': 15, 'piid': 2}, + {'did': 'sweep_mode', 'siid': 14, 'piid': 1}, + {'did': 'fanspeed_mode', 'siid': 2, 'piid': 4}, + {'did': 'sweep_type', 'siid': 2, 'piid': 8} + {'did': 'path_mode', 'siid': 13, 'piid': 8}, + {'did': 'mop_present', 'siid': 8, 'piid': 1}, + {'did': 'work_station_freq', 'siid': 8, 'piid': 2}, + {'did': 'timing', 'siid': 8, 'piid': 6}, + {'did': 'clean_area', 'siid': 8, 'piid': 7}, + {'did': 'auto_boost', 'siid': 8, 'piid': 9}, + {'did': 'forbid_mode', 'siid': 8, 'piid': 10}, + {'did': 'water_level', 'siid': 8, 'piid': 11}, + {'did': 'total_clean_time_sec', 'siid': 8, 'piid': 13}, + {'did': 'total_clean_areas', 'siid': 8, 'piid': 14}, + {'did': 'clean_counts', 'siid': 8, 'piid': 18}, + {'did': 'clean_time_sec', 'siid': 8, 'piid': 19}, + {'did': 'double_clean', 'siid': 8, 'piid': 20}, + {'did': 'led_switch', 'siid': 8, 'piid': 22} + {'did': 'lidar_collision', 'siid': 8, 'piid': 23}, + {'did': 'station_key', 'siid': 8, 'piid': 24}, + {'did': 'station_led', 'siid': 8, 'piid': 25}, + {'did': 'current_audio', 'siid': 8, 'piid': 26}, + {'did': 'station_type', 'siid': 8, 'piid': 29}, + {'did': 'volume', 'siid': 9, 'piid': 1}, + {'did': 'mute', 'siid': 9, 'piid': 2} + ] """ self.data = data @@ -301,9 +301,18 @@ def dust_collection_frequency(self) -> int: @property def timing(self) -> str: - """Repeated cleaning - Example: {"time":[[32400,1,3,0,[1,2,3,4,5],0,[12,10],null],[57600,0,1,2,[1,2,3,4,5,6,0],2,[],null]],"tz":2,"tzs":7200} - Cleaning 1: + """Repeated cleaning. + + Example:: + + {"time":[ + [32400,1,3,0,[1,2,3,4,5],0,[12,10],null], + [57600,0,1,2,[1,2,3,4,5,6,0],2,[],null] + ], + "tz":2,"tzs":7200 + } + + Cleaning 1:: 32400 = startTime(9:00) 1=Enabled 3=FanSpeed.Strong @@ -312,7 +321,8 @@ def timing(self) -> str: 0=WaterLevel [12,10]=List of rooms null: ?Might be related to "Customize"? - Cleaning 2: + + Cleaning 2:: 57600 = startTime(16:00) 0=Disabled 1=FanSpeed.Silent @@ -321,6 +331,7 @@ def timing(self) -> str: 2=WaterLevel.Second []=All rooms null: ?Might be related to "Customize"? + tz/tzs= time-zone """ return self.data["timing"] diff --git a/miio/push_server/server.py b/miio/push_server/server.py index 66816fbf3..ed1bdfea1 100644 --- a/miio/push_server/server.py +++ b/miio/push_server/server.py @@ -30,27 +30,27 @@ class PushServer: """Async UDP push server acting as a fake miio device to handle event notifications from other devices. - Assuming you already have a miio_device class initialized: - - # First create the push server - push_server = PushServer(miio_device.ip) - # Then start the server - await push_server.start() - # Register the miio device to the server and specify a callback function to receive events for this device - # The callback function schould have the form of "def callback_func(source_device, action, params):" - push_server.register_miio_device(miio_device, callback_func) - # create a EventInfo object with the information about the event you which to subscribe to (information taken from packet captures of automations in the mi home app) - event_info = EventInfo( - action="alarm_triggering", - extra="[1,19,1,111,[0,1],2,0]", - trigger_token=miio_device.token, - ) - # Send a message to the miio_device to subscribe for the event to receive messages on the push_server - await loop.run_in_executor(None, push_server.subscribe_event, miio_device, event_info) - # Now you will see the callback function beeing called whenever the event occurs - await asyncio.sleep(30) - # When done stop the push_server, this will send messages to all subscribed miio_devices to unsubscribe all events - push_server.stop() + Assuming you already have a miio_device class initialized:: + + # First create the push server + push_server = PushServer(miio_device.ip) + # Then start the server + await push_server.start() + # Register the miio device to the server and specify a callback function to receive events for this device + # The callback function schould have the form of "def callback_func(source_device, action, params):" + push_server.register_miio_device(miio_device, callback_func) + # create a EventInfo object with the information about the event you which to subscribe to (information taken from packet captures of automations in the mi home app) + event_info = EventInfo( + action="alarm_triggering", + extra="[1,19,1,111,[0,1],2,0]", + trigger_token=miio_device.token, + ) + # Send a message to the miio_device to subscribe for the event to receive messages on the push_server + await loop.run_in_executor(None, push_server.subscribe_event, miio_device, event_info) + # Now you will see the callback function beeing called whenever the event occurs + await asyncio.sleep(30) + # When done stop the push_server, this will send messages to all subscribed miio_devices to unsubscribe all events + push_server.stop() """ def __init__(self, device_ip): diff --git a/miio/updater.py b/miio/updater.py index f356c11bd..a14194fda 100644 --- a/miio/updater.py +++ b/miio/updater.py @@ -15,6 +15,11 @@ def __init__(self, request, client_address, server): super().__init__(request, client_address, server) + def send_error(self, *args, **kwargs): + """Dummy override to avoid crashing sphinx builds on invalid upstream + docstring.""" + return super().send_error(*args, **kwargs) + def handle_one_request(self): self.server.got_request = True self.raw_requestline = self.rfile.readline() @@ -33,7 +38,7 @@ def handle_one_request(self): class OneShotServer: """A simple HTTP server for serving an update file. - The server will be started in an emphemeral port, and will only accept a single + The server will be started in an ephemeral port, and will only accept a single request to keep it simple. """