diff --git a/SUPPORTED_FEATURES.md b/SUPPORTED_FEATURES.md index 752b73cf..8c469737 100644 --- a/SUPPORTED_FEATURES.md +++ b/SUPPORTED_FEATURES.md @@ -1,194 +1,196 @@ -| Feature | roborock.vacuum.a10 | roborock.vacuum.a117 | roborock.vacuum.a123 | roborock.vacuum.a125 | roborock.vacuum.a144 | roborock.vacuum.a147 | roborock.vacuum.a15 | roborock.vacuum.a187 | roborock.vacuum.a27 | roborock.vacuum.a87 | roborock.vacuum.s5e | roborock.vacuum.sc01 | roborock.vacuum.sc05 | roborock.vacuum.ss07 | roborock.wm.a102 | -|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| -| product_nickname | TANOSV | PEARLPLUSS | PEARLSLITE | ULTRONSE | CORALPRO | VERDELITE | TANOSS | Unknown | TOPAZSV | PEARLPLUS | RUBYSLITE | Unknown | PEARLPLUS | Unknown | Unknown | -| protocol_version | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | B01 | B01 | B01 | A01 | -| new_feature_info | X | X | 0 | X | X | X | X | X | False | X | X | 0 | | 0 | 0 | -| new_feature_info_str | | X | X | X | X | X | X | X | | X | X | X | | X | X | -| `111` | | X | | | | | X | | | X | X | | | | | -| `112` | | X | | | | | X | | | X | X | | | | | -| `113` | | X | | | | | X | | | X | X | | | | | -| `114` | | X | | | | | X | | | X | X | | | | | -| `115` | | X | | | | | X | | | X | X | | | | | -| `116` | | X | | | | | X | | | X | X | | | | | -| `117` | | X | | | | | X | | | X | X | | | | | -| `118` | | X | | | | | X | | | X | X | | | | | -| `119` | | X | | | | | X | | | X | X | | | | | -| `120` | | X | | | | | X | | | X | X | | | | | -| `121` | | X | | | | | | | | X | | | | | | -| `122` | | X | | | | | X | | | X | X | | | | | -| `123` | | X | | | | | X | | | X | X | | | | | -| `124` | | X | | | | | X | | | X | X | | | | | -| `125` | | X | | | | | X | | | X | X | | | | | -| `feature_info` | | X | | | | | X | | | X | X | | | | | -| `is_activate_video_charging_and_standby_supported` | | | | | X | | | | | | | | | | | -| `is_analysis_supported` | | X | | | | | X | | | X | X | | | | | -| `is_any_state_transit_goto_supported` | X | X | | X | X | X | X | X | | X | | | | | | -| `is_auto_collection_2_supported` | | X | X | | X | X | | X | | | | | | | | -| `is_auto_delivery_field_in_global_status_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_auto_tear_down_mop_supported` | | | | | X | X | | | | | | | | | | -| `is_avoid_collision_mode_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_avoid_collision_supported` | | X | | | X | X | | X | | X | | | | | | -| `is_back_charge_auto_wash_supported` | | X | X | X | X | X | | X | | X | | | | | | -| `is_back_wash_new_smart_supported` | | | | | | | | | | | | | | | | -| `is_careful_slow_mop_supported` | | X | | X | X | X | X | X | | X | | | | | | -| `is_carpet_custom_clean_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_carpet_deep_clean_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_carpet_long_haired_ex_supported` | | | | | | | | | | | | | | | | -| `is_carpet_long_haired_supported` | | | | | X | X | | | | | | | | | | -| `is_carpet_pressure_use_origin_paras_supported` | | | | | | | | | | | | | | | | -| `is_carpet_shape_type_supported` | | | | | | | | | | | | | | | | -| `is_carpet_show_on_map` | | X | | X | X | X | | X | | X | | | | | | -| `is_carpet_supported` | | X | | | X | X | X | X | | X | | | | | | -| `is_ces_2022_supported` | | | | | | | | | | | | | | | | -| `is_clean_count_setting_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_clean_direct_status_supported` | | | | | X | X | | X | | | | | | | | -| `is_clean_efficiency_supported` | | | | | | | | | | | | | | | | -| `is_clean_fluid_delivery_supported` | | | | | X | | | | | | | | | | | -| `is_clean_history_time_line_supported` | | | | | X | X | | X | | | | | | | | -| `is_clean_route_deep_slow_plus_supported` | | | | | | | | | | | | | | | | -| `is_clean_route_fast_mode_supported` | | X | X | X | X | X | | X | | X | | | | | | -| `is_clean_route_setting_supported` | | | | | | | | | | | | | | | | -| `is_clean_then_mop_mode_supported` | | | | | X | | | X | | | | | | | | -| `is_clean_time_line_supported` | | | | | X | X | | X | | | | | | | | -| `is_collect_dust_count_show_supported` | | | | | X | | | | | | | | | | | -| `is_collect_dust_mode_supported` | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | -| `is_corner_clean_mode_supported` | | | | | | | | | | | | | | | | -| `is_corner_mop_stretch_supported` | | X | X | | X | | | X | | X | | | | | | -| `is_ctm_with_repeat_supported` | | | | | X | | | X | | | | | | | | -| `is_current_map_restore_enabled` | X | X | | X | X | X | X | X | | X | X | | | | | -| `is_custom_clean_mode_count_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_custom_mode_supported` | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | -| `is_custom_water_box_distance_supported` | X | X | | | X | | | X | | X | X | | | | | -| `is_customized_clean_supported` | | | | | | | | | | | | | | | | -| `is_detect_wire_carpet_supported` | | | | | X | | | | | | | | | | | -| `is_dirty_object_detect_supported` | | | | | X | X | | | | | | | | | | -| `is_dirty_replenish_clean_supported` | | X | | | X | X | | X | | X | | | | | | -| `is_dry_interval_timer_supported` | | | | | X | X | | X | | | | | | | | -| `is_dss_believable` | | X | X | X | X | X | | X | | X | | | | | | -| `is_dual_band_wi_fi_supported` | | | | | | | | | | | | | | | | -| `is_dust_collection_setting_supported` | | X | | X | X | X | X | X | | X | | | | | | -| `is_dynamically_add_clean_zones_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_dynamically_skip_clean_zone_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_egg_dance_mode_supported` | | | | | X | X | | | | | | | | | | -| `is_egg_mode_supported_from_new_features` | | | | | | | | | | | | | | | | -| `is_exact_custom_mode_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_exhibition_function_supported` | | | | | | | | | | | | | | | | -| `is_floor_dir_clean_any_time_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_flow_led_setting_supported` | | | | | | | X | | | | | | | | | -| `is_follow_low_obs_supported` | | | | | | | | | | | | | | | | -| `is_full_duples_switch_supported` | | | | | | | | | | | | | | | | -| `is_fw_filter_obstacle_supported` | X | X | | X | X | X | X | X | | X | | | | | | -| `is_gap_deep_clean_supported` | | X | | | X | X | | X | | | | | | | | -| `is_goto_pure_clean_path_supported` | | X | X | X | X | X | | X | | X | | | | | | -| `is_hot_wash_towel_supported` | | X | | | X | X | | X | | X | | | | | | -| `is_identify_room_supported` | | | | | X | X | | | | | | | | | | -| `is_ignore_unknown_map_object_supported` | X | X | | X | X | X | X | X | | X | | | | | | -| `is_lds_lifting_supported` | | | | | | X | | | | | | | | | | -| `is_led_status_switch_supported` | | X | | | | | X | | | X | X | | | | | -| `is_left_water_drain_supported` | | X | X | X | X | X | | X | | X | | | | | | -| `is_low_area_access_supported` | | | | | | | | | | | | | | | | -| `is_main_brush_up_down_supported_from_str` | | X | | | X | X | | X | | X | | | | | | -| `is_map_beautify_internal_debug_supported` | | X | | X | X | X | X | X | | X | | | | | | -| `is_map_carpet_add_support` | | X | | | X | X | | X | | X | | | | | | -| `is_map_eraser_supported` | | | | | X | X | | X | | | | | | | | -| `is_matter_supported` | | X | | | X | X | | X | | | | | | | | -| `is_max_plus_mode_supported` | | | | | | | | | | | | | | | | -| `is_max_zone_opened_supported` | | | | | X | X | | X | | | | | | | | -| `is_mechanical_arm_mode_supported` | | | | | | | | | | | | | | | | -| `is_midway_back_to_dock_supported` | | | | | X | X | | X | | | | | | | | -| `is_min_battery_15_to_clean_task_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_mop_forbidden_supported` | | | | | | | | | | | | | | | | -| `is_mop_path_supported` | | X | | | X | X | X | X | | X | | | | | | -| `is_mop_shake_module_supported` | | | | | | | | | | | | | | | | -| `is_mop_shake_water_max_supported` | | | | | | X | | | | | | | | | | -| `is_multi_floor_supported` | | X | | | | | X | | | X | X | | | | | -| `is_multi_map_segment_timer_supported` | X | X | | X | X | X | X | X | | X | X | | | | | -| `is_new_ai_recognition_supported` | | X | X | | X | X | | X | | | | | | | | -| `is_new_data_for_clean_history` | | X | | X | X | X | X | X | | X | | | | | | -| `is_new_data_for_clean_history_detail` | | X | | X | X | X | X | X | | X | | | | | | -| `is_new_endpoint_supported` | | X | X | X | X | X | | X | | X | | | | | | -| `is_new_remote_view_supported` | | | | | | | | | | | | | | | | -| `is_no_need_carpet_press_set_supported` | | X | X | | X | X | | X | | | | | | | | -| `is_none_pure_clean_mop_with_max_plus` | | | | | | | | | | | | | | | | -| `is_object_detect_check_supported` | | X | | | X | X | | X | | | | | | | | -| `is_offline_map_supported` | | X | X | X | X | X | | X | | X | | | | | | -| `is_optimize_battery_supported` | | | | | | | | | | | | | | | | -| `is_order_clean_supported` | | X | | | | | X | | | X | X | | | | | -| `is_over_sea_ctm_supported` | | | | | X | | | X | | | | | | | | -| `is_pet_snapshot_supported` | | X | | | X | X | | | | | | | | | | -| `is_pet_supplies_deep_clean_supported` | | X | X | | X | X | | X | | | | | | | | -| `is_program_mode_supported` | | | | | | | | | | | | | | | | -| `is_pumping_water_supported` | | | | | | | | | | | | | | | | -| `is_pure_clean_mop_supported` | | | | | | | | | | | | | | | | -| `is_re_segment_supported` | X | X | | X | X | X | X | X | | X | X | | | | | -| `is_record_allowed` | X | X | | X | X | X | X | X | | X | | | | | | -| `is_remote_supported` | | X | | | | | X | | | X | X | | | | | -| `is_right_brush_stretch_supported` | | X | | | X | X | | X | | | | | | | | -| `is_room_name_supported` | X | X | | X | X | X | X | X | | X | X | | | | | -| `is_rpc_retry_supported` | | X | | X | X | X | | X | | X | | | | | | -| `is_rubber_brush_carpet_supported` | | | | | | | | | | | | | | | | -| `is_set_child_supported` | X | X | | X | X | X | X | X | | X | | | | | | -| `is_setting_carpet_first_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_shake_mop_set_supported` | | X | | X | X | X | X | X | | X | | | | | | -| `is_should_show_arm_over_load_supported` | | | | | | | | | | | | | | | | -| `is_show_clean_finish_reason_supported` | X | X | | X | X | X | X | X | | X | X | | | | | -| `is_show_general_obstacle_supported` | | | | | | | | | | | | | | | | -| `is_show_obstacle_photo_supported` | | | | | | | | | | | | | | | | -| `is_side_brush_lift_carpet_supported` | | | | | X | | | | | | | | | | | -| `is_small_side_mop_supported` | | | | | | X | | | | | | | | | | -| `is_smart_clean_mode_set_supported` | | X | X | | X | X | | X | | X | | | | | | -| `is_soak_and_wash_supported` | | | | | | | | | | | | | | | | -| `is_soft_clean_mode_supported` | | | | | | | | | | | | | | | | -| `is_sr_map_supported` | | | | | | | | | | | | | | | | -| `is_super_deep_wash_supported` | | X | X | X | X | X | | X | | X | | | | | | -| `is_support_api_app_stop_grasp_supported` | | | | | | | | | | | | | | | | -| `is_support_backup_map` | | X | | X | X | X | X | X | | X | X | | | | | -| `is_support_clean_estimate` | | X | X | X | X | X | | X | | X | | | | | | -| `is_support_cliff_zone` | | X | X | X | X | X | | X | | X | | | | | | -| `is_support_custom_carpet` | | | | | | | | | | | | | | | | -| `is_support_custom_dnd` | | X | X | X | X | X | | X | | X | | | | | | -| `is_support_custom_door_sill` | | X | X | X | X | X | | X | | X | | | | | | -| `is_support_custom_mode_in_cleaning` | | X | | X | X | X | | X | | X | | | | | | -| `is_support_fetch_timer_summary` | | X | | | | | X | | | X | X | | | | | -| `is_support_floor_direction` | | X | X | X | X | X | | X | | X | | | | | | -| `is_support_floor_edit` | | X | | X | X | X | | X | | X | | | | | | -| `is_support_furniture` | | X | | X | X | X | | X | | X | | | | | | -| `is_support_get_particular_status_supported` | | | | | | | | | | | | | | | | -| `is_support_incremental_map` | | X | X | X | X | X | | X | | X | | | | | | -| `is_support_main_brush_up_down_supported` | | | | | X | X | | | | | | | | | | -| `is_support_mop_back_pwm_set` | | | | | | | | | | | | | | | | -| `is_support_quick_map_builder` | | X | | X | X | X | X | X | | X | X | | | | | -| `is_support_remote_control_in_call` | | X | | | X | X | | | | X | | | | | | -| `is_support_room_tag` | | X | | X | X | X | | X | | X | | | | | | -| `is_support_set_switch_map_mode` | | X | | X | X | X | | X | | X | | | | | | -| `is_support_set_volume_in_call` | | X | | | X | X | | | | X | | | | | | -| `is_support_side_brush_up_down_supported` | | | | | X | X | | | | | | | | | | -| `is_support_smart_door_sill` | | X | X | X | X | X | | X | | X | | | | | | -| `is_support_smart_global_clean_with_custom_mode` | | X | | X | X | X | | X | | X | | | | | | -| `is_support_smart_scene` | X | X | | X | X | X | | X | | X | | | | | | -| `is_support_stuck_zone` | | X | X | X | X | X | | X | | X | | | | | | -| `is_support_voice_control_debug` | | | | | | | | | | | | | | | | -| `is_support_water_mode` | | | | | | | | | | | | | | | | -| `is_supported_download_test_voice` | | X | | X | X | X | | X | | X | | | | | | -| `is_supported_drying` | | X | | | X | X | | X | | X | | | | | | -| `is_supported_valley_electricity` | | X | | X | X | X | | X | | X | | | | | | -| `is_sync_server_name_supported` | | | | | | | | | | | | | | | | -| `is_three_d_mapping_inner_test_supported` | | | | | | | | | | | | | | | | -| `is_tidyup_zones_supported` | | | | | | | | | | | | | | | | -| `is_two_gears_no_collision_supported` | | | | | | | | | | | | | | | | -| `is_two_key_real_time_video_supported` | | X | | | X | | | | | X | | | | | | -| `is_two_key_rtv_in_charging_supported` | | X | | | X | X | | | | X | | | | | | -| `is_type_identify_supported` | | | | | | | | | | | | | | | | -| `is_unsave_map_reason_supported` | | X | | X | X | X | X | X | | X | X | | | | | -| `is_uvc_sterilize_supported` | | | | | | | | | | | | | | | | -| `is_video_monitor_supported` | X | X | | X | X | X | X | X | | X | | | | | | -| `is_video_patrol_supported` | | X | | | X | X | | | | | | | | | | -| `is_video_setting_supported` | X | X | | X | X | X | X | X | | X | | | | | | -| `is_voice_control_led_supported` | | | | | X | X | | | | | | | | | | -| `is_voice_control_supported` | | X | | | X | X | | | | X | | | | | | -| `is_wash_then_charge_cmd_supported` | | X | | X | X | X | | X | | X | | | | | | -| `is_water_leak_check_supported` | | | | | | X | | | | X | | | | | | -| `is_water_slide_mode_supported` | | | | | X | | | | | | | | | | | -| `is_water_up_down_drain_supported` | | X | X | X | X | X | | X | | X | | | | | | -| `is_wifi_manage_supported` | | X | X | X | X | X | | X | | X | | | | | | -| `is_workday_holiday_supported` | | | | | | | | | | | | | | | | +| Feature | roborock.vacuum.a10 | roborock.vacuum.a117 | roborock.vacuum.a123 | roborock.vacuum.a125 | roborock.vacuum.a144 | roborock.vacuum.a147 | roborock.vacuum.a15 | roborock.vacuum.a187 | roborock.vacuum.a27 | roborock.vacuum.a288 | roborock.vacuum.a306 | roborock.vacuum.a75 | roborock.vacuum.a87 | roborock.vacuum.s5e | roborock.vacuum.sc01 | roborock.vacuum.sc05 | roborock.vacuum.ss07 | roborock.wm.a102 | +|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| +| product_nickname | TANOSV | PEARLPLUSS | PEARLSLITE | ULTRONSE | CORALPRO | VERDELITE | TANOSS | Unknown | TOPAZSV | PEARLPLUS | Unknown | PEARL | PEARLPLUS | RUBYSLITE | Unknown | PEARLPLUS | PEARLPLUS | Unknown | +| protocol_version | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | B01 | B01 | B01 | A01 | +| new_feature_info | 10738169343 | 4499197267967999 | 0 | 2097860516935167 | 4499197267967999 | 4499195120484351 | 636084721975295 | 2247397454282751 | False | 4499197267967999 | 4499197267967999 | 2238601361260543 | 4499197267967999 | 633887780925447 | 0 | | | 0 | +| new_feature_info_str | | 000000000000000BC2FF8F7F7EFEFFFF | 42BA8D587EDAFFFE | 00000040385AFFF6 | 0005075028ED3EDDCFFF8F7F7EFEFFFF | 0000000008EFBCDDDFFFAE7E7EFEFFFF | 0000000000002000 | 00040040282834C9C2FA8F5C7EDEFFFE | | 0000000000099518CCFF7EFDA8E93EDDDBFF8F7F7EFEFFFF | 000002637C3FBF1DCEDD7FFDA8E8B6FD5BBFAF7F7EFEFFFF | 100A80505EDEFFFE | 508A977F7EFEFFFF | 0000000000002000 | 0 | | | 40 | +| `111` | | X | | | | | X | | | X | | | X | X | | | | | +| `112` | | X | | | | | X | | | X | | | X | X | | | | | +| `113` | | X | | | | | X | | | X | | | X | X | | | | | +| `114` | | X | | | | | X | | | X | | | X | X | | | | | +| `115` | | X | | | | | X | | | X | | | X | X | | | | | +| `116` | | X | | | | | X | | | X | | | X | X | | | | | +| `117` | | X | | | | | X | | | X | | | X | X | | | | | +| `118` | | X | | | | | X | | | X | | | X | X | | | | | +| `119` | | X | | | | | X | | | X | | | X | X | | | | | +| `120` | | X | | | | | X | | | X | | | X | X | | | | | +| `121` | | X | | | | | | | | X | | | X | | | | | | +| `122` | | X | | | | | X | | | X | | | X | X | | | | | +| `123` | | X | | | | | X | | | X | | | X | X | | | | | +| `124` | | X | | | | | X | | | X | | | X | X | | | | | +| `125` | | X | | | | | X | | | X | | | X | X | | | | | +| `is_activate_video_charging_and_standby_supported` | | | | | X | | | | | X | X | | | | | | | | +| `is_ai_recognition_obstacle_supported` | X | X | X | | X | X | | X | X | X | X | X | X | | X | X | X | X | +| `is_ai_recognition_setting_supported` | X | X | X | | X | X | | X | X | X | X | X | X | | X | X | X | X | +| `is_analysis_supported` | | X | | | | | X | | | X | | | X | X | | | | | +| `is_any_state_transit_goto_supported` | X | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_auto_collection_2_supported` | | X | X | | X | X | | X | | X | X | | | | | | | | +| `is_auto_delivery_field_in_global_status_supported` | | X | X | | X | X | | X | | X | X | | X | | | | | | +| `is_auto_tear_down_mop_supported` | | | | | X | X | | | | X | | | | | | | | | +| `is_avoid_collision_mode_supported` | | X | X | | X | X | | X | | X | X | X | X | | | | | | +| `is_avoid_collision_supported` | | X | | | X | X | | X | | X | X | X | X | | | | | | +| `is_back_charge_auto_wash_supported` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_back_wash_new_smart_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_careful_slow_mop_supported` | | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_carpet_custom_clean_supported` | | X | X | | X | X | | X | | X | X | X | X | | | | | | +| `is_carpet_deep_clean_supported` | | X | X | | X | X | | X | | X | X | X | X | | | | | | +| `is_carpet_long_haired_ex_supported` | | | | | | | | | | X | | | | | | | | | +| `is_carpet_long_haired_supported` | | | | | X | X | | | | X | | | | | | | | | +| `is_carpet_pressure_use_origin_paras_supported` | | | | | | | | | | | | | | | | | | | +| `is_carpet_shape_type_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_carpet_show_on_map` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_carpet_supported` | | X | | | X | X | X | X | | X | X | X | X | | | | | | +| `is_ces_2022_supported` | | | | | | | | | | | | | | | | | | | +| `is_clean_count_setting_supported` | | X | X | | X | X | | X | | X | X | X | X | | | | | | +| `is_clean_direct_status_supported` | | | | | X | X | | X | | X | X | | | | | | | | +| `is_clean_efficiency_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_clean_fluid_delivery_supported` | | | | | X | | | | | X | X | | | | | | | | +| `is_clean_history_time_line_supported` | | | | | X | X | | X | | X | X | | | | | | | | +| `is_clean_route_deep_slow_plus_supported` | | | | | | | | | | | | | | | | | | | +| `is_clean_route_fast_mode_supported` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_clean_route_setting_supported` | | X | X | X | X | X | X | X | X | X | X | X | X | | X | X | X | X | +| `is_clean_then_mop_mode_supported` | | | | | X | | | X | | X | X | | | | | | | | +| `is_clean_time_line_supported` | | | | | X | X | | X | | X | X | | | | | | | | +| `is_collect_dust_count_show_supported` | | | | | X | | | | | X | X | | | | | | | | +| `is_collect_dust_mode_supported` | X | X | X | X | X | X | X | X | X | X | X | | X | X | X | X | X | X | +| `is_corner_clean_mode_supported` | | | | | | | | | | | | | | | | | | | +| `is_corner_mop_stretch_supported` | | X | X | | X | | | X | | X | X | | X | | | | | | +| `is_ctm_with_repeat_supported` | | | | | X | | | X | | X | X | | | | | | | | +| `is_current_map_restore_enabled` | X | X | | X | X | X | X | X | | X | X | X | X | X | | | | | +| `is_custom_clean_mode_count_supported` | | X | X | | X | X | | X | | X | X | X | X | | | | | | +| `is_custom_mode_supported` | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | +| `is_custom_water_box_distance_supported` | X | X | | | X | | | X | | X | X | X | X | X | | | | | +| `is_customized_clean_supported` | | X | X | | X | X | X | X | X | X | X | X | X | | X | X | X | X | +| `is_detect_wire_carpet_supported` | | | | | X | | | | | X | X | | | | | | | | +| `is_dirty_object_detect_supported` | | | | | X | X | | | | X | X | | | | | | | | +| `is_dirty_replenish_clean_supported` | | X | | | X | X | | X | | X | X | | X | | | | | | +| `is_dry_interval_timer_supported` | | | | | X | X | | X | | X | X | | | | | | | | +| `is_dss_believable` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_dual_band_wi_fi_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_dust_collection_setting_supported` | | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_dynamically_add_clean_zones_supported` | | X | X | | X | X | | X | | X | X | X | X | | | | | | +| `is_dynamically_skip_clean_zone_supported` | | X | X | | X | X | | X | | X | X | X | X | | | | | | +| `is_egg_dance_mode_supported` | | | | | X | X | | | | X | X | | | | | | | | +| `is_egg_mode_supported_from_new_features` | | | | | | | | | | | | | | | | | | | +| `is_exact_custom_mode_supported` | | X | X | | X | X | | X | | X | X | X | X | | | | | | +| `is_exhibition_function_supported` | | | | | | | | | | | | | | | | | | | +| `is_floor_dir_clean_any_time_supported` | | X | X | | X | X | | X | | X | X | | X | | | | | | +| `is_flow_led_setting_supported` | | | | | | | X | | | | | | | | | | | | +| `is_follow_low_obs_supported` | | | | | | | | | | X | | | | | | | | | +| `is_full_duples_switch_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_fw_filter_obstacle_supported` | X | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_gap_deep_clean_supported` | | X | | | X | X | | X | | X | | | | | | | | | +| `is_goto_pure_clean_path_supported` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_hot_wash_towel_supported` | | X | | | X | X | | X | | X | X | | X | | | | | | +| `is_identify_room_supported` | | | | | X | X | | | | X | X | | | | | | | | +| `is_ignore_unknown_map_object_supported` | X | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_lds_lifting_supported` | | | | | | X | | | | | X | | | | | | | | +| `is_led_status_switch_supported` | | X | | | | | X | | | X | | | X | X | | | | | +| `is_left_water_drain_supported` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_low_area_access_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_main_brush_up_down_supported_from_str` | | X | | | X | X | | X | | X | X | X | X | | | | | | +| `is_map_beautify_internal_debug_supported` | | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_map_carpet_add_support` | | X | | | X | X | | X | | X | X | X | X | | | | | | +| `is_map_eraser_supported` | | | | | X | X | | X | | X | X | | | | | | | | +| `is_matter_supported` | | X | | | X | X | | X | | X | X | | | | | | | | +| `is_max_plus_mode_supported` | | X | X | | X | X | | X | X | X | X | X | X | | X | X | X | X | +| `is_max_zone_opened_supported` | | | | | X | X | | X | | X | X | | | | | | | | +| `is_mechanical_arm_mode_supported` | | | | | | | | | | | | | | | | | | | +| `is_midway_back_to_dock_supported` | | | | | X | X | | X | | X | X | | | | | | | | +| `is_min_battery_15_to_clean_task_supported` | | X | X | | X | X | | X | | X | X | | X | | | | | | +| `is_mop_forbidden_supported` | X | | | | | | X | | X | | | X | | X | | | | | +| `is_mop_path_supported` | | X | | | X | X | X | X | | X | X | X | X | | | | | | +| `is_mop_shake_module_supported` | | | | | | X | X | | X | | | | | | | | | | +| `is_mop_shake_water_max_supported` | | | | | | X | | | | | X | | | | | | | | +| `is_multi_floor_supported` | | X | | | | | X | | | X | | | X | X | | | | | +| `is_multi_map_segment_timer_supported` | X | X | | X | X | X | X | X | | X | X | X | X | X | | | | | +| `is_new_ai_recognition_supported` | | X | X | | X | X | | X | | X | X | | | | | | | | +| `is_new_data_for_clean_history` | | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_new_data_for_clean_history_detail` | | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_new_endpoint_supported` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_new_remote_view_supported` | X | X | | | X | X | X | X | X | X | X | | X | | X | X | X | X | +| `is_no_need_carpet_press_set_supported` | | X | X | | X | X | | X | | X | X | | | | | | | | +| `is_none_pure_clean_mop_with_max_plus` | | | | X | | | | | | | | | | | | | | | +| `is_object_detect_check_supported` | | X | | | X | X | | X | | X | X | | | | | | | | +| `is_offline_map_supported` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_optimize_battery_supported` | | | | | | | | | | | | | | | | | | | +| `is_order_clean_supported` | | X | | | | | X | | | X | | | X | X | | | | | +| `is_over_sea_ctm_supported` | | | | | X | | | X | | X | X | | | | | | | | +| `is_pet_snapshot_supported` | | X | | | X | X | | | | X | X | | | | | | | | +| `is_pet_supplies_deep_clean_supported` | | X | X | | X | X | | X | | X | X | | | | | | | | +| `is_program_mode_supported` | | | | | | | | | | | | | | | | | | | +| `is_pumping_water_supported` | | | | | | | | | | | | | | | | | | | +| `is_pure_clean_mop_supported` | | X | X | X | X | X | X | X | X | X | X | X | X | | X | X | X | X | +| `is_re_segment_supported` | X | X | | X | X | X | X | X | | X | X | X | X | X | | | | | +| `is_record_allowed` | X | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_remote_supported` | | X | | | | | X | | | X | | | X | X | | | | | +| `is_right_brush_stretch_supported` | | X | | | X | X | | X | | X | | | | | | | | | +| `is_roller_mop_supported` | | | | | | | | | | | X | | | | | | | | +| `is_room_name_supported` | X | X | | X | X | X | X | X | | X | X | X | X | X | | | | | +| `is_rpc_retry_supported` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_rubber_brush_carpet_supported` | | | | | | | | | | | | | | | | | | | +| `is_set_child_supported` | X | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_setting_carpet_first_supported` | | X | X | | X | X | | X | | X | X | X | X | | | | | | +| `is_shake_mop_set_supported` | | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_should_show_arm_over_load_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_show_clean_finish_reason_supported` | X | X | | X | X | X | X | X | | X | X | X | X | X | | | | | +| `is_show_general_obstacle_supported` | | | | | | | | | | | | | | | | | | | +| `is_show_obstacle_photo_supported` | | | | | | | | | | | | | | | | | | | +| `is_side_brush_lift_carpet_supported` | | | | | X | | | | | | X | | | | | | | | +| `is_small_side_mop_supported` | | | | | | X | | | | | | | | | | | | | +| `is_smart_clean_mode_set_supported` | | X | X | | X | X | | X | | X | X | | X | | | | | | +| `is_soak_and_wash_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_soft_clean_mode_supported` | X | | | | | | | | | | | | | | | | | | +| `is_sr_map_supported` | | | | | | | | | | | | | | | | | | | +| `is_super_deep_wash_supported` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_api_app_stop_grasp_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_support_backup_map` | | X | | X | X | X | X | X | | X | X | X | X | X | | | | | +| `is_support_clean_estimate` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_cliff_zone` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_custom_carpet` | | | | | | | | | | | | | | | | | | | +| `is_support_custom_dnd` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_custom_door_sill` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_custom_mode_in_cleaning` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_fetch_timer_summary` | | X | | | | | X | | | X | | | X | X | | | | | +| `is_support_floor_direction` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_floor_edit` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_furniture` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_get_particular_status_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_support_incremental_map` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_main_brush_up_down_supported` | | | | | X | X | | | | X | X | | | | | | | | +| `is_support_mop_back_pwm_set` | | | | | | | | | | | | X | | | | | | | +| `is_support_quick_map_builder` | | X | | X | X | X | X | X | | X | X | X | X | X | | | | | +| `is_support_remote_control_in_call` | | X | | | X | X | | | | X | X | | X | | | | | | +| `is_support_room_tag` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_set_switch_map_mode` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_set_volume_in_call` | | X | | | X | X | | | | X | X | | X | | | | | | +| `is_support_side_brush_up_down_supported` | | | | | X | X | | | | | | | | | | | | | +| `is_support_smart_door_sill` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_smart_global_clean_with_custom_mode` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_smart_scene` | X | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_stuck_zone` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_support_voice_control_debug` | | | | | | | | | | | | | | | | | | | +| `is_support_water_mode` | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | X | +| `is_supported_download_test_voice` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_supported_drying` | | X | | | X | X | | X | | X | X | X | X | | | | | | +| `is_supported_valley_electricity` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_sync_server_name_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_three_d_mapping_inner_test_supported` | | | | | | | | | | | | | | | | | | | +| `is_tidyup_zones_supported` | | | | | | | | | | | | | | | | | | | +| `is_two_gears_no_collision_supported` | | | | | | | | | | X | X | | | | | | | | +| `is_two_key_real_time_video_supported` | | X | | | X | | | | | X | X | | X | | | | | | +| `is_two_key_rtv_in_charging_supported` | | X | | | X | X | | | | X | X | | X | | | | | | +| `is_type_identify_supported` | | | | | | | | | | | | | | | | | | | +| `is_unsave_map_reason_supported` | | X | | X | X | X | X | X | | X | X | X | X | X | | | | | +| `is_uvc_sterilize_supported` | | | | | | | | | | | | | | | | | | | +| `is_video_monitor_supported` | X | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_video_patrol_supported` | | X | | | X | X | | | | X | X | | | | | | | | +| `is_video_setting_supported` | X | X | | X | X | X | X | X | | X | X | X | X | | | | | | +| `is_voice_control_led_supported` | | | | | X | X | | | | | | | | | | | | | +| `is_voice_control_supported` | | X | | | X | X | | | | X | X | | X | | | | | | +| `is_wash_then_charge_cmd_supported` | | X | | X | X | X | | X | | X | X | X | X | | | | | | +| `is_water_leak_check_supported` | | | | | | X | | | | X | X | X | X | | | | | | +| `is_water_slide_mode_supported` | | | | | X | | | | | X | X | | | | | | | | +| `is_water_up_down_drain_supported` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_wifi_manage_supported` | | X | X | X | X | X | | X | | X | X | X | X | | | | | | +| `is_workday_holiday_supported` | | | | | | | | | | | X | | | | | | | | diff --git a/roborock/cli.py b/roborock/cli.py index c797213c..723dfa2a 100644 --- a/roborock/cli.py +++ b/roborock/cli.py @@ -57,7 +57,7 @@ YXDeviceDustCollectionFrequency, YXFanLevel, ) -from roborock.data.code_mappings import SHORT_MODEL_TO_ENUM +from roborock.data.code_mappings import SHORT_MODEL_TO_ENUM, RoborockProductNickname from roborock.device_features import DeviceFeatures from roborock.devices.cache import Cache, CacheData from roborock.devices.device import RoborockDevice @@ -1316,12 +1316,19 @@ def update_docs(data_file: str, output_file: str): # Process the combined data to build the feature map for model, data in combined_product_data.items(): + nickname_name = data.get("product_nickname") + product_nickname = SHORT_MODEL_TO_ENUM.get(model.split(".")[-1], RoborockProductNickname.PEARLPLUS) + if nickname_name not in (None, "", "Unknown"): + try: + product_nickname = RoborockProductNickname[nickname_name] + except KeyError as err: + raise click.ClickException(f"Unknown product nickname {nickname_name!r} for {model}") from err # Reconstruct the DeviceFeatures object from the raw data in the YAML file device_features = DeviceFeatures.from_feature_flags( new_feature_info=data.get("new_feature_info", 0), new_feature_info_str=data.get("new_feature_info_str", ""), feature_info=data.get("feature_info", []), - product_nickname=data.get("product_nickname", ""), + product_nickname=product_nickname, ) features_dict = asdict(device_features) @@ -1335,6 +1342,8 @@ def update_docs(data_file: str, output_file: str): # Populate features from the calculated DeviceFeatures object for feature, is_supported in features_dict.items(): + if not isinstance(is_supported, bool): + continue all_feature_names.add(feature) if is_supported: current_product_data[feature] = "X" diff --git a/tests/devices/test_device_manager.py b/tests/devices/test_device_manager.py index 734c2065..634471db 100644 --- a/tests/devices/test_device_manager.py +++ b/tests/devices/test_device_manager.py @@ -279,30 +279,32 @@ async def test_start_connect_failure( fake_device.local_channel.inject_error(channel_exception) ready_devices: list[RoborockDevice] = [] - device_manager = await create_device_manager(USER_PARAMS, ready_callback=ready_devices.append) - devices = await device_manager.get_devices() + ready = asyncio.Event() - # Device should exist but not be connected - assert len(devices) == 1 - assert not devices[0].is_connected - assert not ready_devices - - # Clear error so connection succeeds on retry - fake_device.mqtt_channel.clear_error() - fake_device.local_channel.clear_error() - - # Wait for the device to attempt to connect again and succeed - attempts = 0 - while not devices[0].is_connected: - await asyncio.sleep(0.01) - attempts += 1 - assert attempts < 10, "Device did not connect after multiple attempts" - - assert devices[0].is_connected - assert ready_devices - assert len(ready_devices) == 1 + def on_ready(device: RoborockDevice) -> None: + ready_devices.append(device) + ready.set() - await device_manager.close() + device_manager = await create_device_manager(USER_PARAMS, ready_callback=on_ready) + try: + devices = await device_manager.get_devices() + + # Device should exist but not be connected + assert len(devices) == 1 + assert not devices[0].is_connected + assert not ready_devices + + # Clear error so connection succeeds on retry + fake_device.mqtt_channel.clear_error() + fake_device.local_channel.clear_error() + + # Transport connection can precede initialization and the ready callback. + await asyncio.wait_for(ready.wait(), timeout=5) + + assert devices[0].is_connected + assert ready_devices == devices + finally: + await device_manager.close() async def test_rediscover_devices( diff --git a/tests/test_cli.py b/tests/test_cli.py index 2dc63835..ac77c75b 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,20 +1,103 @@ """Tests for the command line interface.""" import json +from dataclasses import asdict from pathlib import Path from typing import Any from unittest.mock import Mock import pytest +import yaml from click.testing import CliRunner from roborock.cli import ConnectionCache, RoborockContext, cli -from roborock.data import HomeDataSchedule, UserData +from roborock.data import HomeDataProduct, HomeDataSchedule, UserData +from roborock.device_features import DeviceFeatures from roborock.exceptions import RoborockException from roborock.web_api import RoborockApiClient from tests.mock_data import USER_DATA, USER_EMAIL +@pytest.mark.parametrize( + ("nickname_name", "short_model"), + [ + ("PEARLPLUS", "a87"), + ("TANOS", "s6"), + ("ULTRONLITE", "a73"), + ("Unknown", "test"), + ("", "test"), + (None, "test"), + ("Unknown", "s6"), + ("", "s6"), + (None, "s6"), + ], +) +def test_update_docs_nickname( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, + nickname_name: str | None, + short_model: str, +) -> None: + """Generated capabilities agree with runtime decoding of the same family.""" + monkeypatch.chdir(tmp_path) + model = f"roborock.vacuum.{short_model}" + product = HomeDataProduct.from_dict( + {"id": "test", "name": "Test", "model": model, "category": "robot.vacuum.cleaner"} + ) + data_file = tmp_path / "devices.yaml" + output_file = tmp_path / "features.md" + data_file.write_text( + yaml.safe_dump( + { + model: { + "product_nickname": nickname_name, + "new_feature_info": 0, + "new_feature_info_str": "0", + "feature_info": [119], + } + } + ), + encoding="utf-8", + ) + + result = CliRunner().invoke(cli, ["update-docs", "--data-file", str(data_file), "--output-file", str(output_file)]) + + assert result.exit_code == 0, result.output + rows = { + cells[0].strip("`"): cells[1] + for line in output_file.read_text(encoding="utf-8").splitlines()[2:] + if (cells := [cell.strip() for cell in line.strip("|").split("|")]) + } + expected = { + name: value + for name, value in asdict(DeviceFeatures.from_feature_flags(0, "0", [119], product.product_nickname)).items() + if isinstance(value, bool) + } + assert {name: rows[name] == "X" for name in expected} == expected + assert rows["119"] == "X" + assert rows["new_feature_info"] == "0" + assert rows["new_feature_info_str"] == "0" + assert "feature_info" not in rows + + +def test_update_docs_invalid_nickname(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: + """A misspelled family is reported rather than silently losing capabilities.""" + monkeypatch.chdir(tmp_path) + data_file = tmp_path / "devices.yaml" + output_file = tmp_path / "features.md" + data_file.write_text( + yaml.safe_dump({"roborock.vacuum.test": {"product_nickname": "PEARLPLUSS_TYPO"}}), + encoding="utf-8", + ) + + result = CliRunner().invoke(cli, ["update-docs", "--data-file", str(data_file), "--output-file", str(output_file)]) + + assert result.exit_code != 0 + assert "PEARLPLUSS_TYPO" in result.output + assert "roborock.vacuum.test" in result.output + assert not output_file.exists() + + @pytest.fixture(autouse=True) def isolated_login(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None: """Use temporary cached credentials so commands never load the user's login."""