diff --git a/docs/回调消息协议.md b/docs/回调消息协议.md index c4c3c3c0dd..bf289ee7bf 100644 --- a/docs/回调消息协议.md +++ b/docs/回调消息协议.md @@ -81,6 +81,10 @@ Todo 分辨率不被支持 - `ResolutionError` 分辨率获取错误 +- `Disconnect` + 连接断开(adb / 模拟器 炸了,且已经重试过一次) +- `CommandExecFailed` + 命令执行失败(adb / 模拟器 炸了,且已经重试过一次) #### AllTasksCompleted diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index bd71c84389..54932c3f29 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -248,8 +248,6 @@ std::optional> asst::Controller::call_command(const s std::vector pipe_data; - std::unique_lock pipe_lock(m_pipe_mutex); - auto start_time = std::chrono::steady_clock::now(); auto check_timeout = [&]() -> bool { return timeout && @@ -268,6 +266,7 @@ std::optional> asst::Controller::call_command(const s if (!recv_by_socket) { DWORD peek_num = 0; DWORD read_num = 0; + std::unique_lock pipe_lock(m_pipe_mutex); do { //DWORD write_num = 0; //WriteFile(parent_write, cmd.c_str(), cmd.size(), &write_num, nullptr); @@ -279,6 +278,7 @@ std::optional> asst::Controller::call_command(const s } while (::WaitForSingleObject(process_info.hProcess, 0) == WAIT_TIMEOUT && !check_timeout()); } else { + std::unique_lock pipe_lock(m_pipe_mutex); fd_set fdset = { 0 }; FD_SET(m_server_sock, &fdset); timeval select_timeout = { 3, 0 }; @@ -327,6 +327,7 @@ std::optional> asst::Controller::call_command(const s else if (m_child > 0) { // parent process // LogTraceScope("Parent process: " + cmd); + std::unique_lock pipe_lock(m_pipe_mutex); do { ssize_t read_num = read(m_pipe_out[PIPE_READ], m_pipe_buffer.get(), PipeBuffSize); @@ -350,9 +351,48 @@ std::optional> asst::Controller::call_command(const s if (!exit_ret) { return pipe_data; } - else { - return std::nullopt; + else if (m_inited) { + // 之前可以运行,突然运行不了了,这种情况多半是 adb 炸了。所以重新连接一下 + m_inited = false; + auto reconnect_ret = call_command(m_adb.connect, 60 * 1000); + bool is_reconnect_success = false; + if (reconnect_ret) { + auto& reconnect_val = reconnect_ret.value(); + std::string reconnect_str( + std::make_move_iterator(reconnect_val.begin()), + std::make_move_iterator(reconnect_val.end())); + is_reconnect_success = reconnect_str.find("error") == std::string::npos; + } + if (is_reconnect_success) { + auto recall_ret = call_command(cmd, timeout, recv_by_socket); + if (recall_ret) { + m_inited = true; + return recall_ret; + } + else { + json::value info = json::object{ + { "uuid", m_uuid}, + { "what", "CommandExecFailed" }, + { "why", "I dont fucking know, go look at the log!" }, + { "details", json::object { + { "cmd", cmd }, + { "recv_by_socket", recv_by_socket} + }} }; + m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); + } + } + else { + json::value info = json::object{ + { "uuid", m_uuid}, + { "what", "Disconnect" }, + { "why", "Reconnect failed" }, + { "details", json::object { + { "cmd", m_adb.connect } + }} }; + m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); + } } + return std::nullopt; } void asst::Controller::convert_lf(std::vector& data) @@ -433,6 +473,7 @@ void asst::Controller::random_delay() const void asst::Controller::clear_info() noexcept { + m_inited = false; m_adb = decltype(m_adb)(); m_uuid.clear(); m_width = 0; @@ -590,16 +631,19 @@ bool asst::Controller::screencap() screencap(m_adb.screencap_raw_by_nc, decode_raw, true)) { m_adb.screencap_method = AdbProperty::ScreencapMethod::RawByNc; Log.info("screencap by RawByNc"); + m_inited = true; return true; } else if (screencap(m_adb.screencap_raw_with_gzip, decode_raw_with_gzip)) { m_adb.screencap_method = AdbProperty::ScreencapMethod::RawWithGzip; Log.info("screencap by RawWithGzip"); + m_inited = true; return true; } else if (screencap(m_adb.screencap_encode, decode_encode)) { m_adb.screencap_method = AdbProperty::ScreencapMethod::Encode; Log.info("screencap by Encode"); + m_inited = true; return true; } else { @@ -864,9 +908,18 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a /* connect */ { - auto connect_ret = call_command(cmd_replace(adb_cfg.connect), 60 * 1000); + m_adb.connect = cmd_replace(adb_cfg.connect); + auto connect_ret = call_command(m_adb.connect, 60 * 1000); // 端口即使错误,命令仍然会返回0,TODO 对connect_result进行判断 - if (!connect_ret) { + bool is_connect_success = false; + if (connect_ret) { + auto& connect_val = connect_ret.value(); + std::string connect_str( + std::make_move_iterator(connect_val.begin()), + std::make_move_iterator(connect_val.end())); + is_connect_success = connect_str.find("error") == std::string::npos; + } + if (!is_connect_success) { json::value info = get_info_json() | json::object{ { "what", "ConnectFailed" }, @@ -1085,11 +1138,16 @@ const std::string& asst::Controller::get_uuid() const cv::Mat asst::Controller::get_image(bool raw) { + bool inited = m_inited; // 有些模拟器adb偶尔会莫名其妙截图失败,多试几次 for (int i = 0; i != 20; ++i) { if (screencap()) { break; } + // 截图之前正常,截图之后不正常了,说明截图过程中发现 adb 炸了 + if (inited && !m_inited) { + break; + } } if (raw) { diff --git a/src/MeoAssistant/Controller.h b/src/MeoAssistant/Controller.h index 21b2f4bf1c..adbac00e5c 100644 --- a/src/MeoAssistant/Controller.h +++ b/src/MeoAssistant/Controller.h @@ -114,6 +114,7 @@ namespace asst struct AdbProperty { /* command */ + std::string connect; std::string click; std::string swipe; @@ -150,6 +151,7 @@ namespace asst int m_height = 0; bool m_support_socket = false; bool m_server_started = false; + bool m_inited = false; inline static int m_instance_count = 0; diff --git a/src/MeoAsstGui/Helper/AsstProxy.cs b/src/MeoAsstGui/Helper/AsstProxy.cs index a30f4c72de..b32c0da153 100644 --- a/src/MeoAsstGui/Helper/AsstProxy.cs +++ b/src/MeoAsstGui/Helper/AsstProxy.cs @@ -170,11 +170,17 @@ namespace MeoAsstGui break; case "UnsupportedResolution": - mainModel.AddLog("分辨率过低\n请设置为 720p 或更高", "darkred"); + mainModel.AddLog("分辨率过低,请设置为 720p 或更高", "darkred"); break; case "ResolutionError": - mainModel.AddLog("分辨率获取失败\n建议重启电脑\n或更换模拟器后再试", "darkred"); + mainModel.AddLog("分辨率获取失败,建议重启电脑,或更换模拟器后再试", "darkred"); + break; + + case "Disconnect": + case "CommandExecFailed": + mainModel.AddLog("错误!连接断开!", "darkred"); + AsstStop(); break; } }