From 2f6c062f44cd34f3fa83f450653a502a896d596a Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Fri, 16 Jan 2026 07:25:57 -0800 Subject: [PATCH 1/6] feat: Add StatusField support for DeviceFeatures --- device_info.yaml | 1022 ++++++++--------- roborock/data/v1/v1_containers.py | 27 +- roborock/devices/traits/v1/device_features.py | 11 +- .../__snapshots__/test_device_features.ambr | 3 + tests/devices/traits/v1/fixtures.py | 13 +- tests/mock_data.py | 14 + 6 files changed, 563 insertions(+), 527 deletions(-) diff --git a/device_info.yaml b/device_info.yaml index 3125fcee..e87e38d2 100644 --- a/device_info.yaml +++ b/device_info.yaml @@ -1,24 +1,24 @@ roborock.vacuum.a117: - protocol_version: '1.0' + protocol_version: "1.0" product_nickname: PEARLPLUSS new_feature_info: 4499197267967999 new_feature_info_str: 000000000000000BC2FF8F7F7EFEFFFF feature_info: - - 111 - - 112 - - 113 - - 114 - - 115 - - 116 - - 117 - - 118 - - 119 - - 120 - - 121 - - 122 - - 123 - - 124 - - 125 + - 111 + - 112 + - 113 + - 114 + - 115 + - 116 + - 117 + - 118 + - 119 + - 120 + - 121 + - 122 + - 123 + - 124 + - 125 product: id: 3hVxBJoGbDP2kv93Pcc1pb name: Roborock Qrevo Master @@ -26,119 +26,119 @@ roborock.vacuum.a117: category: robot.vacuum.cleaner capability: 0 schema: - - id: 101 - name: rpc_request - code: rpc_request - mode: rw - type: RAW - - id: 102 - name: rpc_response - code: rpc_response - mode: rw - type: RAW - - id: 120 - name: "\u9519\u8BEF\u4EE3\u7801" - code: error_code - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 121 - name: "\u8BBE\u5907\u72B6\u6001" - code: state - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 122 - name: "\u8BBE\u5907\u7535\u91CF" - code: battery - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 123 - name: "\u6E05\u626B\u6A21\u5F0F" - code: fan_power - mode: rw - type: ENUM - property: '{"range": [""]}' - - id: 124 - name: "\u62D6\u5730\u6A21\u5F0F" - code: water_box_mode - mode: rw - type: ENUM - property: '{"range": [""]}' - - id: 125 - name: "\u4E3B\u5237\u5BFF\u547D" - code: main_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 126 - name: "\u8FB9\u5237\u5BFF\u547D" - code: side_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 127 - name: "\u6EE4\u7F51\u5BFF\u547D" - code: filter_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 128 - name: "\u989D\u5916\u72B6\u6001" - code: additional_props - mode: ro - type: RAW - - id: 130 - name: "\u5B8C\u6210\u4E8B\u4EF6" - code: task_complete - mode: ro - type: RAW - - id: 131 - name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_low_power - mode: ro - type: RAW - - id: 132 - name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_in_motion - mode: ro - type: RAW - - id: 133 - name: "\u5145\u7535\u72B6\u6001" - code: charge_status - mode: ro - type: RAW - - id: 134 - name: "\u70D8\u5E72\u72B6\u6001" - code: drying_status - mode: ro - type: RAW - - id: 135 - name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" - code: offline_status - mode: ro - type: RAW + - id: 101 + name: rpc_request + code: rpc_request + mode: rw + type: RAW + - id: 102 + name: rpc_response + code: rpc_response + mode: rw + type: RAW + - id: 120 + name: "\u9519\u8BEF\u4EE3\u7801" + code: error_code + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 121 + name: "\u8BBE\u5907\u72B6\u6001" + code: state + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 122 + name: "\u8BBE\u5907\u7535\u91CF" + code: battery + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 123 + name: "\u6E05\u626B\u6A21\u5F0F" + code: fan_power + mode: rw + type: ENUM + property: '{"range": [""]}' + - id: 124 + name: "\u62D6\u5730\u6A21\u5F0F" + code: water_box_mode + mode: rw + type: ENUM + property: '{"range": [""]}' + - id: 125 + name: "\u4E3B\u5237\u5BFF\u547D" + code: main_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 126 + name: "\u8FB9\u5237\u5BFF\u547D" + code: side_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 127 + name: "\u6EE4\u7F51\u5BFF\u547D" + code: filter_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 128 + name: "\u989D\u5916\u72B6\u6001" + code: additional_props + mode: ro + type: RAW + - id: 130 + name: "\u5B8C\u6210\u4E8B\u4EF6" + code: task_complete + mode: ro + type: RAW + - id: 131 + name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_low_power + mode: ro + type: RAW + - id: 132 + name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_in_motion + mode: ro + type: RAW + - id: 133 + name: "\u5145\u7535\u72B6\u6001" + code: charge_status + mode: ro + type: RAW + - id: 134 + name: "\u70D8\u5E72\u72B6\u6001" + code: drying_status + mode: ro + type: RAW + - id: 135 + name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" + code: offline_status + mode: ro + type: RAW roborock.vacuum.a15: - protocol_version: '1.0' + protocol_version: "1.0" product_nickname: TANOSS new_feature_info: 636084721975295 - new_feature_info_str: '0000000000002000' + new_feature_info_str: "0000000000002000" feature_info: - - 111 - - 112 - - 113 - - 114 - - 115 - - 116 - - 117 - - 118 - - 119 - - 120 - - 122 - - 123 - - 124 - - 125 + - 111 + - 112 + - 113 + - 114 + - 115 + - 116 + - 117 + - 118 + - 119 + - 120 + - 122 + - 123 + - 124 + - 125 product: id: 1YYW18rpgyAJTISwb1NM91 name: S7 @@ -146,120 +146,120 @@ roborock.vacuum.a15: category: robot.vacuum.cleaner capability: 0 schema: - - id: 101 - name: rpc_request - code: rpc_request - mode: rw - type: RAW - - id: 102 - name: rpc_response - code: rpc_response - mode: rw - type: RAW - - id: 120 - name: "\u9519\u8BEF\u4EE3\u7801" - code: error_code - mode: ro - type: ENUM - property: '{"range": []}' - - id: 121 - name: "\u8BBE\u5907\u72B6\u6001" - code: state - mode: ro - type: ENUM - property: '{"range": []}' - - id: 122 - name: "\u8BBE\u5907\u7535\u91CF" - code: battery - mode: ro - type: ENUM - property: '{"range": []}' - - id: 123 - name: "\u6E05\u626B\u6A21\u5F0F" - code: fan_power - mode: rw - type: ENUM - property: '{"range": []}' - - id: 124 - name: "\u62D6\u5730\u6A21\u5F0F" - code: water_box_mode - mode: rw - type: ENUM - property: '{"range": []}' - - id: 125 - name: "\u4E3B\u5237\u5BFF\u547D" - code: main_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' - - id: 126 - name: "\u8FB9\u5237\u5BFF\u547D" - code: side_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' - - id: 127 - name: "\u6EE4\u7F51\u5BFF\u547D" - code: filter_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' - - id: 128 - name: "\u989D\u5916\u72B6\u6001" - code: additional_props - mode: ro - type: RAW - - id: 130 - name: "\u5B8C\u6210\u4E8B\u4EF6" - code: task_complete - mode: ro - type: RAW - - id: 131 - name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_low_power - mode: ro - type: RAW - - id: 132 - name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_in_motion - mode: ro - type: RAW - - id: 133 - name: "\u5145\u7535\u72B6\u6001" - code: charge_status - mode: ro - type: RAW - - id: 134 - name: "\u70D8\u5E72\u72B6\u6001" - code: drying_status - mode: ro - type: RAW - - id: 135 - name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" - code: offline_status - mode: ro - type: RAW + - id: 101 + name: rpc_request + code: rpc_request + mode: rw + type: RAW + - id: 102 + name: rpc_response + code: rpc_response + mode: rw + type: RAW + - id: 120 + name: "\u9519\u8BEF\u4EE3\u7801" + code: error_code + mode: ro + type: ENUM + property: '{"range": []}' + - id: 121 + name: "\u8BBE\u5907\u72B6\u6001" + code: state + mode: ro + type: ENUM + property: '{"range": []}' + - id: 122 + name: "\u8BBE\u5907\u7535\u91CF" + code: battery + mode: ro + type: ENUM + property: '{"range": []}' + - id: 123 + name: "\u6E05\u626B\u6A21\u5F0F" + code: fan_power + mode: rw + type: ENUM + property: '{"range": []}' + - id: 124 + name: "\u62D6\u5730\u6A21\u5F0F" + code: water_box_mode + mode: rw + type: ENUM + property: '{"range": []}' + - id: 125 + name: "\u4E3B\u5237\u5BFF\u547D" + code: main_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' + - id: 126 + name: "\u8FB9\u5237\u5BFF\u547D" + code: side_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' + - id: 127 + name: "\u6EE4\u7F51\u5BFF\u547D" + code: filter_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' + - id: 128 + name: "\u989D\u5916\u72B6\u6001" + code: additional_props + mode: ro + type: RAW + - id: 130 + name: "\u5B8C\u6210\u4E8B\u4EF6" + code: task_complete + mode: ro + type: RAW + - id: 131 + name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_low_power + mode: ro + type: RAW + - id: 132 + name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_in_motion + mode: ro + type: RAW + - id: 133 + name: "\u5145\u7535\u72B6\u6001" + code: charge_status + mode: ro + type: RAW + - id: 134 + name: "\u70D8\u5E72\u72B6\u6001" + code: drying_status + mode: ro + type: RAW + - id: 135 + name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" + code: offline_status + mode: ro + type: RAW roborock.vacuum.a87: - protocol_version: '1.0' + protocol_version: "1.0" product_nickname: PEARLPLUS new_feature_info: 4499197267967999 new_feature_info_str: 508A977F7EFEFFFF feature_info: - - 111 - - 112 - - 113 - - 114 - - 115 - - 116 - - 117 - - 118 - - 119 - - 120 - - 121 - - 122 - - 123 - - 124 - - 125 + - 111 + - 112 + - 113 + - 114 + - 115 + - 116 + - 117 + - 118 + - 119 + - 120 + - 121 + - 122 + - 123 + - 124 + - 125 product: id: 5gUei3OIJIXVD3eD85Balg name: Roborock Qrevo MaxV @@ -267,119 +267,119 @@ roborock.vacuum.a87: category: robot.vacuum.cleaner capability: 0 schema: - - id: 101 - name: rpc_request - code: rpc_request - mode: rw - type: RAW - - id: 102 - name: rpc_response - code: rpc_response - mode: rw - type: RAW - - id: 120 - name: "\u9519\u8BEF\u4EE3\u7801" - code: error_code - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 121 - name: "\u8BBE\u5907\u72B6\u6001" - code: state - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 122 - name: "\u8BBE\u5907\u7535\u91CF" - code: battery - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 123 - name: "\u6E05\u626B\u6A21\u5F0F" - code: fan_power - mode: rw - type: ENUM - property: '{"range": [""]}' - - id: 124 - name: "\u62D6\u5730\u6A21\u5F0F" - code: water_box_mode - mode: rw - type: ENUM - property: '{"range": [""]}' - - id: 125 - name: "\u4E3B\u5237\u5BFF\u547D" - code: main_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 126 - name: "\u8FB9\u5237\u5BFF\u547D" - code: side_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 127 - name: "\u6EE4\u7F51\u5BFF\u547D" - code: filter_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 128 - name: "\u989D\u5916\u72B6\u6001" - code: additional_props - mode: ro - type: RAW - - id: 130 - name: "\u5B8C\u6210\u4E8B\u4EF6" - code: task_complete - mode: ro - type: RAW - - id: 131 - name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_low_power - mode: ro - type: RAW - - id: 132 - name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_in_motion - mode: ro - type: RAW - - id: 133 - name: "\u5145\u7535\u72B6\u6001" - code: charge_status - mode: ro - type: RAW - - id: 134 - name: "\u70D8\u5E72\u72B6\u6001" - code: drying_status - mode: ro - type: RAW - - id: 135 - name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" - code: offline_status - mode: ro - type: RAW + - id: 101 + name: rpc_request + code: rpc_request + mode: rw + type: RAW + - id: 102 + name: rpc_response + code: rpc_response + mode: rw + type: RAW + - id: 120 + name: "\u9519\u8BEF\u4EE3\u7801" + code: error_code + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 121 + name: "\u8BBE\u5907\u72B6\u6001" + code: state + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 122 + name: "\u8BBE\u5907\u7535\u91CF" + code: battery + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 123 + name: "\u6E05\u626B\u6A21\u5F0F" + code: fan_power + mode: rw + type: ENUM + property: '{"range": [""]}' + - id: 124 + name: "\u62D6\u5730\u6A21\u5F0F" + code: water_box_mode + mode: rw + type: ENUM + property: '{"range": [""]}' + - id: 125 + name: "\u4E3B\u5237\u5BFF\u547D" + code: main_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 126 + name: "\u8FB9\u5237\u5BFF\u547D" + code: side_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 127 + name: "\u6EE4\u7F51\u5BFF\u547D" + code: filter_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 128 + name: "\u989D\u5916\u72B6\u6001" + code: additional_props + mode: ro + type: RAW + - id: 130 + name: "\u5B8C\u6210\u4E8B\u4EF6" + code: task_complete + mode: ro + type: RAW + - id: 131 + name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_low_power + mode: ro + type: RAW + - id: 132 + name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_in_motion + mode: ro + type: RAW + - id: 133 + name: "\u5145\u7535\u72B6\u6001" + code: charge_status + mode: ro + type: RAW + - id: 134 + name: "\u70D8\u5E72\u72B6\u6001" + code: drying_status + mode: ro + type: RAW + - id: 135 + name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" + code: offline_status + mode: ro + type: RAW roborock.vacuum.s5e: - protocol_version: '1.0' + protocol_version: "1.0" product_nickname: RUBYSLITE new_feature_info: 633887780925447 - new_feature_info_str: '0000000000002000' + new_feature_info_str: "0000000000002000" feature_info: - - 111 - - 112 - - 113 - - 114 - - 115 - - 116 - - 117 - - 118 - - 119 - - 120 - - 122 - - 123 - - 124 - - 125 + - 111 + - 112 + - 113 + - 114 + - 115 + - 116 + - 117 + - 118 + - 119 + - 120 + - 122 + - 123 + - 124 + - 125 roborock.vacuum.sc05: protocol_version: B01 product_nickname: PEARLPLUS @@ -390,171 +390,171 @@ roborock.vacuum.sc05: category: robot.vacuum.cleaner capability: 0 schema: - - id: 101 - name: RPC Request - code: rpc_request - mode: rw - type: RAW - property: 'null' - - id: 102 - name: RPC Response - code: rpc_response - mode: rw - type: RAW - property: 'null' - - id: 120 - name: "\u9519\u8BEF\u4EE3\u7801" - code: error_code - mode: ro - type: ENUM - property: 'null' - - id: 121 - name: "\u8BBE\u5907\u72B6\u6001" - code: state - mode: ro - type: VALUE - property: 'null' - - id: 122 - name: "\u8BBE\u5907\u7535\u91CF" - code: battery - mode: ro - type: ENUM - property: 'null' - - id: 123 - name: "\u5438\u529B\u6863\u4F4D" - code: fan_power - mode: rw - type: ENUM - property: 'null' - - id: 124 - name: "\u62D6\u5730\u6863\u4F4D" - code: water_box_mode - mode: rw - type: RAW - property: 'null' - - id: 125 - name: "\u4E3B\u5237\u5BFF\u547D" - code: main_brush_life - mode: ro - type: ENUM - property: 'null' - - id: 126 - name: "\u8FB9\u5237\u5BFF\u547D" - code: side_brush_life - mode: ro - type: ENUM - property: 'null' - - id: 127 - name: "\u6EE4\u7F51\u5BFF\u547D" - code: filter_life - mode: ro - type: ENUM - property: 'null' - - id: 135 - name: "\u79BB\u7EBF\u539F\u56E0" - code: offline_status - mode: ro - type: ENUM - property: 'null' - - id: 136 - name: "\u6E05\u6D01\u6B21\u6570" - code: clean_times - mode: rw - type: ENUM - property: 'null' - - id: 137 - name: "\u626B\u62D6\u6A21\u5F0F" - code: cleaning_preference - mode: rw - type: ENUM - property: 'null' - - id: 138 - name: "\u6E05\u6D01\u4EFB\u52A1\u7C7B\u578B" - code: clean_task_type - mode: ro - type: ENUM - property: 'null' - - id: 139 - name: "\u8FD4\u56DE\u57FA\u7AD9\u7C7B\u578B" - code: back_type - mode: ro - type: ENUM - property: 'null' - - id: 141 - name: "\u6E05\u6D01\u8FDB\u5EA6" - code: cleaning_progress - mode: ro - type: ENUM - property: 'null' - - id: 142 - name: "\u7A9C\u8D27\u4FE1\u606F" - code: fc_state - mode: ro - type: RAW - property: 'null' - - id: 201 - name: "\u542F\u52A8\u6E05\u6D01\u4EFB\u52A1" - code: start_clean_task - mode: wo - type: ENUM - property: 'null' - - id: 202 - name: "\u8FD4\u56DE\u57FA\u7AD9\u4EFB\u52A1" - code: start_back_dock_task - mode: wo - type: ENUM - property: 'null' - - id: 203 - name: "\u542F\u52A8\u57FA\u7AD9\u4EFB\u52A1" - code: start_dock_task - mode: wo - type: ENUM - property: 'null' - - id: 204 - name: "\u6682\u505C\u4EFB\u52A1" - code: pause - mode: wo - type: RAW - property: 'null' - - id: 205 - name: "\u7EE7\u7EED\u4EFB\u52A1" - code: resume - mode: wo - type: RAW - property: 'null' - - id: 206 - name: "\u7ED3\u675F\u4EFB\u52A1" - code: stop - mode: wo - type: RAW - property: 'null' - - id: 10000 - name: request_cmd - code: request_cmd - mode: wo - type: RAW - property: 'null' - - id: 10001 - name: response_cmd - code: response_cmd - mode: ro - type: RAW - property: 'null' - - id: 10002 - name: request_map - code: request_map - mode: ro - type: RAW - property: 'null' - - id: 10003 - name: response_map - code: response_map - mode: ro - type: RAW - property: 'null' - - id: 10004 - name: event_report - code: event_report - mode: rw - type: RAW - property: 'null' + - id: 101 + name: RPC Request + code: rpc_request + mode: rw + type: RAW + property: "null" + - id: 102 + name: RPC Response + code: rpc_response + mode: rw + type: RAW + property: "null" + - id: 120 + name: "\u9519\u8BEF\u4EE3\u7801" + code: error_code + mode: ro + type: ENUM + property: "null" + - id: 121 + name: "\u8BBE\u5907\u72B6\u6001" + code: state + mode: ro + type: VALUE + property: "null" + - id: 122 + name: "\u8BBE\u5907\u7535\u91CF" + code: battery + mode: ro + type: ENUM + property: "null" + - id: 123 + name: "\u5438\u529B\u6863\u4F4D" + code: fan_power + mode: rw + type: ENUM + property: "null" + - id: 124 + name: "\u62D6\u5730\u6863\u4F4D" + code: water_box_mode + mode: rw + type: RAW + property: "null" + - id: 125 + name: "\u4E3B\u5237\u5BFF\u547D" + code: main_brush_life + mode: ro + type: ENUM + property: "null" + - id: 126 + name: "\u8FB9\u5237\u5BFF\u547D" + code: side_brush_life + mode: ro + type: ENUM + property: "null" + - id: 127 + name: "\u6EE4\u7F51\u5BFF\u547D" + code: filter_life + mode: ro + type: ENUM + property: "null" + - id: 135 + name: "\u79BB\u7EBF\u539F\u56E0" + code: offline_status + mode: ro + type: ENUM + property: "null" + - id: 136 + name: "\u6E05\u6D01\u6B21\u6570" + code: clean_times + mode: rw + type: ENUM + property: "null" + - id: 137 + name: "\u626B\u62D6\u6A21\u5F0F" + code: cleaning_preference + mode: rw + type: ENUM + property: "null" + - id: 138 + name: "\u6E05\u6D01\u4EFB\u52A1\u7C7B\u578B" + code: clean_task_type + mode: ro + type: ENUM + property: "null" + - id: 139 + name: "\u8FD4\u56DE\u57FA\u7AD9\u7C7B\u578B" + code: back_type + mode: ro + type: ENUM + property: "null" + - id: 141 + name: "\u6E05\u6D01\u8FDB\u5EA6" + code: cleaning_progress + mode: ro + type: ENUM + property: "null" + - id: 142 + name: "\u7A9C\u8D27\u4FE1\u606F" + code: fc_state + mode: ro + type: RAW + property: "null" + - id: 201 + name: "\u542F\u52A8\u6E05\u6D01\u4EFB\u52A1" + code: start_clean_task + mode: wo + type: ENUM + property: "null" + - id: 202 + name: "\u8FD4\u56DE\u57FA\u7AD9\u4EFB\u52A1" + code: start_back_dock_task + mode: wo + type: ENUM + property: "null" + - id: 203 + name: "\u542F\u52A8\u57FA\u7AD9\u4EFB\u52A1" + code: start_dock_task + mode: wo + type: ENUM + property: "null" + - id: 204 + name: "\u6682\u505C\u4EFB\u52A1" + code: pause + mode: wo + type: RAW + property: "null" + - id: 205 + name: "\u7EE7\u7EED\u4EFB\u52A1" + code: resume + mode: wo + type: RAW + property: "null" + - id: 206 + name: "\u7ED3\u675F\u4EFB\u52A1" + code: stop + mode: wo + type: RAW + property: "null" + - id: 10000 + name: request_cmd + code: request_cmd + mode: wo + type: RAW + property: "null" + - id: 10001 + name: response_cmd + code: response_cmd + mode: ro + type: RAW + property: "null" + - id: 10002 + name: request_map + code: request_map + mode: ro + type: RAW + property: "null" + - id: 10003 + name: response_map + code: response_map + mode: ro + type: RAW + property: "null" + - id: 10004 + name: event_report + code: event_report + mode: rw + type: RAW + property: "null" diff --git a/roborock/data/v1/v1_containers.py b/roborock/data/v1/v1_containers.py index cf988590..09050186 100644 --- a/roborock/data/v1/v1_containers.py +++ b/roborock/data/v1/v1_containers.py @@ -103,8 +103,10 @@ class StatusField(FieldNameBase): to understand if a feature is supported by the device using `is_field_supported`. The enum values are names of fields in the `Status` class. Each field is - annotated with `requires_schema_code` metadata to map the field to a schema - code in the product schema, which may have a different name than the field/attribute name. + annotated with one of the following: + - `requires_schema_code` metadata to map the field to a schema code in the + product schema, which may have a different name than the field/attribute name. + - `requires_supported_feature` metadata to map the field to a field in `DeviceFeatures`. """ STATE = "state" @@ -113,20 +115,25 @@ class StatusField(FieldNameBase): WATER_BOX_MODE = "water_box_mode" CHARGE_STATUS = "charge_status" DRY_STATUS = "dry_status" + CLEAN_PERCENT = "clean_percent" -def _requires_schema_code(requires_schema_code: str, default=None) -> Any: +def _requires_schema_code(requires_schema_code: str, default: Any = None) -> Any: return field(metadata={"requires_schema_code": requires_schema_code}, default=default) +def _requires_supported_feature(requires_supported_feature: str, default: Any = None) -> Any: + return field(metadata={"requires_supported_feature": requires_supported_feature}, default=default) + + @dataclass class Status(RoborockBase): """This status will be deprecated in favor of StatusV2.""" msg_ver: int | None = None msg_seq: int | None = None - state: RoborockStateCode | None = _requires_schema_code("state", default=None) - battery: int | None = _requires_schema_code("battery", default=None) + state: RoborockStateCode | None = _requires_schema_code("state") + battery: int | None = _requires_schema_code("battery") clean_time: int | None = None clean_area: int | None = None error_code: RoborockErrorCode | None = None @@ -139,12 +146,12 @@ class Status(RoborockBase): back_type: int | None = None wash_phase: int | None = None wash_ready: int | None = None - fan_power: RoborockFanPowerCode | None = _requires_schema_code("fan_power", default=None) + fan_power: RoborockFanPowerCode | None = _requires_schema_code("fan_power") dnd_enabled: int | None = None map_status: int | None = None is_locating: int | None = None lock_status: int | None = None - water_box_mode: RoborockMopIntensityCode | None = _requires_schema_code("water_box_mode", default=None) + water_box_mode: RoborockMopIntensityCode | None = _requires_schema_code("water_box_mode") water_box_carriage_status: int | None = None mop_forbidden_enable: int | None = None camera_status: int | None = None @@ -162,15 +169,15 @@ class Status(RoborockBase): collision_avoid_status: int | None = None switch_map_mode: int | None = None dock_error_status: RoborockDockErrorCode | None = None - charge_status: int | None = _requires_schema_code("charge_status", default=None) + charge_status: int | None = _requires_schema_code("charge_status") unsave_map_reason: int | None = None unsave_map_flag: int | None = None wash_status: int | None = None distance_off: int | None = None in_warmup: int | None = None - dry_status: int | None = _requires_schema_code("drying_status", default=None) + dry_status: int | None = _requires_schema_code("drying_status") rdt: int | None = None - clean_percent: int | None = None + clean_percent: int | None = _requires_supported_feature("is_support_clean_estimate") rss: int | None = None dss: int | None = None common_status: int | None = None diff --git a/roborock/devices/traits/v1/device_features.py b/roborock/devices/traits/v1/device_features.py index ed6e186e..1f325757 100644 --- a/roborock/devices/traits/v1/device_features.py +++ b/roborock/devices/traits/v1/device_features.py @@ -61,11 +61,12 @@ def is_field_supported(self, cls: type[RoborockBase], field_name: FieldNameBase) raise ValueError(f"Field {field_name} not found in {cls}") requires_schema_code = dataclass_field.metadata.get("requires_schema_code", None) - if requires_schema_code is None: - # We assume the field is supported - return True - # If the field requires a protocol that is not supported, we return False - return requires_schema_code in self._product.supported_schema_codes + if requires_schema_code is not None: + return requires_schema_code in self._product.supported_schema_codes + requires_supported_feature = dataclass_field.metadata.get("requires_supported_feature", None) + if requires_supported_feature is not None: + return getattr(self, requires_supported_feature) + return True async def refresh(self) -> None: """Refresh the contents of this trait. diff --git a/tests/devices/traits/v1/__snapshots__/test_device_features.ambr b/tests/devices/traits/v1/__snapshots__/test_device_features.ambr index 9b2a4827..924a9a3b 100644 --- a/tests/devices/traits/v1/__snapshots__/test_device_features.ambr +++ b/tests/devices/traits/v1/__snapshots__/test_device_features.ambr @@ -3,6 +3,7 @@ dict({ 'battery': True, 'charge_status': True, + 'clean_percent': False, 'dry_status': True, 'fan_power': True, 'state': True, @@ -13,6 +14,7 @@ dict({ 'battery': True, 'charge_status': True, + 'clean_percent': False, 'dry_status': True, 'fan_power': True, 'state': True, @@ -23,6 +25,7 @@ dict({ 'battery': True, 'charge_status': True, + 'clean_percent': False, 'dry_status': True, 'fan_power': True, 'state': True, diff --git a/tests/devices/traits/v1/fixtures.py b/tests/devices/traits/v1/fixtures.py index 08397493..fc847b52 100644 --- a/tests/devices/traits/v1/fixtures.py +++ b/tests/devices/traits/v1/fixtures.py @@ -1,6 +1,7 @@ """Fixtures for V1 trait tests.""" from copy import deepcopy +from typing import Any from unittest.mock import AsyncMock import pytest @@ -107,16 +108,26 @@ def dock_type_code_fixture(request: pytest.FixtureRequest) -> RoborockDockTypeCo return RoborockDockTypeCode.s7_max_ultra_dock +@pytest.fixture(name="mock_app_get_init_status") +def mock_app_get_init_status_fixture(device_info: HomeDataDevice, products: list[HomeDataProduct]) -> dict[str, Any]: + """Fixture to provide a DeviceFeaturesInfo instance for tests.""" + product = next(filter(lambda product: product.id == device_info.product_id, products)) + if not product: + raise ValueError(f"Product {device_info.product_id} not found") + return mock_data.APP_GET_INIT_STATUS + + @pytest.fixture(autouse=True) async def discover_features_fixture( device: RoborockDevice, mock_rpc_channel: AsyncMock, + mock_app_get_init_status: dict[str, Any], dock_type_code: RoborockDockTypeCode | None, ) -> None: """Fixture to handle device feature discovery.""" assert device.v1_properties mock_rpc_channel.send_command.side_effect = [ - [mock_data.APP_GET_INIT_STATUS], + [mock_app_get_init_status], { **mock_data.STATUS, "dock_type": dock_type_code, diff --git a/tests/mock_data.py b/tests/mock_data.py index 73292c3b..7bcaddd2 100644 --- a/tests/mock_data.py +++ b/tests/mock_data.py @@ -5,6 +5,8 @@ import pathlib from typing import Any +import yaml + # All data is based on a U.S. customer with a Roborock S7 MaxV Ultra USER_EMAIL = "user@domain.com" @@ -141,6 +143,18 @@ ZEO_ONE_DEVICE_DATA = DEVICES["home_data_device_zeo_one.json"] SAROS_10R_DEVICE_DATA = DEVICES["home_data_device_saros_10r.json"] +# Additional Device Features info from YAML. In the future we can merge these +# all into a similar format or get from diagnostrics. +_DEVICE_INFO_DATA = yaml.safe_load(pathlib.Path("device_info.yaml").read_text()) +DEVICE_INFO = { + product_model: { + "new_feature_info": data.get("New Feature Info"), + "new_feature_info_str": data.get("New Feature Info Str"), + "feature_info": data.get("Feature Info"), + } + for product_model, data in _DEVICE_INFO_DATA.items() +} + HOME_DATA_RAW: dict[str, Any] = { "id": 123456, From 76590f8a47c3747fc9f96effc7ac296522bf39a5 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Sun, 22 Mar 2026 09:54:38 -0700 Subject: [PATCH 2/6] chore: Update device snapshots --- .../traits/v1/__snapshots__/test_device_features.ambr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/devices/traits/v1/__snapshots__/test_device_features.ambr b/tests/devices/traits/v1/__snapshots__/test_device_features.ambr index 924a9a3b..a15f714c 100644 --- a/tests/devices/traits/v1/__snapshots__/test_device_features.ambr +++ b/tests/devices/traits/v1/__snapshots__/test_device_features.ambr @@ -3,7 +3,7 @@ dict({ 'battery': True, 'charge_status': True, - 'clean_percent': False, + 'clean_percent': True, 'dry_status': True, 'fan_power': True, 'state': True, @@ -14,7 +14,7 @@ dict({ 'battery': True, 'charge_status': True, - 'clean_percent': False, + 'clean_percent': True, 'dry_status': True, 'fan_power': True, 'state': True, @@ -25,7 +25,7 @@ dict({ 'battery': True, 'charge_status': True, - 'clean_percent': False, + 'clean_percent': True, 'dry_status': True, 'fan_power': True, 'state': True, From f74388568782ad64bc86cd6c837100714bbb56dc Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Sun, 22 Mar 2026 11:34:09 -0700 Subject: [PATCH 3/6] feat: Initialize only boolean fields in `DeviceFeatures` and enhance `APP_GET_INIT_STATUS` mock data with model-specific feature information --- .pre-commit-config.yaml | 88 +++++++++---------- roborock/device_features.py | 6 +- roborock/devices/traits/v1/device_features.py | 5 +- tests/devices/traits/v1/fixtures.py | 14 ++- tests/mock_data.py | 12 +-- 5 files changed, 67 insertions(+), 58 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 755f4f90..2aeed7d4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,51 +1,51 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks exclude: "CHANGELOG.md" -default_stages: [ pre-commit ] +default_stages: [pre-commit] repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 - hooks: - - id: debug-statements - - id: check-builtin-literals - - id: check-case-conflict - - id: check-docstring-first - - id: check-json - - id: check-toml - - id: check-yaml - - id: detect-private-key - - id: end-of-file-fixer - - id: trailing-whitespace - - repo: https://github.com/astral-sh/uv-pre-commit - rev: 0.9.1 - hooks: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: debug-statements + - id: check-builtin-literals + - id: check-case-conflict + - id: check-docstring-first + - id: check-json + - id: check-toml + - id: check-yaml + - id: detect-private-key + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/astral-sh/uv-pre-commit + rev: 0.9.1 + hooks: - id: uv-sync args: ["--locked", "--all-packages"] - - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 - hooks: - - id: codespell - exclude: > - (?x)^( - .*\.ambr - )$ - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.13.2 - hooks: - - id: ruff-format - - id: ruff - args: - - --fix - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.1 - hooks: - - id: mypy - exclude: cli.py - additional_dependencies: [ "types-paho-mqtt" ] - - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook - rev: v9.23.0 - hooks: - - id: commitlint - stages: [commit-msg] - additional_dependencies: ['@commitlint/config-conventional'] + - repo: https://github.com/codespell-project/codespell + rev: v2.2.6 + hooks: + - id: codespell + exclude: > + (?x)^( + .*\.ambr + )$ + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.13.2 + hooks: + - id: ruff-format + - id: ruff + args: + - --fix + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.7.1 + hooks: + - id: mypy + exclude: cli.py + additional_dependencies: ["types-paho-mqtt", "types-pyyaml"] + - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook + rev: v9.23.0 + hooks: + - id: commitlint + stages: [commit-msg] + additional_dependencies: ["@commitlint/config-conventional"] diff --git a/roborock/device_features.py b/roborock/device_features.py index b8ecf483..ef3ea19f 100644 --- a/roborock/device_features.py +++ b/roborock/device_features.py @@ -1,8 +1,6 @@ -from __future__ import annotations - from dataclasses import dataclass, field, fields from enum import IntEnum, StrEnum -from typing import Any +from typing import Any, Self from roborock.data.code_mappings import RoborockProductNickname from roborock.data.containers import RoborockBase @@ -566,7 +564,7 @@ def from_feature_flags( new_feature_info_str: str, feature_info: list[int], product_nickname: RoborockProductNickname | None, - ) -> DeviceFeatures: + ) -> Self: """Creates a DeviceFeatures instance from raw feature flags. :param new_feature_info: A int from get_init_status (sometimes can be found in homedata, but it is not always) :param new_feature_info_str: A hex string from get_init_status or home_data. diff --git a/roborock/devices/traits/v1/device_features.py b/roborock/devices/traits/v1/device_features.py index 1f325757..87971643 100644 --- a/roborock/devices/traits/v1/device_features.py +++ b/roborock/devices/traits/v1/device_features.py @@ -40,10 +40,11 @@ def __init__(self, product: HomeDataProduct, device_cache: DeviceCache) -> None: self.converter = DeviceTraitsConverter(product) self._product = product self._device_cache = device_cache - # All fields of DeviceFeatures are required. Initialize them to False + # All boolean fields of DeviceFeatures are required. Initialize them to False # so we have some known state. for field in fields(self): - setattr(self, field.name, False) + if field.type is bool: + setattr(self, field.name, False) def is_field_supported(self, cls: type[RoborockBase], field_name: FieldNameBase) -> bool: """Determines if the specified field is supported by this device. diff --git a/tests/devices/traits/v1/fixtures.py b/tests/devices/traits/v1/fixtures.py index fc847b52..19755242 100644 --- a/tests/devices/traits/v1/fixtures.py +++ b/tests/devices/traits/v1/fixtures.py @@ -110,11 +110,21 @@ def dock_type_code_fixture(request: pytest.FixtureRequest) -> RoborockDockTypeCo @pytest.fixture(name="mock_app_get_init_status") def mock_app_get_init_status_fixture(device_info: HomeDataDevice, products: list[HomeDataProduct]) -> dict[str, Any]: - """Fixture to provide a DeviceFeaturesInfo instance for tests.""" + """Fixture to provide model-specific APP_GET_INIT_STATUS data. + + Uses real device feature data from device_info.yaml when available for the + product model, falling back to the default mock data otherwise. + """ product = next(filter(lambda product: product.id == device_info.product_id, products)) if not product: raise ValueError(f"Product {device_info.product_id} not found") - return mock_data.APP_GET_INIT_STATUS + device_info_data = mock_data.DEVICE_INFO.get(product.model) + if device_info_data is None: + return mock_data.APP_GET_INIT_STATUS + return { + **mock_data.APP_GET_INIT_STATUS, + **device_info_data, + } @pytest.fixture(autouse=True) diff --git a/tests/mock_data.py b/tests/mock_data.py index 7bcaddd2..abfbd650 100644 --- a/tests/mock_data.py +++ b/tests/mock_data.py @@ -143,14 +143,14 @@ ZEO_ONE_DEVICE_DATA = DEVICES["home_data_device_zeo_one.json"] SAROS_10R_DEVICE_DATA = DEVICES["home_data_device_saros_10r.json"] -# Additional Device Features info from YAML. In the future we can merge these -# all into a similar format or get from diagnostrics. +# Additional Device Features info from YAML keyed by product model. +# Each entry contains the fields needed for APP_GET_INIT_STATUS responses. _DEVICE_INFO_DATA = yaml.safe_load(pathlib.Path("device_info.yaml").read_text()) -DEVICE_INFO = { +DEVICE_INFO: dict[str, dict[str, Any]] = { product_model: { - "new_feature_info": data.get("New Feature Info"), - "new_feature_info_str": data.get("New Feature Info Str"), - "feature_info": data.get("Feature Info"), + "new_feature_info": data.get("new_feature_info"), + "new_feature_info_str": data.get("new_feature_info_str"), + "feature_info": data.get("feature_info", []), } for product_model, data in _DEVICE_INFO_DATA.items() } From acdc98dffbc76edfb86b0f4b171e53ac4e5d96c7 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Sun, 22 Mar 2026 13:00:56 -0700 Subject: [PATCH 4/6] chore: Revert formatting changes --- .pre-commit-config.yaml | 88 ++-- device_info.yaml | 1022 +++++++++++++++++++-------------------- 2 files changed, 555 insertions(+), 555 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2aeed7d4..755f4f90 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,51 +1,51 @@ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks exclude: "CHANGELOG.md" -default_stages: [pre-commit] +default_stages: [ pre-commit ] repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 - hooks: - - id: debug-statements - - id: check-builtin-literals - - id: check-case-conflict - - id: check-docstring-first - - id: check-json - - id: check-toml - - id: check-yaml - - id: detect-private-key - - id: end-of-file-fixer - - id: trailing-whitespace - - repo: https://github.com/astral-sh/uv-pre-commit - rev: 0.9.1 - hooks: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: debug-statements + - id: check-builtin-literals + - id: check-case-conflict + - id: check-docstring-first + - id: check-json + - id: check-toml + - id: check-yaml + - id: detect-private-key + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/astral-sh/uv-pre-commit + rev: 0.9.1 + hooks: - id: uv-sync args: ["--locked", "--all-packages"] - - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 - hooks: - - id: codespell - exclude: > - (?x)^( - .*\.ambr - )$ - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.13.2 - hooks: - - id: ruff-format - - id: ruff - args: - - --fix - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.1 - hooks: - - id: mypy - exclude: cli.py - additional_dependencies: ["types-paho-mqtt", "types-pyyaml"] - - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook - rev: v9.23.0 - hooks: - - id: commitlint - stages: [commit-msg] - additional_dependencies: ["@commitlint/config-conventional"] + - repo: https://github.com/codespell-project/codespell + rev: v2.2.6 + hooks: + - id: codespell + exclude: > + (?x)^( + .*\.ambr + )$ + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.13.2 + hooks: + - id: ruff-format + - id: ruff + args: + - --fix + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.7.1 + hooks: + - id: mypy + exclude: cli.py + additional_dependencies: [ "types-paho-mqtt" ] + - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook + rev: v9.23.0 + hooks: + - id: commitlint + stages: [commit-msg] + additional_dependencies: ['@commitlint/config-conventional'] diff --git a/device_info.yaml b/device_info.yaml index e87e38d2..3125fcee 100644 --- a/device_info.yaml +++ b/device_info.yaml @@ -1,24 +1,24 @@ roborock.vacuum.a117: - protocol_version: "1.0" + protocol_version: '1.0' product_nickname: PEARLPLUSS new_feature_info: 4499197267967999 new_feature_info_str: 000000000000000BC2FF8F7F7EFEFFFF feature_info: - - 111 - - 112 - - 113 - - 114 - - 115 - - 116 - - 117 - - 118 - - 119 - - 120 - - 121 - - 122 - - 123 - - 124 - - 125 + - 111 + - 112 + - 113 + - 114 + - 115 + - 116 + - 117 + - 118 + - 119 + - 120 + - 121 + - 122 + - 123 + - 124 + - 125 product: id: 3hVxBJoGbDP2kv93Pcc1pb name: Roborock Qrevo Master @@ -26,119 +26,119 @@ roborock.vacuum.a117: category: robot.vacuum.cleaner capability: 0 schema: - - id: 101 - name: rpc_request - code: rpc_request - mode: rw - type: RAW - - id: 102 - name: rpc_response - code: rpc_response - mode: rw - type: RAW - - id: 120 - name: "\u9519\u8BEF\u4EE3\u7801" - code: error_code - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 121 - name: "\u8BBE\u5907\u72B6\u6001" - code: state - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 122 - name: "\u8BBE\u5907\u7535\u91CF" - code: battery - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 123 - name: "\u6E05\u626B\u6A21\u5F0F" - code: fan_power - mode: rw - type: ENUM - property: '{"range": [""]}' - - id: 124 - name: "\u62D6\u5730\u6A21\u5F0F" - code: water_box_mode - mode: rw - type: ENUM - property: '{"range": [""]}' - - id: 125 - name: "\u4E3B\u5237\u5BFF\u547D" - code: main_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 126 - name: "\u8FB9\u5237\u5BFF\u547D" - code: side_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 127 - name: "\u6EE4\u7F51\u5BFF\u547D" - code: filter_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 128 - name: "\u989D\u5916\u72B6\u6001" - code: additional_props - mode: ro - type: RAW - - id: 130 - name: "\u5B8C\u6210\u4E8B\u4EF6" - code: task_complete - mode: ro - type: RAW - - id: 131 - name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_low_power - mode: ro - type: RAW - - id: 132 - name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_in_motion - mode: ro - type: RAW - - id: 133 - name: "\u5145\u7535\u72B6\u6001" - code: charge_status - mode: ro - type: RAW - - id: 134 - name: "\u70D8\u5E72\u72B6\u6001" - code: drying_status - mode: ro - type: RAW - - id: 135 - name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" - code: offline_status - mode: ro - type: RAW + - id: 101 + name: rpc_request + code: rpc_request + mode: rw + type: RAW + - id: 102 + name: rpc_response + code: rpc_response + mode: rw + type: RAW + - id: 120 + name: "\u9519\u8BEF\u4EE3\u7801" + code: error_code + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 121 + name: "\u8BBE\u5907\u72B6\u6001" + code: state + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 122 + name: "\u8BBE\u5907\u7535\u91CF" + code: battery + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 123 + name: "\u6E05\u626B\u6A21\u5F0F" + code: fan_power + mode: rw + type: ENUM + property: '{"range": [""]}' + - id: 124 + name: "\u62D6\u5730\u6A21\u5F0F" + code: water_box_mode + mode: rw + type: ENUM + property: '{"range": [""]}' + - id: 125 + name: "\u4E3B\u5237\u5BFF\u547D" + code: main_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 126 + name: "\u8FB9\u5237\u5BFF\u547D" + code: side_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 127 + name: "\u6EE4\u7F51\u5BFF\u547D" + code: filter_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 128 + name: "\u989D\u5916\u72B6\u6001" + code: additional_props + mode: ro + type: RAW + - id: 130 + name: "\u5B8C\u6210\u4E8B\u4EF6" + code: task_complete + mode: ro + type: RAW + - id: 131 + name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_low_power + mode: ro + type: RAW + - id: 132 + name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_in_motion + mode: ro + type: RAW + - id: 133 + name: "\u5145\u7535\u72B6\u6001" + code: charge_status + mode: ro + type: RAW + - id: 134 + name: "\u70D8\u5E72\u72B6\u6001" + code: drying_status + mode: ro + type: RAW + - id: 135 + name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" + code: offline_status + mode: ro + type: RAW roborock.vacuum.a15: - protocol_version: "1.0" + protocol_version: '1.0' product_nickname: TANOSS new_feature_info: 636084721975295 - new_feature_info_str: "0000000000002000" + new_feature_info_str: '0000000000002000' feature_info: - - 111 - - 112 - - 113 - - 114 - - 115 - - 116 - - 117 - - 118 - - 119 - - 120 - - 122 - - 123 - - 124 - - 125 + - 111 + - 112 + - 113 + - 114 + - 115 + - 116 + - 117 + - 118 + - 119 + - 120 + - 122 + - 123 + - 124 + - 125 product: id: 1YYW18rpgyAJTISwb1NM91 name: S7 @@ -146,120 +146,120 @@ roborock.vacuum.a15: category: robot.vacuum.cleaner capability: 0 schema: - - id: 101 - name: rpc_request - code: rpc_request - mode: rw - type: RAW - - id: 102 - name: rpc_response - code: rpc_response - mode: rw - type: RAW - - id: 120 - name: "\u9519\u8BEF\u4EE3\u7801" - code: error_code - mode: ro - type: ENUM - property: '{"range": []}' - - id: 121 - name: "\u8BBE\u5907\u72B6\u6001" - code: state - mode: ro - type: ENUM - property: '{"range": []}' - - id: 122 - name: "\u8BBE\u5907\u7535\u91CF" - code: battery - mode: ro - type: ENUM - property: '{"range": []}' - - id: 123 - name: "\u6E05\u626B\u6A21\u5F0F" - code: fan_power - mode: rw - type: ENUM - property: '{"range": []}' - - id: 124 - name: "\u62D6\u5730\u6A21\u5F0F" - code: water_box_mode - mode: rw - type: ENUM - property: '{"range": []}' - - id: 125 - name: "\u4E3B\u5237\u5BFF\u547D" - code: main_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' - - id: 126 - name: "\u8FB9\u5237\u5BFF\u547D" - code: side_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' - - id: 127 - name: "\u6EE4\u7F51\u5BFF\u547D" - code: filter_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' - - id: 128 - name: "\u989D\u5916\u72B6\u6001" - code: additional_props - mode: ro - type: RAW - - id: 130 - name: "\u5B8C\u6210\u4E8B\u4EF6" - code: task_complete - mode: ro - type: RAW - - id: 131 - name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_low_power - mode: ro - type: RAW - - id: 132 - name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_in_motion - mode: ro - type: RAW - - id: 133 - name: "\u5145\u7535\u72B6\u6001" - code: charge_status - mode: ro - type: RAW - - id: 134 - name: "\u70D8\u5E72\u72B6\u6001" - code: drying_status - mode: ro - type: RAW - - id: 135 - name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" - code: offline_status - mode: ro - type: RAW + - id: 101 + name: rpc_request + code: rpc_request + mode: rw + type: RAW + - id: 102 + name: rpc_response + code: rpc_response + mode: rw + type: RAW + - id: 120 + name: "\u9519\u8BEF\u4EE3\u7801" + code: error_code + mode: ro + type: ENUM + property: '{"range": []}' + - id: 121 + name: "\u8BBE\u5907\u72B6\u6001" + code: state + mode: ro + type: ENUM + property: '{"range": []}' + - id: 122 + name: "\u8BBE\u5907\u7535\u91CF" + code: battery + mode: ro + type: ENUM + property: '{"range": []}' + - id: 123 + name: "\u6E05\u626B\u6A21\u5F0F" + code: fan_power + mode: rw + type: ENUM + property: '{"range": []}' + - id: 124 + name: "\u62D6\u5730\u6A21\u5F0F" + code: water_box_mode + mode: rw + type: ENUM + property: '{"range": []}' + - id: 125 + name: "\u4E3B\u5237\u5BFF\u547D" + code: main_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' + - id: 126 + name: "\u8FB9\u5237\u5BFF\u547D" + code: side_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' + - id: 127 + name: "\u6EE4\u7F51\u5BFF\u547D" + code: filter_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": null, "scale": 1}' + - id: 128 + name: "\u989D\u5916\u72B6\u6001" + code: additional_props + mode: ro + type: RAW + - id: 130 + name: "\u5B8C\u6210\u4E8B\u4EF6" + code: task_complete + mode: ro + type: RAW + - id: 131 + name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_low_power + mode: ro + type: RAW + - id: 132 + name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_in_motion + mode: ro + type: RAW + - id: 133 + name: "\u5145\u7535\u72B6\u6001" + code: charge_status + mode: ro + type: RAW + - id: 134 + name: "\u70D8\u5E72\u72B6\u6001" + code: drying_status + mode: ro + type: RAW + - id: 135 + name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" + code: offline_status + mode: ro + type: RAW roborock.vacuum.a87: - protocol_version: "1.0" + protocol_version: '1.0' product_nickname: PEARLPLUS new_feature_info: 4499197267967999 new_feature_info_str: 508A977F7EFEFFFF feature_info: - - 111 - - 112 - - 113 - - 114 - - 115 - - 116 - - 117 - - 118 - - 119 - - 120 - - 121 - - 122 - - 123 - - 124 - - 125 + - 111 + - 112 + - 113 + - 114 + - 115 + - 116 + - 117 + - 118 + - 119 + - 120 + - 121 + - 122 + - 123 + - 124 + - 125 product: id: 5gUei3OIJIXVD3eD85Balg name: Roborock Qrevo MaxV @@ -267,119 +267,119 @@ roborock.vacuum.a87: category: robot.vacuum.cleaner capability: 0 schema: - - id: 101 - name: rpc_request - code: rpc_request - mode: rw - type: RAW - - id: 102 - name: rpc_response - code: rpc_response - mode: rw - type: RAW - - id: 120 - name: "\u9519\u8BEF\u4EE3\u7801" - code: error_code - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 121 - name: "\u8BBE\u5907\u72B6\u6001" - code: state - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 122 - name: "\u8BBE\u5907\u7535\u91CF" - code: battery - mode: ro - type: ENUM - property: '{"range": [""]}' - - id: 123 - name: "\u6E05\u626B\u6A21\u5F0F" - code: fan_power - mode: rw - type: ENUM - property: '{"range": [""]}' - - id: 124 - name: "\u62D6\u5730\u6A21\u5F0F" - code: water_box_mode - mode: rw - type: ENUM - property: '{"range": [""]}' - - id: 125 - name: "\u4E3B\u5237\u5BFF\u547D" - code: main_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 126 - name: "\u8FB9\u5237\u5BFF\u547D" - code: side_brush_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 127 - name: "\u6EE4\u7F51\u5BFF\u547D" - code: filter_life - mode: rw - type: VALUE - property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' - - id: 128 - name: "\u989D\u5916\u72B6\u6001" - code: additional_props - mode: ro - type: RAW - - id: 130 - name: "\u5B8C\u6210\u4E8B\u4EF6" - code: task_complete - mode: ro - type: RAW - - id: 131 - name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_low_power - mode: ro - type: RAW - - id: 132 - name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" - code: task_cancel_in_motion - mode: ro - type: RAW - - id: 133 - name: "\u5145\u7535\u72B6\u6001" - code: charge_status - mode: ro - type: RAW - - id: 134 - name: "\u70D8\u5E72\u72B6\u6001" - code: drying_status - mode: ro - type: RAW - - id: 135 - name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" - code: offline_status - mode: ro - type: RAW + - id: 101 + name: rpc_request + code: rpc_request + mode: rw + type: RAW + - id: 102 + name: rpc_response + code: rpc_response + mode: rw + type: RAW + - id: 120 + name: "\u9519\u8BEF\u4EE3\u7801" + code: error_code + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 121 + name: "\u8BBE\u5907\u72B6\u6001" + code: state + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 122 + name: "\u8BBE\u5907\u7535\u91CF" + code: battery + mode: ro + type: ENUM + property: '{"range": [""]}' + - id: 123 + name: "\u6E05\u626B\u6A21\u5F0F" + code: fan_power + mode: rw + type: ENUM + property: '{"range": [""]}' + - id: 124 + name: "\u62D6\u5730\u6A21\u5F0F" + code: water_box_mode + mode: rw + type: ENUM + property: '{"range": [""]}' + - id: 125 + name: "\u4E3B\u5237\u5BFF\u547D" + code: main_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 126 + name: "\u8FB9\u5237\u5BFF\u547D" + code: side_brush_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 127 + name: "\u6EE4\u7F51\u5BFF\u547D" + code: filter_life + mode: rw + type: VALUE + property: '{"max": 100, "min": 0, "step": 1, "unit": "null", "scale": 1}' + - id: 128 + name: "\u989D\u5916\u72B6\u6001" + code: additional_props + mode: ro + type: RAW + - id: 130 + name: "\u5B8C\u6210\u4E8B\u4EF6" + code: task_complete + mode: ro + type: RAW + - id: 131 + name: "\u7535\u91CF\u4E0D\u8DB3\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_low_power + mode: ro + type: RAW + - id: 132 + name: "\u8FD0\u52A8\u4E2D\u4EFB\u52A1\u53D6\u6D88" + code: task_cancel_in_motion + mode: ro + type: RAW + - id: 133 + name: "\u5145\u7535\u72B6\u6001" + code: charge_status + mode: ro + type: RAW + - id: 134 + name: "\u70D8\u5E72\u72B6\u6001" + code: drying_status + mode: ro + type: RAW + - id: 135 + name: "\u79BB\u7EBF\u539F\u56E0\u7EC6\u5206" + code: offline_status + mode: ro + type: RAW roborock.vacuum.s5e: - protocol_version: "1.0" + protocol_version: '1.0' product_nickname: RUBYSLITE new_feature_info: 633887780925447 - new_feature_info_str: "0000000000002000" + new_feature_info_str: '0000000000002000' feature_info: - - 111 - - 112 - - 113 - - 114 - - 115 - - 116 - - 117 - - 118 - - 119 - - 120 - - 122 - - 123 - - 124 - - 125 + - 111 + - 112 + - 113 + - 114 + - 115 + - 116 + - 117 + - 118 + - 119 + - 120 + - 122 + - 123 + - 124 + - 125 roborock.vacuum.sc05: protocol_version: B01 product_nickname: PEARLPLUS @@ -390,171 +390,171 @@ roborock.vacuum.sc05: category: robot.vacuum.cleaner capability: 0 schema: - - id: 101 - name: RPC Request - code: rpc_request - mode: rw - type: RAW - property: "null" - - id: 102 - name: RPC Response - code: rpc_response - mode: rw - type: RAW - property: "null" - - id: 120 - name: "\u9519\u8BEF\u4EE3\u7801" - code: error_code - mode: ro - type: ENUM - property: "null" - - id: 121 - name: "\u8BBE\u5907\u72B6\u6001" - code: state - mode: ro - type: VALUE - property: "null" - - id: 122 - name: "\u8BBE\u5907\u7535\u91CF" - code: battery - mode: ro - type: ENUM - property: "null" - - id: 123 - name: "\u5438\u529B\u6863\u4F4D" - code: fan_power - mode: rw - type: ENUM - property: "null" - - id: 124 - name: "\u62D6\u5730\u6863\u4F4D" - code: water_box_mode - mode: rw - type: RAW - property: "null" - - id: 125 - name: "\u4E3B\u5237\u5BFF\u547D" - code: main_brush_life - mode: ro - type: ENUM - property: "null" - - id: 126 - name: "\u8FB9\u5237\u5BFF\u547D" - code: side_brush_life - mode: ro - type: ENUM - property: "null" - - id: 127 - name: "\u6EE4\u7F51\u5BFF\u547D" - code: filter_life - mode: ro - type: ENUM - property: "null" - - id: 135 - name: "\u79BB\u7EBF\u539F\u56E0" - code: offline_status - mode: ro - type: ENUM - property: "null" - - id: 136 - name: "\u6E05\u6D01\u6B21\u6570" - code: clean_times - mode: rw - type: ENUM - property: "null" - - id: 137 - name: "\u626B\u62D6\u6A21\u5F0F" - code: cleaning_preference - mode: rw - type: ENUM - property: "null" - - id: 138 - name: "\u6E05\u6D01\u4EFB\u52A1\u7C7B\u578B" - code: clean_task_type - mode: ro - type: ENUM - property: "null" - - id: 139 - name: "\u8FD4\u56DE\u57FA\u7AD9\u7C7B\u578B" - code: back_type - mode: ro - type: ENUM - property: "null" - - id: 141 - name: "\u6E05\u6D01\u8FDB\u5EA6" - code: cleaning_progress - mode: ro - type: ENUM - property: "null" - - id: 142 - name: "\u7A9C\u8D27\u4FE1\u606F" - code: fc_state - mode: ro - type: RAW - property: "null" - - id: 201 - name: "\u542F\u52A8\u6E05\u6D01\u4EFB\u52A1" - code: start_clean_task - mode: wo - type: ENUM - property: "null" - - id: 202 - name: "\u8FD4\u56DE\u57FA\u7AD9\u4EFB\u52A1" - code: start_back_dock_task - mode: wo - type: ENUM - property: "null" - - id: 203 - name: "\u542F\u52A8\u57FA\u7AD9\u4EFB\u52A1" - code: start_dock_task - mode: wo - type: ENUM - property: "null" - - id: 204 - name: "\u6682\u505C\u4EFB\u52A1" - code: pause - mode: wo - type: RAW - property: "null" - - id: 205 - name: "\u7EE7\u7EED\u4EFB\u52A1" - code: resume - mode: wo - type: RAW - property: "null" - - id: 206 - name: "\u7ED3\u675F\u4EFB\u52A1" - code: stop - mode: wo - type: RAW - property: "null" - - id: 10000 - name: request_cmd - code: request_cmd - mode: wo - type: RAW - property: "null" - - id: 10001 - name: response_cmd - code: response_cmd - mode: ro - type: RAW - property: "null" - - id: 10002 - name: request_map - code: request_map - mode: ro - type: RAW - property: "null" - - id: 10003 - name: response_map - code: response_map - mode: ro - type: RAW - property: "null" - - id: 10004 - name: event_report - code: event_report - mode: rw - type: RAW - property: "null" + - id: 101 + name: RPC Request + code: rpc_request + mode: rw + type: RAW + property: 'null' + - id: 102 + name: RPC Response + code: rpc_response + mode: rw + type: RAW + property: 'null' + - id: 120 + name: "\u9519\u8BEF\u4EE3\u7801" + code: error_code + mode: ro + type: ENUM + property: 'null' + - id: 121 + name: "\u8BBE\u5907\u72B6\u6001" + code: state + mode: ro + type: VALUE + property: 'null' + - id: 122 + name: "\u8BBE\u5907\u7535\u91CF" + code: battery + mode: ro + type: ENUM + property: 'null' + - id: 123 + name: "\u5438\u529B\u6863\u4F4D" + code: fan_power + mode: rw + type: ENUM + property: 'null' + - id: 124 + name: "\u62D6\u5730\u6863\u4F4D" + code: water_box_mode + mode: rw + type: RAW + property: 'null' + - id: 125 + name: "\u4E3B\u5237\u5BFF\u547D" + code: main_brush_life + mode: ro + type: ENUM + property: 'null' + - id: 126 + name: "\u8FB9\u5237\u5BFF\u547D" + code: side_brush_life + mode: ro + type: ENUM + property: 'null' + - id: 127 + name: "\u6EE4\u7F51\u5BFF\u547D" + code: filter_life + mode: ro + type: ENUM + property: 'null' + - id: 135 + name: "\u79BB\u7EBF\u539F\u56E0" + code: offline_status + mode: ro + type: ENUM + property: 'null' + - id: 136 + name: "\u6E05\u6D01\u6B21\u6570" + code: clean_times + mode: rw + type: ENUM + property: 'null' + - id: 137 + name: "\u626B\u62D6\u6A21\u5F0F" + code: cleaning_preference + mode: rw + type: ENUM + property: 'null' + - id: 138 + name: "\u6E05\u6D01\u4EFB\u52A1\u7C7B\u578B" + code: clean_task_type + mode: ro + type: ENUM + property: 'null' + - id: 139 + name: "\u8FD4\u56DE\u57FA\u7AD9\u7C7B\u578B" + code: back_type + mode: ro + type: ENUM + property: 'null' + - id: 141 + name: "\u6E05\u6D01\u8FDB\u5EA6" + code: cleaning_progress + mode: ro + type: ENUM + property: 'null' + - id: 142 + name: "\u7A9C\u8D27\u4FE1\u606F" + code: fc_state + mode: ro + type: RAW + property: 'null' + - id: 201 + name: "\u542F\u52A8\u6E05\u6D01\u4EFB\u52A1" + code: start_clean_task + mode: wo + type: ENUM + property: 'null' + - id: 202 + name: "\u8FD4\u56DE\u57FA\u7AD9\u4EFB\u52A1" + code: start_back_dock_task + mode: wo + type: ENUM + property: 'null' + - id: 203 + name: "\u542F\u52A8\u57FA\u7AD9\u4EFB\u52A1" + code: start_dock_task + mode: wo + type: ENUM + property: 'null' + - id: 204 + name: "\u6682\u505C\u4EFB\u52A1" + code: pause + mode: wo + type: RAW + property: 'null' + - id: 205 + name: "\u7EE7\u7EED\u4EFB\u52A1" + code: resume + mode: wo + type: RAW + property: 'null' + - id: 206 + name: "\u7ED3\u675F\u4EFB\u52A1" + code: stop + mode: wo + type: RAW + property: 'null' + - id: 10000 + name: request_cmd + code: request_cmd + mode: wo + type: RAW + property: 'null' + - id: 10001 + name: response_cmd + code: response_cmd + mode: ro + type: RAW + property: 'null' + - id: 10002 + name: request_map + code: request_map + mode: ro + type: RAW + property: 'null' + - id: 10003 + name: response_map + code: response_map + mode: ro + type: RAW + property: 'null' + - id: 10004 + name: event_report + code: event_report + mode: rw + type: RAW + property: 'null' From 8c618ca73652aa71812d666b551e1fec026ae644 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Sun, 22 Mar 2026 13:05:16 -0700 Subject: [PATCH 5/6] chore: Add types-pyyaml --- .pre-commit-config.yaml | 2 +- tests/devices/traits/v1/fixtures.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 755f4f90..81883851 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,7 +42,7 @@ repos: hooks: - id: mypy exclude: cli.py - additional_dependencies: [ "types-paho-mqtt" ] + additional_dependencies: [ "types-paho-mqtt", "types-pyyaml" ] - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook rev: v9.23.0 hooks: diff --git a/tests/devices/traits/v1/fixtures.py b/tests/devices/traits/v1/fixtures.py index 19755242..cce29875 100644 --- a/tests/devices/traits/v1/fixtures.py +++ b/tests/devices/traits/v1/fixtures.py @@ -118,9 +118,7 @@ def mock_app_get_init_status_fixture(device_info: HomeDataDevice, products: list product = next(filter(lambda product: product.id == device_info.product_id, products)) if not product: raise ValueError(f"Product {device_info.product_id} not found") - device_info_data = mock_data.DEVICE_INFO.get(product.model) - if device_info_data is None: - return mock_data.APP_GET_INIT_STATUS + device_info_data = mock_data.DEVICE_INFO.get(product.model, {}) return { **mock_data.APP_GET_INIT_STATUS, **device_info_data, From ca60cbe32e02e3f7da5655eeff07db1c8edf367c Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Sun, 22 Mar 2026 13:17:49 -0700 Subject: [PATCH 6/6] chore: Update tests/devices/traits/v1/fixtures.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/devices/traits/v1/fixtures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/devices/traits/v1/fixtures.py b/tests/devices/traits/v1/fixtures.py index cce29875..384ebdab 100644 --- a/tests/devices/traits/v1/fixtures.py +++ b/tests/devices/traits/v1/fixtures.py @@ -115,8 +115,8 @@ def mock_app_get_init_status_fixture(device_info: HomeDataDevice, products: list Uses real device feature data from device_info.yaml when available for the product model, falling back to the default mock data otherwise. """ - product = next(filter(lambda product: product.id == device_info.product_id, products)) - if not product: + product = next((product for product in products if product.id == device_info.product_id), None) + if product is None: raise ValueError(f"Product {device_info.product_id} not found") device_info_data = mock_data.DEVICE_INFO.get(product.model, {}) return {