/* * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD * * SPDX-License-Identifier: MIT */ #pragma once #include "common.h" #include #include #include #include #include #include #include namespace setup_workers { /** * @brief * */ class WorkerBase { public: virtual ~WorkerBase() = default; virtual void update() { } bool isDone() const { return _is_done; } protected: bool _is_done = false; }; /** * @brief * */ class ZeroCalibrationWorker : public WorkerBase { public: ZeroCalibrationWorker(); void update() override; private: std::unique_ptr _page_tips; std::unique_ptr _page_calibration; }; /** * @brief * */ class ServoTestWorker : public WorkerBase { public: ServoTestWorker(); void update() override; private: std::unique_ptr _page_tips; std::unique_ptr _page_test; std::unique_ptr _page_done; }; /** * @brief * */ class WifiSetupWorker : public WorkerBase { public: WifiSetupWorker(); ~WifiSetupWorker(); void update() override; private: enum class State { None, AppDownload, WaitAppConnection, AppConnected, Done, }; State _state = State::AppDownload; State _last_state = State::None; uint32_t _last_tick = 0; bool _is_first_in = false; AppConfigEvent _last_app_config_event = AppConfigEvent::None; int _app_config_signal_id = -1; struct StateAppDownloadData { std::unique_ptr panel; std::unique_ptr title; std::unique_ptr qrcode_ios; std::unique_ptr qrcode_android; std::unique_ptr label_ios; std::unique_ptr label_android; std::unique_ptr btn_next; std::unique_ptr btn_quit; std::unique_ptr info; bool next_clicked = false; bool quit_clicked = false; void reset() { panel.reset(); title.reset(); qrcode_ios.reset(); qrcode_android.reset(); label_ios.reset(); label_android.reset(); btn_next.reset(); btn_quit.reset(); info.reset(); next_clicked = false; quit_clicked = false; } }; StateAppDownloadData _state_app_download_data; struct StateWaitAppConnectionData { std::unique_ptr panel; std::unique_ptr btn_id; std::unique_ptr info; void reset() { panel.reset(); btn_id.reset(); info.reset(); } }; StateWaitAppConnectionData _state_wait_app_connection_data; struct StateDoneData { int reboot_count = 0; }; StateDoneData _state_done_data; void update_state(); void cleanup_ui(); void switch_state(State newState); }; /** * @brief * */ class RgbTestWorker : public WorkerBase { public: RgbTestWorker(); ~RgbTestWorker(); private: std::unique_ptr _panel; std::vector> _buttons; }; /** * @brief * */ class MicTestWorker : public WorkerBase { public: MicTestWorker(); ~MicTestWorker(); void update() override; private: void update_button_text(); void update_button_state(); void update_button_color(); void update_waveform(); std::unique_ptr _panel; std::unique_ptr _chart_waveform; std::unique_ptr _btn_test; std::unique_ptr _btn_back; MicTestStatus _status = MicTestStatus::Done; bool _test_flag = false; bool _back_flag = false; bool _is_testing = false; int _waveform_series = -1; uint8_t _original_volume = 80; uint32_t _last_waveform_tick = 0; std::string _error_message; std::vector _waveform_frame; }; /** * @brief * */ class StartupWorker : public WorkerBase { public: class PageStartup { public: PageStartup(); bool isSkipClicked() const { return _is_skip_clicked; } bool isStartClicked() const { return _is_start_clicked; } private: std::unique_ptr _panel; std::unique_ptr _info; std::unique_ptr _btn_skip; std::unique_ptr _btn_start; bool _is_skip_clicked = false; bool _is_start_clicked = false; }; StartupWorker(); ~StartupWorker(); void update() override; private: std::unique_ptr _page_startup; std::unique_ptr _worker_servo_test; std::unique_ptr _worker_wifi; }; /** * @brief * */ class FwVersionWorker : public WorkerBase { public: FwVersionWorker(); ~FwVersionWorker(); void update() override; private: uint32_t _last_tick = 0; }; /** * @brief * */ class SystemUpdateWorker : public WorkerBase { public: SystemUpdateWorker(); ~SystemUpdateWorker(); void update() override; }; /** * @brief * */ class BrightnessSetupWorker : public WorkerBase { public: BrightnessSetupWorker(); ~BrightnessSetupWorker(); void update() override; private: std::unique_ptr _panel; std::unique_ptr _label_brightness; std::unique_ptr _slider; std::unique_ptr _btn_confirm; uint8_t _original_brightness = 0; int32_t _target_brightness = -1; bool _confirmed = false; }; /** * @brief * */ class VolumeSetupWorker : public WorkerBase { public: VolumeSetupWorker(); ~VolumeSetupWorker(); void update() override; private: std::unique_ptr _panel; std::unique_ptr _label_volume; std::unique_ptr _slider; std::unique_ptr _btn_confirm; std::vector _volume_levels; uint8_t _original_volume = 0; int32_t _target_volume = -1; bool _confirmed = false; }; /** * @brief * */ class XiaozhiPowerSavingWorker : public WorkerBase { public: XiaozhiPowerSavingWorker(); void update() override; private: void update_idle_label(); std::unique_ptr _panel; std::unique_ptr _panel_idle_shutdown; std::unique_ptr _panel_charging; std::unique_ptr _label_idle_title; std::unique_ptr _label_idle_value; std::unique_ptr _slider_idle_shutdown; std::unique_ptr _label_charging_title; std::unique_ptr _switch_charging; std::unique_ptr _btn_confirm; XiaozhiConfig_t _config; std::vector _idle_shutdown_levels; int32_t _pending_idle_index = -1; bool _confirm_flag = false; }; /** * @brief * */ class XiaozhiGeneralWorker : public WorkerBase { public: XiaozhiGeneralWorker(); void update() override; private: void update_idle_motion_label(); std::unique_ptr _panel; std::unique_ptr _panel_general; std::unique_ptr _label_idle_motion_title; std::unique_ptr _label_idle_motion_value; std::unique_ptr _slider_idle_motion; std::unique_ptr _btn_confirm; XiaozhiConfig_t _config; std::vector _idle_motion_levels; int32_t _pending_idle_motion_index = -1; bool _confirm_flag = false; }; /** * @brief * */ class TimezoneWorker : public WorkerBase { public: TimezoneWorker(); ~TimezoneWorker(); void update() override; private: std::unique_ptr _panel; std::unique_ptr _roller; std::unique_ptr _btn_confirm; std::unique_ptr _label; bool _confirm_flag = false; }; /** * @brief * */ class FactoryResetWorker : public WorkerBase { public: FactoryResetWorker(std::function beforeResetAction = {}); ~FactoryResetWorker(); void update() override; private: std::unique_ptr _panel; std::unique_ptr _label_title; std::unique_ptr _label_info; std::unique_ptr _btn_cancel; std::unique_ptr _btn_confirm; int _confirm_count = 0; bool _cancel_flag = false; bool _confirm_flag = false; std::function _before_reset_action; void update_ui(); }; /** * @brief * */ class AccountWorker : public WorkerBase { public: class PanelInfo { public: PanelInfo(lv_obj_t* parent, int posY, std::string_view title, std::string_view info); private: std::unique_ptr _panel; std::unique_ptr _label_title; std::unique_ptr _label_info; }; class PageAccount { public: PageAccount(std::string_view username, std::string_view deviceName); bool isUnbindClicked() const { return _is_unbind_clicked; } bool isQuitClicked() const { return _is_quit_clicked; } private: std::unique_ptr _panel; std::unique_ptr _label_title; std::unique_ptr _panel_username; std::unique_ptr _panel_device_name; std::unique_ptr _btn_unbind; std::unique_ptr _btn_quit; bool _is_unbind_clicked = false; bool _is_quit_clicked = false; }; AccountWorker(); ~AccountWorker(); void update() override; private: std::unique_ptr _page_account; std::unique_ptr _worker_reset; }; } // namespace setup_workers