From 1aac78a07d575bf57ea918c814ad21b8f50fa860 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Tue, 25 Aug 2026 15:05:02 +0000 Subject: [PATCH] feat: add device info and test data for Roborock Q Revo (a75) --- device_info.yaml | 105 ++++++++++ .../test_supported_features.ambr | 179 ++++++++++++++++++ .../__snapshots__/test_device_features.ambr | 27 +++ tests/mock_data.py | 1 + tests/testdata/home_data_device_q_revo.json | 33 ++++ tests/testdata/home_data_product_a75.json | 136 +++++++++++++ 6 files changed, 481 insertions(+) create mode 100644 tests/testdata/home_data_device_q_revo.json create mode 100644 tests/testdata/home_data_product_a75.json diff --git a/device_info.yaml b/device_info.yaml index 3034065a..07bbc036 100644 --- a/device_info.yaml +++ b/device_info.yaml @@ -877,6 +877,111 @@ roborock.vacuum.a27: code: offline_status mode: ro type: RAW +roborock.vacuum.a75: + protocol_version: '1.0' + product_nickname: PEARL + new_feature_info: 2238601361260543 + new_feature_info_str: 100A80505EDEFFFE + product: + id: ldHlB6hwVPMvdm6AdkxJv + name: Roborock Q Revo + model: roborock.vacuum.a75 + 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 roborock.vacuum.a87: protocol_version: '1.0' product_nickname: PEARLPLUS diff --git a/tests/__snapshots__/test_supported_features.ambr b/tests/__snapshots__/test_supported_features.ambr index eac70c3d..95450787 100644 --- a/tests/__snapshots__/test_supported_features.ambr +++ b/tests/__snapshots__/test_supported_features.ambr @@ -715,6 +715,185 @@ 'is_workday_holiday_supported': False, }) # --- +# name: test_device_features_from_home_data[home_data_device_q_revo.json] + dict({ + 'is_activate_video_charging_and_standby_supported': False, + 'is_ai_recognition_obstacle_supported': True, + 'is_ai_recognition_setting_supported': True, + 'is_analysis_supported': False, + 'is_any_state_transit_goto_supported': True, + 'is_auto_collection_2_supported': False, + 'is_auto_delivery_field_in_global_status_supported': False, + 'is_auto_tear_down_mop_supported': False, + 'is_avoid_collision_mode_supported': True, + 'is_avoid_collision_supported': True, + 'is_back_charge_auto_wash_supported': True, + 'is_back_wash_new_smart_supported': False, + 'is_careful_slow_mop_supported': True, + 'is_carpet_custom_clean_supported': True, + 'is_carpet_deep_clean_supported': True, + 'is_carpet_long_haired_ex_supported': False, + 'is_carpet_long_haired_supported': False, + 'is_carpet_pressure_use_origin_paras_supported': False, + 'is_carpet_shape_type_supported': False, + 'is_carpet_show_on_map': True, + 'is_carpet_supported': True, + 'is_ces_2022_supported': False, + 'is_clean_count_setting_supported': True, + 'is_clean_direct_status_supported': False, + 'is_clean_efficiency_supported': False, + 'is_clean_fluid_delivery_supported': False, + 'is_clean_history_time_line_supported': False, + 'is_clean_route_deep_slow_plus_supported': False, + 'is_clean_route_fast_mode_supported': True, + 'is_clean_route_setting_supported': True, + 'is_clean_then_mop_mode_supported': False, + 'is_clean_time_line_supported': False, + 'is_collect_dust_count_show_supported': False, + 'is_collect_dust_mode_supported': False, + 'is_corner_clean_mode_supported': False, + 'is_corner_mop_stretch_supported': False, + 'is_ctm_with_repeat_supported': False, + 'is_current_map_restore_enabled': True, + 'is_custom_clean_mode_count_supported': True, + 'is_custom_mode_supported': True, + 'is_custom_water_box_distance_supported': True, + 'is_customized_clean_supported': True, + 'is_detect_wire_carpet_supported': False, + 'is_dirty_object_detect_supported': False, + 'is_dirty_replenish_clean_supported': False, + 'is_dry_interval_timer_supported': False, + 'is_dss_believable': True, + 'is_dual_band_wi_fi_supported': False, + 'is_dust_collection_setting_supported': True, + 'is_dynamically_add_clean_zones_supported': True, + 'is_dynamically_skip_clean_zone_supported': True, + 'is_egg_dance_mode_supported': False, + 'is_egg_mode_supported_from_new_features': False, + 'is_exact_custom_mode_supported': True, + 'is_exhibition_function_supported': False, + 'is_floor_dir_clean_any_time_supported': False, + 'is_flow_led_setting_supported': False, + 'is_follow_low_obs_supported': False, + 'is_full_duples_switch_supported': False, + 'is_fw_filter_obstacle_supported': True, + 'is_gap_deep_clean_supported': False, + 'is_goto_pure_clean_path_supported': True, + 'is_hot_wash_towel_supported': False, + 'is_identify_room_supported': False, + 'is_ignore_unknown_map_object_supported': True, + 'is_lds_lifting_supported': False, + 'is_led_status_switch_supported': False, + 'is_left_water_drain_supported': True, + 'is_low_area_access_supported': False, + 'is_main_brush_up_down_supported_from_str': True, + 'is_map_beautify_internal_debug_supported': True, + 'is_map_carpet_add_support': True, + 'is_map_eraser_supported': False, + 'is_matter_supported': False, + 'is_max_plus_mode_supported': True, + 'is_max_zone_opened_supported': False, + 'is_mechanical_arm_mode_supported': False, + 'is_midway_back_to_dock_supported': False, + 'is_min_battery_15_to_clean_task_supported': False, + 'is_mop_forbidden_supported': True, + 'is_mop_path_supported': True, + 'is_mop_shake_module_supported': False, + 'is_mop_shake_water_max_supported': False, + 'is_multi_floor_supported': False, + 'is_multi_map_segment_timer_supported': True, + 'is_new_ai_recognition_supported': False, + 'is_new_data_for_clean_history': True, + 'is_new_data_for_clean_history_detail': True, + 'is_new_endpoint_supported': True, + 'is_new_remote_view_supported': False, + 'is_no_need_carpet_press_set_supported': False, + 'is_none_pure_clean_mop_with_max_plus': False, + 'is_object_detect_check_supported': False, + 'is_offline_map_supported': True, + 'is_optimize_battery_supported': False, + 'is_order_clean_supported': False, + 'is_over_sea_ctm_supported': False, + 'is_pet_snapshot_supported': False, + 'is_pet_supplies_deep_clean_supported': False, + 'is_program_mode_supported': False, + 'is_pumping_water_supported': False, + 'is_pure_clean_mop_supported': True, + 'is_re_segment_supported': True, + 'is_record_allowed': True, + 'is_remote_supported': False, + 'is_right_brush_stretch_supported': False, + 'is_roller_mop_supported': False, + 'is_room_name_supported': True, + 'is_rpc_retry_supported': True, + 'is_rubber_brush_carpet_supported': False, + 'is_set_child_supported': True, + 'is_setting_carpet_first_supported': True, + 'is_shake_mop_set_supported': True, + 'is_should_show_arm_over_load_supported': False, + 'is_show_clean_finish_reason_supported': True, + 'is_show_general_obstacle_supported': False, + 'is_show_obstacle_photo_supported': False, + 'is_side_brush_lift_carpet_supported': False, + 'is_small_side_mop_supported': False, + 'is_smart_clean_mode_set_supported': False, + 'is_soak_and_wash_supported': False, + 'is_soft_clean_mode_supported': False, + 'is_sr_map_supported': False, + 'is_super_deep_wash_supported': True, + 'is_support_api_app_stop_grasp_supported': False, + 'is_support_backup_map': True, + 'is_support_clean_estimate': True, + 'is_support_cliff_zone': True, + 'is_support_custom_carpet': False, + 'is_support_custom_dnd': True, + 'is_support_custom_door_sill': True, + 'is_support_custom_mode_in_cleaning': True, + 'is_support_fetch_timer_summary': False, + 'is_support_floor_direction': True, + 'is_support_floor_edit': True, + 'is_support_furniture': True, + 'is_support_get_particular_status_supported': False, + 'is_support_incremental_map': True, + 'is_support_main_brush_up_down_supported': False, + 'is_support_mop_back_pwm_set': True, + 'is_support_quick_map_builder': True, + 'is_support_remote_control_in_call': False, + 'is_support_room_tag': True, + 'is_support_set_switch_map_mode': True, + 'is_support_set_volume_in_call': False, + 'is_support_side_brush_up_down_supported': False, + 'is_support_smart_door_sill': True, + 'is_support_smart_global_clean_with_custom_mode': True, + 'is_support_smart_scene': True, + 'is_support_stuck_zone': True, + 'is_support_voice_control_debug': False, + 'is_support_water_mode': True, + 'is_supported_download_test_voice': True, + 'is_supported_drying': True, + 'is_supported_valley_electricity': True, + 'is_sync_server_name_supported': False, + 'is_three_d_mapping_inner_test_supported': False, + 'is_tidyup_zones_supported': False, + 'is_two_gears_no_collision_supported': False, + 'is_two_key_real_time_video_supported': False, + 'is_two_key_rtv_in_charging_supported': False, + 'is_type_identify_supported': False, + 'is_unsave_map_reason_supported': True, + 'is_uvc_sterilize_supported': False, + 'is_video_monitor_supported': True, + 'is_video_patrol_supported': False, + 'is_video_setting_supported': True, + 'is_voice_control_led_supported': False, + 'is_voice_control_supported': False, + 'is_wash_then_charge_cmd_supported': True, + 'is_water_leak_check_supported': True, + 'is_water_slide_mode_supported': False, + 'is_water_up_down_drain_supported': True, + 'is_wifi_manage_supported': True, + 'is_workday_holiday_supported': False, + }) +# --- # name: test_device_features_from_home_data[home_data_device_s5e.json] dict({ 'is_activate_video_charging_and_standby_supported': False, diff --git a/tests/devices/traits/v1/__snapshots__/test_device_features.ambr b/tests/devices/traits/v1/__snapshots__/test_device_features.ambr index 731f6f16..5a8ffbac 100644 --- a/tests/devices/traits/v1/__snapshots__/test_device_features.ambr +++ b/tests/devices/traits/v1/__snapshots__/test_device_features.ambr @@ -39,6 +39,26 @@ 'water_shortage_status': True, }) # --- +# name: test_is_attribute_supported[home_data_device_q_revo.json] + dict({ + 'battery': True, + 'charge_status': True, + 'clean_fluid_status': False, + 'clean_percent': True, + 'clear_water_box_status': True, + 'dirty_water_box_status': True, + 'dock_error_status': True, + 'dry_status': True, + 'error_code': True, + 'fan_power': True, + 'rdt': True, + 'state': True, + 'water_box_carriage_status': True, + 'water_box_mode': True, + 'water_box_status': True, + 'water_shortage_status': True, + }) +# --- # name: test_is_attribute_supported[home_data_device_s5e.json] dict({ 'battery': True, @@ -133,6 +153,13 @@ 'side_brush_work_time': True, }) # --- +# name: test_is_consumable_field_supported[home_data_device_q_revo.json] + dict({ + 'filter_work_time': True, + 'main_brush_work_time': True, + 'side_brush_work_time': True, + }) +# --- # name: test_is_consumable_field_supported[home_data_device_s5e.json] dict({ 'filter_work_time': True, diff --git a/tests/mock_data.py b/tests/mock_data.py index 71442c0d..871e9c92 100644 --- a/tests/mock_data.py +++ b/tests/mock_data.py @@ -172,6 +172,7 @@ "product-id-s7-maxv": RoborockDockTypeCode.o3_plus_dock, # Ultra (Wash/Empty) "product-id-a125": RoborockDockTypeCode.o1_dock, # Q5 Max+ (Auto-Empty) "73EnOOM2NhDujvnvb7hvvv": RoborockDockTypeCode.o0_dock, # S5 Max (Standard Charging) + "product-id-a75": RoborockDockTypeCode.pearl_dock, # Q Revo (Wash/Empty) "product-id-a123": RoborockDockTypeCode.pearl_plus_dock, # PearlS Lite / Q Revo (Wash/Empty) "product-saros-10": RoborockDockTypeCode.o4_dock, # Saros 10 / Q Revo Pro (Wash/Empty/Auto Fluid) "product-saros-10r": RoborockDockTypeCode.o6_dock, # JC / Q Revo Master (Wash/Empty/Hot water) diff --git a/tests/testdata/home_data_device_q_revo.json b/tests/testdata/home_data_device_q_revo.json new file mode 100644 index 00000000..fc0c2ea8 --- /dev/null +++ b/tests/testdata/home_data_device_q_revo.json @@ -0,0 +1,33 @@ +{ + "duid": "device-id-a75", + "name": "Roborock Q Revo", + "localKey": "key123key123key1", + "productId": "product-id-a75", + "fv": "02.20.60", + "activeTime": 1700593279, + "timeZoneId": "Europe/Berlin", + "iconUrl": "", + "share": false, + "online": true, + "pv": "1.0", + "tuyaMigrated": false, + "extra": "{}", + "sn": "A75SAMPLESNTEST", + "featureSet": "2238601361260543", + "newFeatureSet": "100A80505EDEFFFE", + "deviceStatus": { + "120": 0, + "121": 8, + "122": 100, + "123": 103, + "124": 202, + "125": 6, + "126": 2, + "127": 66, + "128": 0, + "133": 1, + "134": 0 + }, + "silentOtaSwitch": true, + "f": false +} diff --git a/tests/testdata/home_data_product_a75.json b/tests/testdata/home_data_product_a75.json new file mode 100644 index 00000000..bf690235 --- /dev/null +++ b/tests/testdata/home_data_product_a75.json @@ -0,0 +1,136 @@ +{ + "id": "product-id-a75", + "name": "Roborock Q Revo", + "model": "roborock.vacuum.a75", + "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" + } + ] +}