mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
https://github.com/MaaAssistantArknights/MaaAssistantArknights/actions/runs/28622519749 [skip changelog]
233 lines
6.9 KiB
C++
233 lines
6.9 KiB
C++
#pragma once
|
||
|
||
#include "ControllerAPI.h"
|
||
|
||
#include <chrono>
|
||
#include <deque>
|
||
#include <random>
|
||
|
||
#include "Platform/PlatformFactory.h"
|
||
|
||
#include "Common/AsstMsg.h"
|
||
#include "Config/GeneralConfig.h"
|
||
#include "InstHelper.h"
|
||
#include "LDExtras.h"
|
||
#include "MumuExtras.h"
|
||
#include "Utils/StringMisc.hpp"
|
||
|
||
namespace asst
|
||
{
|
||
|
||
// 连接过程中的临时状态,基类 connect() 填充后子类直接复用
|
||
struct AdbConnectionContext
|
||
{
|
||
// 连接基本信息(reset 时设置)
|
||
std::string adb_path;
|
||
std::string address;
|
||
std::string package_name;
|
||
|
||
// 缓存的 ADB 配置(基类 connect 获取后存入)
|
||
AdbCfg adb_cfg;
|
||
|
||
// 连接过程中获取/更新的动态状态
|
||
std::string display_id;
|
||
std::string event_id;
|
||
std::string nc_address = "10.0.2.2";
|
||
uint16_t nc_port = 0;
|
||
|
||
void reset(const std::string& adb, const std::string& addr, const std::string& client_type)
|
||
{
|
||
adb_path = adb;
|
||
address = addr;
|
||
package_name = client_type.empty() ? "" : Config.get_package_name(client_type).value_or("");
|
||
adb_cfg = {};
|
||
display_id.clear();
|
||
event_id.clear();
|
||
nc_address = "10.0.2.2";
|
||
nc_port = 0;
|
||
}
|
||
|
||
std::string replace_cmd(const std::string& cfg_cmd) const
|
||
{
|
||
return utils::string_replace_all(
|
||
cfg_cmd,
|
||
{
|
||
{ "[Adb]", adb_path },
|
||
{ "[AdbSerial]", address },
|
||
{ "[DisplayId]", display_id },
|
||
{ "[EventId]", event_id },
|
||
{ "[NcPort]", std::to_string(nc_port) },
|
||
{ "[NcAddress]", nc_address },
|
||
});
|
||
}
|
||
};
|
||
|
||
class AdbController : public ControllerAPI, protected InstHelper
|
||
{
|
||
public:
|
||
AdbController(const AsstCallback& callback, Assistant* inst, PlatformType type);
|
||
AdbController(const AdbController&) = delete;
|
||
AdbController(AdbController&&) = delete;
|
||
virtual ~AdbController();
|
||
|
||
virtual bool connect(const std::string& adb_path, const std::string& address, const std::string& config) override;
|
||
|
||
virtual void set_kill_adb_on_exit(bool enable) noexcept override;
|
||
|
||
virtual bool inited() const noexcept override;
|
||
|
||
virtual const std::string& get_uuid() const override;
|
||
|
||
virtual size_t get_pipe_data_size() const noexcept override;
|
||
|
||
virtual size_t get_version() const noexcept override;
|
||
|
||
virtual bool screencap(cv::Mat& image_payload, bool allow_reconnect = false) override;
|
||
|
||
virtual bool start_game(const std::string& client_type) override;
|
||
virtual bool stop_game(const std::string& client_type) override;
|
||
|
||
virtual bool click(const Point& p) override;
|
||
|
||
virtual bool input(const std::string& text) override;
|
||
|
||
virtual bool swipe(
|
||
const Point& p1,
|
||
const Point& p2,
|
||
int duration = 0,
|
||
bool extra_swipe = false,
|
||
double slope_in = 1,
|
||
double slope_out = 1,
|
||
bool with_pause = false) override;
|
||
|
||
virtual bool inject_input_event([[maybe_unused]] const InputEvent& event) override { return false; }
|
||
|
||
virtual bool press_esc() override;
|
||
|
||
virtual ControlFeat::Feat support_features() const noexcept override { return ControlFeat::NONE; }
|
||
|
||
virtual std::pair<int, int> get_screen_res() const noexcept override;
|
||
|
||
AdbController& operator=(const AdbController&) = delete;
|
||
AdbController& operator=(AdbController&&) = delete;
|
||
|
||
virtual void back_to_home() noexcept override;
|
||
|
||
protected:
|
||
std::optional<std::string> call_command(
|
||
const std::string& cmd,
|
||
int64_t timeout = 20000,
|
||
bool allow_reconnect = true,
|
||
bool recv_by_socket = false);
|
||
|
||
virtual std::optional<std::string> reconnect(const std::string& cmd, int64_t timeout, bool recv_by_socket);
|
||
|
||
void release();
|
||
|
||
void close_socket() noexcept;
|
||
std::optional<unsigned short> init_socket(const std::string& local_address);
|
||
|
||
using DecodeFunc = std::function<bool(const std::string&)>;
|
||
bool screencap(
|
||
const std::string& cmd,
|
||
const DecodeFunc& decode_func,
|
||
bool allow_reconnect = false,
|
||
bool by_socket = false,
|
||
int max_timeout = 20000);
|
||
void clear_lf_info();
|
||
|
||
virtual void clear_info() noexcept;
|
||
void callback(AsstMsg msg, const json::value& details);
|
||
static int get_mumu_index(const std::string& address);
|
||
void init_mumu_extras(const AdbCfg& adb_cfg, const std::string& address);
|
||
void set_mumu_package(const std::string& client_type);
|
||
void init_ld_extras(const AdbCfg& adb_cfg, const std::string& address);
|
||
static int get_ld_index(const std::string& address);
|
||
|
||
// 转换 data 中的 CRLF 为 LF:有些模拟器自带的 adb,exec-out 输出的 \n 会被替换成 \r\n,
|
||
// 导致解码错误,所以这里转一下回来(点名批评 mumu 和雷电)
|
||
static bool convert_lf(std::string& data);
|
||
|
||
// 每 1 分钟检测一次模拟器帧率,回调给 UI 用于低帧率提示
|
||
void check_fps();
|
||
|
||
AdbConnectionContext m_conn_ctx;
|
||
|
||
AsstCallback m_callback;
|
||
|
||
std::mutex m_callcmd_mutex;
|
||
|
||
std::shared_ptr<asst::PlatformIO> m_platform_io = nullptr;
|
||
|
||
struct AdbProperty
|
||
{
|
||
/* command */
|
||
std::string devices;
|
||
std::string address_regex;
|
||
std::string connect;
|
||
std::string call_minitouch;
|
||
std::string call_maatouch;
|
||
std::string click;
|
||
std::string input;
|
||
std::string swipe;
|
||
std::string press_esc;
|
||
|
||
std::string screencap_raw_by_nc;
|
||
std::string screencap_raw_with_gzip;
|
||
std::string screencap_encode;
|
||
std::string release;
|
||
|
||
std::string start;
|
||
std::string stop;
|
||
|
||
std::string version;
|
||
|
||
std::string back_to_home;
|
||
|
||
std::string fps; // 获取模拟器刷新率的命令
|
||
|
||
/* properties */
|
||
enum class ScreencapEndOfLine
|
||
{
|
||
UnknownYet,
|
||
CRLF,
|
||
LF,
|
||
CR
|
||
} screencap_end_of_line = ScreencapEndOfLine::UnknownYet;
|
||
|
||
enum class ScreencapMethod
|
||
{
|
||
UnknownYet,
|
||
// Default,
|
||
RawByNc,
|
||
RawWithGzip,
|
||
Encode,
|
||
#if ASST_WITH_EMULATOR_EXTRAS
|
||
MumuExtras,
|
||
LDExtras,
|
||
#endif
|
||
} screencap_method = ScreencapMethod::UnknownYet;
|
||
} m_adb;
|
||
|
||
std::string m_uuid;
|
||
size_t m_pipe_data_size = 0;
|
||
size_t m_version = 0;
|
||
std::pair<int, int> m_screen_size = { 0, 0 };
|
||
int m_width = 0;
|
||
int m_height = 0;
|
||
bool m_support_socket = false;
|
||
bool m_server_started = false;
|
||
bool m_inited = false;
|
||
bool m_kill_adb_on_exit = false;
|
||
long long m_last_command_duration = 0; // 上次命令执行用时
|
||
std::deque<long long> m_screencap_cost; // 截图用时
|
||
int m_screencap_times = 0; // 截图次数
|
||
std::chrono::steady_clock::time_point m_last_fps_check_time; // 上次帧率检测时间
|
||
|
||
#if ASST_WITH_EMULATOR_EXTRAS
|
||
MumuExtras m_mumu_extras;
|
||
LDExtras m_ld_extras;
|
||
#endif
|
||
};
|
||
} // namespace asst
|