Files
OrcaSlicer/src/slic3r/Utils/MoonRaker.cpp
2025-12-29 11:25:44 +08:00

3119 lines
151 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Implementation of Moonraker printer host communication
#include "MoonRaker.hpp"
#include "MQTT.hpp"
#include <algorithm>
#include <sstream>
#include <exception>
#include <boost/format.hpp>
#include <boost/log/trivial.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/asio.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/nowide/convert.hpp>
#include <curl/curl.h>
#include <wx/progdlg.h>
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/format.hpp"
#include "Http.hpp"
#include "libslic3r/AppConfig.hpp"
#include "Bonjour.hpp"
#include "slic3r/GUI/BonjourDialog.hpp"
#include "slic3r/GUI/WebPreprintDialog.hpp"
#include "slic3r/GUI/SSWCP.hpp"
#include "sentry_wrapper/SentryWrapper.hpp"
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
namespace fs = boost::filesystem;
namespace pt = boost::property_tree;
namespace Slic3r {
namespace {
#ifdef WIN32
// Helper function to extract host and port from URL
std::string get_host_from_url(const std::string& url_in)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始解析URL获取主机信息: " << url_in;
wcp_loger.add_log("开始解析URL获取主机信息: " + url_in, false, "", "Moonraker_Mqtt", "info");
std::string url = url_in;
// Add http:// if there is no scheme
size_t double_slash = url.find("//");
if (double_slash == std::string::npos) {
url = "http://" + url;
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 添加默认协议前缀修改后的URL: " << url;
wcp_loger.add_log("添加默认协议前缀修改后的URL: " + url, false, "", "Moonraker_Mqtt", "info");
}
std::string out = url;
CURLU* hurl = curl_url();
if (hurl) {
// Parse the input URL
CURLUcode rc = curl_url_set(hurl, CURLUPART_URL, url.c_str(), 0);
if (rc == CURLUE_OK) {
// Extract host and port
char* host;
rc = curl_url_get(hurl, CURLUPART_HOST, &host, 0);
if (rc == CURLUE_OK) {
char* port;
rc = curl_url_get(hurl, CURLUPART_PORT, &port, 0);
if (rc == CURLUE_OK && port != nullptr) {
out = std::string(host) + ":" + port;
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 成功提取主机和端口: " << out;
wcp_loger.add_log("成功提取主机和端口 " + out, false, "", "Moonraker_Mqtt", "info");
curl_free(port);
} else {
out = host;
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 成功提取主机(无端口): " << out;
wcp_loger.add_log("成功提取主机(无端口): " + out, false, "", "Moonraker_Mqtt", "info");
curl_free(host);
}
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 从URL获取主机失败: " << url;
wcp_loger.add_log("从url获取主机失败: " + url, false, "", "Moonraker_Mqtt", "error");
}
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 解析URL失败: " << url;
wcp_loger.add_log("解析URL失败: " + url, false, "", "Moonraker_Mqtt", "error");
}
curl_url_cleanup(hurl);
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 分配curl_url失败";
wcp_loger.add_log("分配Curlurl失败", false, "", "Moonraker_Mqtt", "error");
}
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] URL解析完成返回结果: " << out;
wcp_loger.add_log("URL解析完成返回结果: " + out, false, "", "Moonraker_Mqtt", "info");
return out;
}
// Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
std::string substitute_host(const std::string& orig_addr, std::string sub_addr)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始替换主机地址,原地址: " << orig_addr << ", 新地址: " << sub_addr;
wcp_loger.add_log("开始替换主机地址,原地址: " + orig_addr + ", 新地址: " + sub_addr, false, "", "Moonraker_Mqtt", "info");
// put ipv6 into [] brackets
if (sub_addr.find(':') != std::string::npos && sub_addr.at(0) != '[') {
sub_addr = "[" + sub_addr + "]";
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 检测到IPv6地址添加方括号: " << sub_addr;
wcp_loger.add_log("检测到IPv6地址添加方括号: " + sub_addr, false, "", "Moonraker_Mqtt", "info");
}
#if 0
//URI = scheme ":"["//"[userinfo "@"] host [":" port]] path["?" query]["#" fragment]
std::string final_addr = orig_addr;
// http
size_t double_dash = orig_addr.find("//");
size_t host_start = (double_dash == std::string::npos ? 0 : double_dash + 2);
// userinfo
size_t at = orig_addr.find("@");
host_start = (at != std::string::npos && at > host_start ? at + 1 : host_start);
// end of host, could be port(:), subpath(/) (could be query(?) or fragment(#)?)
// or it will be ']' if address is ipv6 )
size_t potencial_host_end = orig_addr.find_first_of(":/", host_start);
// if there are more ':' it must be ipv6
if (potencial_host_end != std::string::npos && orig_addr[potencial_host_end] == ':' && orig_addr.rfind(':') != potencial_host_end) {
size_t ipv6_end = orig_addr.find(']', host_start);
// DK: Uncomment and replace orig_addr.length() if we want to allow subpath after ipv6 without [] parentheses.
potencial_host_end = (ipv6_end != std::string::npos ? ipv6_end + 1 : orig_addr.length()); //orig_addr.find('/', host_start));
}
size_t host_end = (potencial_host_end != std::string::npos ? potencial_host_end : orig_addr.length());
// now host_start and host_end should mark where to put resolved addr
// check host_start. if its nonsense, lets just use original addr (or resolved addr?)
if (host_start >= orig_addr.length()) {
return final_addr;
}
final_addr.replace(host_start, host_end - host_start, sub_addr);
return final_addr;
#else
// Using the new CURL API for handling URL. https://everything.curl.dev/libcurl/url
// If anything fails, return the input unchanged.
std::string out = orig_addr;
CURLU* hurl = curl_url();
if (hurl) {
// Parse the input URL.
CURLUcode rc = curl_url_set(hurl, CURLUPART_URL, orig_addr.c_str(), 0);
if (rc == CURLUE_OK) {
// Replace the address.
rc = curl_url_set(hurl, CURLUPART_HOST, sub_addr.c_str(), 0);
if (rc == CURLUE_OK) {
// Extract a string fromt the CURL URL handle.
char* url;
rc = curl_url_get(hurl, CURLUPART_URL, &url, 0);
if (rc == CURLUE_OK) {
out = url;
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 主机地址替换成功: " << out;
wcp_loger.add_log("主机地址替换成功: " + out, false, "", "Moonraker_Mqtt", "info");
curl_free(url);
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 替换后提取URL失败";
wcp_loger.add_log("替换后提取URL失败", false, "", "Moonraker_Mqtt", "error");
}
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 替换主机失败,主机: " << sub_addr << ", URL: " << orig_addr;
wcp_loger.add_log("替换主机失败,主机: " + sub_addr, false, "", "Moonraker_Mqtt", "error");
}
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 解析原始URL失败: " << orig_addr;
wcp_loger.add_log("解析原始URL失败: " + orig_addr, false, "", "Moonraker_Mqtt", "error");
}
curl_url_cleanup(hurl);
} else{
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 分配curl_url失败";
wcp_loger.add_log("分配curl_url失败", false, "", "Moonraker_Mqtt", "error");
}
return out;
#endif
}
#endif // WIN32
// Helper function to URL encode a string
std::string escape_string(const std::string& unescaped)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 开始URL编码字符串长度: " << unescaped.size();
wcp_loger.add_log("开始URL编码字符串长度: " + std::to_string(unescaped.size()), false, "", "Moonraker_Mqtt", "info");
std::string ret_val;
CURL* curl = curl_easy_init();
if (curl) {
char* decoded = curl_easy_escape(curl, unescaped.c_str(), unescaped.size());
if (decoded) {
ret_val = std::string(decoded);
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] URL编码成功";
wcp_loger.add_log("URL编码成功: ", false, "", "Moonraker_Mqtt", "info");
curl_free(decoded);
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] URL编码失败";
wcp_loger.add_log("URL编码失败", false, "", "Moonraker_Mqtt", "error");
}
curl_easy_cleanup(curl);
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 初始化CURL失败";
wcp_loger.add_log("初始化CURL失败", false, "", "Moonraker_Mqtt", "error");
}
return ret_val;
}
// Helper function to URL encode each element of a filesystem path
std::string escape_path_by_element(const boost::filesystem::path& path)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 开始路径元素编码: " << path.string();
wcp_loger.add_log("开始路径元素编码: " + path.string(), false, "", "Moonraker_Mqtt", "info");
std::string ret_val = escape_string(path.filename().string());
boost::filesystem::path parent(path.parent_path());
while (!parent.empty() &&
parent.string() != "/") // "/" check is for case "/file.gcode" was inserted. Then boost takes "/" as parent_path.
{
ret_val = escape_string(parent.filename().string()) + "/" + ret_val;
parent = parent.parent_path();
}
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 路径编码完成: " << ret_val;
wcp_loger.add_log("路径编码完成: " + ret_val, false, "", "Moonraker_Mqtt", "info");
return ret_val;
}
} // namespace
Moonraker::Moonraker(DynamicPrintConfig* config)
: m_host(config->opt_string("print_host"))
, m_apikey(config->opt_string("printhost_apikey"))
, m_cafile(config->opt_string("printhost_cafile"))
, m_ssl_revoke_best_effort(config->opt_bool("printhost_ssl_ignore_revoke"))
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 初始化Moonraker实例主机: " << m_host;
wcp_loger.add_log("初始化Moonraker实例主机: " + m_host, false, "", "Moonraker_Mqtt", "info");
}
// Return the name of this print host type
const char* Moonraker::get_name() const { return "Moonraker"; }
#ifdef WIN32
bool Moonraker::test_with_resolved_ip(wxString& msg) const
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始使用解析的IP进行测试";
wcp_loger.add_log("开始使用解析的IP进行测试", false, "", "Moonraker_Mqtt", "info");
// Since the request is performed synchronously here,
// it is ok to refer to `msg` from within the closure
const char* name = get_name();
bool res = true;
// Msg contains ip string.
auto url = substitute_host(make_url("api/version"), GUI::into_u8(msg));
msg.Clear();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 获取版本信息URL: %2%") % name % url;
wcp_loger.add_log(name + std::string(": 获取版本信息URL: ") + url, false, "", "Moonraker_Mqtt", "info");
std::string host = get_host_from_url(m_host);
auto http = Http::get(url); // std::move(url));
// "Host" header is necessary here. We have resolved IP address and subsituted it into "url" variable.
// And when creating Http object above, libcurl automatically includes "Host" header from address it got.
// Thus "Host" is set to the resolved IP instead of host filled by user. We need to change it back.
// Not changing the host would work on the most cases (where there is 1 service on 1 hostname) but would break when f.e. reverse proxy
// is used (issue #9734). Also when allow_ip_resolve = 0, this is not needed, but it should not break anything if it stays.
// https://www.rfc-editor.org/rfc/rfc7230#section-5.4
http.header("Host", host);
set_auth(http);
http.on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] " << boost::format("%1%: 获取版本信息出错URL: %2%, 错误: %3%, HTTP状态: %4%, 响应体: `%5%`") % name % url %
error % status % body;
wcp_loger.add_log(std::string(name) + "ddd" + url + ", 错误: " + error + ", HTTP状态: " + std::to_string(status) +
", 响应体: " + body,
false, "", "Moonraker_Mqtt", "error");
res = false;
msg = format_error(body, error, status);
})
.on_complete([&, this](std::string body, unsigned) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 获取版本信息成功: %2%") % name % body;
wcp_loger.add_log(std::string(name) + ": 获取版本信息成功: " + body, false, "", "Moonraker_Mqtt", "info");
try {
std::stringstream ss(body);
pt::ptree ptree;
pt::read_json(ss, ptree);
if (!ptree.get_optional<std::string>("api")) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 响应中未找到API字段";
wcp_loger.add_log("响应中未找到API字段", false, "", "Moonraker_Mqtt", "error");
res = false;
return;
}
const auto text = ptree.get_optional<std::string>("text");
res = validate_version_text(text);
if (!res) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 版本文本验证失败";
wcp_loger.add_log("版本文本验证失败", false, "", "Moonraker_Mqtt", "error");
msg = GUI::format_wxstr(_L("Mismatched type of print host: %s"), (text ? *text : name));
} else {
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 版本验证成功";
wcp_loger.add_log("版本验证成功", false, "", "Moonraker_Mqtt", "info");
}
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 解析服务器响应失败: " << e.what();
wcp_loger.add_log("解析服务器响应失败: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
res = false;
msg = "Could not parse server response.";
}
})
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
.perform_sync();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] IP测试完成结果: " << (res ? "成功" : "失败");
wcp_loger.add_log("IP测试完成结果: " + std::string(res ? "成功" : "失败"), false, "", "Moonraker_Mqtt", "info");
return res;
}
#endif // WIN32
bool Moonraker::get_machine_info(const std::vector<std::pair<std::string, std::vector<std::string>>>& targets, json& response) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取机器信息,目标数量: " << targets.size();
wcp_loger.add_log("开始获取机器信息,目标数量: " + std::to_string(targets.size()), false, "", "Moonraker_Mqtt", "info");
bool res = true;
auto url = make_url("printer/objects/query");
auto http = Http::post(std::move(url));
for (const auto pair : targets) {
std::string value = "";
for (size_t i = 0; i < pair.second.size(); ++i) {
if (i != 0) {
value += ",";
}
value += pair.second[i];
}
http.form_add(pair.first, value);
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 添加查询参数: " << pair.first << " = " << value;
wcp_loger.add_log("添加查询参数: " + pair.first + " = " + value, false, "", "Moonraker_Mqtt", "info");
}
http.on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 获取机器信息失败,错误: " << error << ", HTTP状态: " << status;
wcp_loger.add_log("获取机器信息失败,错误: " + error + ", HTTP状态: " + std::to_string(status), false, "", "Moonraker_Mqtt", "error");
res = false;
try{
response = json::parse(body);
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 解析错误响应失败: " << e.what();
wcp_loger.add_log("解析错误响应失败: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
}
})
.on_complete([&](std::string body, unsigned) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 获取机器信息成功";
wcp_loger.add_log("获取机器信息成功", false, "", "Moonraker_Mqtt", "info");
try {
response = json::parse(body);
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 解析机器信息响应失败: " << e.what();
wcp_loger.add_log("解析机器信息响应失败: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
}
})
.perform_sync();
return res;
}
bool Moonraker::send_gcodes(const std::vector<std::string>& codes, std::string& extraInfo)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始发送G代码数量: " << codes.size();
wcp_loger.add_log("开始发送G代码数量: " + std::to_string(codes.size()), false, "", "Moonraker_Mqtt", "info");
bool res = true;
std::string param = "?script=";
for (const auto code : codes) {
param += "\n";
param += code;
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 添加G代码: " << code;
wcp_loger.add_log("添加G代码: " + code, false, "", "Moonraker_Mqtt", "info");
}
auto url = make_url("printer/gcode/script");
auto http = Http::post(std::move(url));
http.form_add("script", param)
.on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送G代码失败错误: " << error << ", HTTP状态: " << status;
wcp_loger.add_log("发送G代码失败错误: " + error + ", HTTP状态: " + std::to_string(status), false, "", "Moonraker_Mqtt", "error");
res = false;
})
.on_complete([&](std::string body, unsigned){
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] G代码发送成功";
wcp_loger.add_log("G代码发送成功", false, "", "Moonraker_Mqtt", "info");
res = true;
})
.perform_sync();
return res;
}
bool Moonraker::test(wxString& msg) const
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始连接测试";
wcp_loger.add_log("开始连接测试", false, "", "Moonraker_Mqtt", "info");
//// test
//MqttClient* mqttClient = new MqttClient("mqtt://172.18.0.9:1883", "OrcaClient", false);
//mqttClient->SetMessageCallback([](const std::string& topic, const std::string& payload) {
// int a = 0;
// int b = 0;
//});
//mqttClient->Connect();
//mqttClient->Subscribe("9BD4E436F33D0B56/response", 2);
//mqttClient->Subscribe("9BD4E436F33D0B56/status", 2);
//mqttClient->Publish("9BD4E436F33D0B56/request", "{\"jsonrpc\": \"2.0\",\"method\": \"server.info\",\"id\": 9546}", 1);
// Since the request is performed synchronously here,
// it is ok to refer to `msg` from within the closure
const char* name = get_name();
bool res = true;
auto url = make_url("printer/info");
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 获取版本信息URL: %2%") % name % url;
wcp_loger.add_log(name + std::string(": 获取版本信息URL: ") + url, false, "", "Moonraker_Mqtt", "info");
// Here we do not have to add custom "Host" header - the url contains host filled by user and libCurl will set the header by itself.
auto http = Http::get(std::move(url));
set_auth(http);
http.on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] " << boost::format("%1%: 获取版本信息出错: %2%, HTTP状态: %3%, 响应体: `%4%`") % name % error % status %
body;
wcp_loger.add_log(name + std::string(": 获取版本信息出错: ") + error + ", HTTP状态: " + std::to_string(status) + ", 响应体: " + body, false, "", "Moonraker_Mqtt", "error");
res = false;
msg = format_error(body, error, status);
})
.on_complete([&, this](std::string body, unsigned) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 获取版本信息成功: %2%") % name % body;
wcp_loger.add_log(name + std::string(": 获取版本信息成功: ") + body, false, "", "Moonraker_Mqtt", "info");
//try {
// std::stringstream ss(body);
// pt::ptree ptree;
// pt::read_json(ss, ptree);
// if (!ptree.get_optional<std::string>("api")) {
// res = false;
// return;
// }
// const auto text = ptree.get_optional<std::string>("text");
// // test
// //res = validate_version_text(text);
// res = true;
// if (!res) {
// msg = GUI::format_wxstr(_L("Mismatched type of print host: %s"), (text ? *text : name));
// }
//} catch (const std::exception&) {
// res = false;
// msg = "Could not parse server response";
//}
})
#ifdef WIN32
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
.on_ip_resolve([&](std::string address) {
// Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
// Remember resolved address to be reused at successive REST API call.
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] IP解析成功: " << address;
wcp_loger.add_log("IP解析成功: " + address, false, "", "Moonraker_Mqtt", "info");
msg = GUI::from_u8(address);
})
#endif // WIN32
.perform_sync();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 连接测试完成,结果: " << (res ? "成功" : "失败");
wcp_loger.add_log("连接测试完成,结果: " + std::string((res ? "成功" : "失败")), false, "", "Moonraker_Mqtt", "info");
return res;
}
// Return success message for connection test
wxString Moonraker::get_test_ok_msg() const { return _(L("Connection to Moonraker works correctly.")); }
// Return formatted error message for failed connection test
wxString Moonraker::get_test_failed_msg(wxString& msg) const
{
return GUI::format_wxstr("%s: %s\n\n%s", _L("Could not connect to Moonraker"), msg,
_L("Note: Moonraker version at least 1.1.0 is required."));
}
// Upload a file to the printer
bool Moonraker::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始文件上传,源文件: " << upload_data.source_path.string()
<< ", 目标路径: " << upload_data.upload_path.string();
wcp_loger.add_log("开始文件上传,源文件: " + upload_data.source_path.string() + ", 目标路径: " + upload_data.upload_path.string(), false, "", "Moonraker_Mqtt", "info");
// 依赖flutter先放开
if (upload_data.post_action == PrintHostPostUploadAction::StartPrint) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 上传后需要开始打印,显示预打印对话框";
wcp_loger.add_log("上传后需要开始打印,显示预打印对话框", false, "", "Moonraker_Mqtt", "info");
// 创建 promise 和 future 用于线程同步
std::promise<bool> promise;
auto future = promise.get_future();
// 使用 CallAfter 切换到主线程
wxTheApp->CallAfter([this, &promise, upload_data, &wcp_loger]() {
GUI::WebPreprintDialog dialog;
dialog.set_gcode_file_name(upload_data.source_path.string());
dialog.set_display_file_name(upload_data.upload_path.string());
bool res = dialog.run();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 预打印对话框结果: " << (res ? "确认" : "取消");
wcp_loger.add_log("预打印对话框结果: " + std::string((res ? "确认" : "取消")), false, "", "Moonraker_Mqtt", "info");
// 设置结果
promise.set_value(res);
});
// 等待主线程完成
bool flag = future.get();
if (!flag) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 用户取消了打印,终止上传";
wcp_loger.add_log("用户取消了打印,终止上传", false, "", "Moonraker_Mqtt", "info");
Http::Progress progress(0, 0, 0, 0, "");
bool cancel = true;
prorgess_fn(progress, cancel);
return false;
}
}
#ifndef WIN32
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 使用主机名上传非Windows";
wcp_loger.add_log("使用主机名上传非Windows", false, "", "Moonraker_Mqtt", "info");
return upload_inner_with_host(std::move(upload_data), prorgess_fn, error_fn, info_fn);
#else
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] Windows平台开始IP解析流程";
wcp_loger.add_log("Windows平台开始IP解析流程", false, "", "Moonraker_Mqtt", "info");
std::string host = get_host_from_url(m_host);
// decide what to do based on m_host - resolve hostname or upload to ip
std::vector<boost::asio::ip::address> resolved_addr;
boost::system::error_code ec;
boost::asio::ip::address host_ip = boost::asio::ip::make_address(host, ec);
if (!ec) {
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 主机已是IP地址: " << host_ip.to_string();
wcp_loger.add_log("主机已是IP地址: " + host_ip.to_string(), false, "", "Moonraker_Mqtt", "info");
resolved_addr.push_back(host_ip);
} else if (GUI::get_app_config()->get_bool("allow_ip_resolve") && boost::algorithm::ends_with(host, ".local")) {
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 开始解析.local域名: " << host;
wcp_loger.add_log("开始解析.local域名: " + host, false, "", "Moonraker_Mqtt", "info");
Bonjour("Moonraker")
.set_hostname(host)
.set_retries(5) // number of rounds of queries send
.set_timeout(1) // after each timeout, if there is any answer, the resolving will stop
.on_resolve([&ra = resolved_addr, &wcp_loger](const std::vector<BonjourReply>& replies) {
for (const auto& rpl : replies) {
boost::asio::ip::address ip(rpl.ip);
ra.emplace_back(ip);
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 解析到IP地址: " << rpl.ip;
wcp_loger.add_log("解析到IP地址: " + rpl.ip.to_string(), false, "", "Moonraker_Mqtt", "info");
}
})
.resolve_sync();
}
// Handle different resolution scenarios
if (resolved_addr.empty()) {
// no resolved addresses - try system resolving
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 无法解析主机名 " << m_host
<< " 到IP地址使用系统解析进行上传";
wcp_loger.add_log("无法解析主机名 " + m_host + " 到IP地址使用系统解析进行上传", false, "", "Moonraker_Mqtt", "error");
return upload_inner_with_host(std::move(upload_data), prorgess_fn, error_fn, info_fn);
} else if (resolved_addr.size() == 1) {
// one address resolved - upload there
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 解析到单个地址,开始上传: " << resolved_addr.front().to_string();
wcp_loger.add_log("解析到单个地址,开始上传: " + resolved_addr.front().to_string(), false, "", "Moonraker_Mqtt", "info");
return upload_inner_with_resolved_ip(std::move(upload_data), prorgess_fn, error_fn, info_fn, resolved_addr.front());
} else if (resolved_addr.size() == 2 && resolved_addr[0].is_v4() != resolved_addr[1].is_v4()) {
// there are just 2 addresses and 1 is ip_v4 and other is ip_v6
// try sending to both. (Then if both fail, show both error msg after second try)
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 解析到IPv4和IPv6地址依次尝试上传";
wcp_loger.add_log("解析到IPv4和IPv6地址依次尝试上传", false, "", "Moonraker_Mqtt", "info");
wxString error_message;
if (!upload_inner_with_resolved_ip(
std::move(upload_data), prorgess_fn,
[&msg = error_message, resolved_addr, &wcp_loger](wxString error) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 第一个IP上传失败: " << resolved_addr.front().to_string();
wcp_loger.add_log("第一个IP上传失败: " + resolved_addr.front().to_string(), false, "", "Moonraker_Mqtt", "warning");
msg = GUI::format_wxstr("%1%: %2%", resolved_addr.front(), error);
},
info_fn, resolved_addr.front()) &&
!upload_inner_with_resolved_ip(
std::move(upload_data), prorgess_fn,
[&msg = error_message, resolved_addr, &wcp_loger](wxString error) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 第二个IP上传失败: " << resolved_addr.back().to_string();
wcp_loger.add_log("第二个IP上传失败: " + resolved_addr.back().to_string(), false, "", "Moonraker_Mqtt", "warning");
msg += GUI::format_wxstr("\n%1%: %2%", resolved_addr.back(), error);
},
info_fn, resolved_addr.back())) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 所有IP地址上传均失败";
wcp_loger.add_log("所有IP地址上传均失败", false, "", "Moonraker_Mqtt", "error");
error_fn(error_message);
return false;
}
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 至少一个IP地址上传成功";
wcp_loger.add_log("至少一个IP地址上传成功", false, "", "Moonraker_Mqtt", "info");
return true;
} else {
// There are multiple addresses - user needs to choose which to use.
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 解析到多个地址(" << resolved_addr.size() << "个),需要用户选择";
wcp_loger.add_log("解析到多个地址(" + std::to_string(resolved_addr.size()) + "个),需要用户选择", false, "", "Moonraker_Mqtt", "info");
size_t selected_index = resolved_addr.size();
IPListDialog dialog(nullptr, boost::nowide::widen(m_host), resolved_addr, selected_index);
if (dialog.ShowModal() == wxID_OK && selected_index < resolved_addr.size()) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 用户选择IP地址: " << resolved_addr[selected_index].to_string();
wcp_loger.add_log("用户选择IP地址: " + resolved_addr[selected_index].to_string(), false, "", "Moonraker_Mqtt", "info");
return upload_inner_with_resolved_ip(std::move(upload_data), prorgess_fn, error_fn, info_fn, resolved_addr[selected_index]);
} else {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 用户取消IP选择";
wcp_loger.add_log("用户取消IP选择", false, "", "Moonraker_Mqtt", "info");
}
}
return false;
#endif // WIN32
}
#ifdef WIN32
// Upload file using resolved IP address
bool Moonraker::upload_inner_with_resolved_ip(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn, const boost::asio::ip::address& resolved_addr) const
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 使用解析的IP地址上传: " << resolved_addr.to_string();
wcp_loger.add_log("使用解析的IP地址上传: " + resolved_addr.to_string(), false, "", "Moonraker_Mqtt", "info");
info_fn(L"resolve", boost::nowide::widen(resolved_addr.to_string()));
// If test fails, test_msg_or_host_ip contains the error message.
// Otherwise on Windows it contains the resolved IP address of the host.
// Test_msg already contains resolved ip and will be cleared on start of test().
wxString test_msg_or_host_ip = GUI::from_u8(resolved_addr.to_string());
if (/* !test_with_resolved_ip(test_msg_or_host_ip)*/ false) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] IP测试失败";
wcp_loger.add_log("IP测试失败", false, "", "Moonraker_Mqtt", "error");
error_fn(std::move(test_msg_or_host_ip));
return false;
}
const char* name = get_name();
const auto upload_filename = upload_data.upload_path.filename();
const auto upload_parent_path = upload_data.upload_path.parent_path();
std::string url = substitute_host(make_url("server/files/upload"), resolved_addr.to_string());
bool result = true;
info_fn(L"resolve", boost::nowide::widen(url));
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 上传文件 %2% 到 %3%, 文件名: %4%, 路径: %5%, 打印: %6%") % name %
upload_data.source_path % url % upload_filename.string() % upload_parent_path.string() %
(upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "" : "");
wcp_loger.add_log(name + std::string(": 上传文件 ") + upload_data.source_path.string() + "" + url + ", 文件名: " + upload_filename.string() + ", 路径: " + upload_parent_path.string() + ", 打印: " + (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "" : ""), false, "", "Moonraker_Mqtt", "info");
std::string host = get_host_from_url(m_host);
auto http = Http::post(url); // std::move(url));
// "Host" header is necessary here. We have resolved IP address and subsituted it into "url" variable.
// And when creating Http object above, libcurl automatically includes "Host" header from address it got.
// Thus "Host" is set to the resolved IP instead of host filled by user. We need to change it back.
// Not changing the host would work on the most cases (where there is 1 service on 1 hostname) but would break when f.e. reverse proxy
// is used (issue #9734). https://www.rfc-editor.org/rfc/rfc7230#section-5.4
http.header("Host", host);
set_auth(http);
http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
.form_add("path", upload_parent_path.string()) // XXX: slashes on windows ???
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
.on_complete([&](std::string body, unsigned status) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 文件上传成功: HTTP %2%: %3%") % name % status % body;
wcp_loger.add_log(name + std::string(": 文件上传成功: HTTP ") + std::to_string(status) + ": " + body, false, "", "Moonraker_Mqtt", "info");
})
.on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] " << boost::format("%1%: 上传文件到 %2% 失败: %3%, HTTP %4%, 响应体: `%5%`") % name % url % error %
status % body;
wcp_loger.add_log(name + std::string(": 上传文件到 ") + url + " 失败: " + error + ", HTTP " + std::to_string(status) + ", 响应体: `" + body + "`", false, "", "Moonraker_Mqtt", "error");
// 尝试8080端口
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 尝试使用8080端口重新上传";
wcp_loger.add_log("尝试使用8080端口重新上传", false, "", "Moonraker_Mqtt", "info");
url = substitute_host(make_url_8080("server/files/upload"), GUI::into_u8(test_msg_or_host_ip));
auto http_8080 = Http::post(std::move(url));
http_8080.header("host", host);
set_auth(http_8080);
http_8080.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
.form_add("path", upload_parent_path.string()) // XXX: slashes on windows ???
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
.on_complete([&](std::string body, unsigned status) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 8080端口文件上传成功: HTTP %2%: %3%") % name % status % body;
wcp_loger.add_log(name + std::string(": 8080端口文件上传成功: HTTP ") + std::to_string(status) + ": " + body, false, "", "Moonraker_Mqtt", "info");
})
.on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] " << boost::format("%1%: 8080端口上传失败: %2%, HTTP %3%, 响应体: `%4%`") % name % error %
status % body;
wcp_loger.add_log(name + std::string(": 8080端口上传失败: ") + error + ", HTTP " + std::to_string(status) + ", 响应体: `" + body + "`", false, "", "Moonraker_Mqtt", "error");
error_fn(format_error(body, error, status));
result = false;
})
.on_progress([&](Http::Progress progress, bool& cancel) {
prorgess_fn(std::move(progress), cancel);
if (cancel) {
// Upload was canceled
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << name << ": 8080端口上传被取消";
wcp_loger.add_log(name + std::string(": 8080端口上传被取消"), false, "", "Moonraker_Mqtt", "info");
result = false;
}
})
#ifdef WIN32
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
#endif
.perform_sync();
})
.on_progress([&](Http::Progress progress, bool& cancel) {
prorgess_fn(std::move(progress), cancel);
if (cancel) {
// Upload was canceled
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << name << ": 上传被取消";
wcp_loger.add_log(name + std::string(": 上传被取消"), false, "", "Moonraker_Mqtt", "info");
result = false;
}
})
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
.perform_sync();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] IP地址上传完成结果: " << (result ? "成功" : "失败");
wcp_loger.add_log("IP地址上传完成结果: " + std::string((result ? "成功" : "失败")), false, "", "Moonraker_Mqtt", "info");
return result;
}
#endif // WIN32
// Upload file using hostname
bool Moonraker::upload_inner_with_host(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 使用主机名上传文件";
wcp_loger.add_log("使用主机名上传文件", false, "", "Moonraker_Mqtt", "info");
const char* name = get_name();
const auto upload_filename = upload_data.upload_path.filename();
const auto upload_parent_path = upload_data.upload_path.parent_path();
// If test fails, test_msg_or_host_ip contains the error message.
// Otherwise on Windows it contains the resolved IP address of the host.
wxString test_msg_or_host_ip;
/*
if (!test(test_msg_or_host_ip)) {
error_fn(std::move(test_msg_or_host_ip));
return false;
}
*/
std::string url;
bool res = true;
#ifdef WIN32
// Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
if (m_host.find("https://") == 0 || test_msg_or_host_ip.empty() || !GUI::get_app_config()->get_bool("allow_ip_resolve"))
#endif // _WIN32
{
// If https is entered we assume signed ceritificate is being used
// IP resolving will not happen - it could resolve into address not being specified in cert
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 使用HTTPS或禁用IP解析直接使用主机名";
wcp_loger.add_log("使用HTTPS或禁用IP解析直接使用主机名", false, "", "Moonraker_Mqtt", "info");
url = make_url("server/files/upload");
}
#ifdef WIN32
else {
// Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
// Curl uses easy_getinfo to get ip address of last successful transaction.
// If it got the address use it instead of the stored in "host" variable.
// This new address returns in "test_msg_or_host_ip" variable.
// Solves troubles of uploades failing with name address.
// in original address (m_host) replace host for resolved ip
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 使用IP解析workaround";
wcp_loger.add_log("使用IP解析workaround", false, "", "Moonraker_Mqtt", "info");
info_fn(L"resolve", test_msg_or_host_ip);
url = substitute_host(make_url("server/files/upload"), GUI::into_u8(test_msg_or_host_ip));
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] IP解析后的上传地址: " << url;
wcp_loger.add_log("IP解析后的上传地址: " + url, false, "", "Moonraker_Mqtt", "info");
}
#endif // _WIN32
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 上传文件 %2% 到 %3%, 文件名: %4%, 路径: %5%, 打印: %6%") % name %
upload_data.source_path % url % upload_filename.string() % upload_parent_path.string() %
(upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "" : "");
wcp_loger.add_log(name + std::string(": 上传文件 ") + upload_data.source_path.string() + "" + url + ", 文件名: " + upload_filename.string() + ", 路径: " + upload_parent_path.string() + ", 打印: " + (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "" : ""), false, "", "Moonraker_Mqtt", "info");
auto http = Http::post(std::move(url));
#ifdef WIN32
// "Host" header is necessary here. In the workaround above (two mDNS..) we have got IP address from test connection and subsituted it
// into "url" variable. And when creating Http object above, libcurl automatically includes "Host" header from address it got. Thus "Host"
// is set to the resolved IP instead of host filled by user. We need to change it back. Not changing the host would work on the most cases
// (where there is 1 service on 1 hostname) but would break when f.e. reverse proxy is used (issue #9734). Also when allow_ip_resolve =
// 0, this is not needed, but it should not break anything if it stays. https://www.rfc-editor.org/rfc/rfc7230#section-5.4
std::string host = get_host_from_url(m_host);
http.header("Host", host);
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 设置Host头: " << host;
wcp_loger.add_log("设置Host头: " + host, false, "", "Moonraker_Mqtt", "info");
#endif // _WIN32
set_auth(http);
http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
.form_add("path", upload_parent_path.string()) // XXX: slashes on windows ???
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
.on_complete([&](std::string body, unsigned status) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 文件上传成功: HTTP %2%: %3%") % name % status % body;
wcp_loger.add_log(name + std::string(": 文件上传成功: HTTP ") + std::to_string(status) + ": " + body, false, "", "Moonraker_Mqtt", "info");
})
.on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] " << boost::format("%1%: 上传文件失败: %2%, HTTP %3%, 响应体: `%4%`") % name % error % status %
body;
wcp_loger.add_log(name + std::string(": 上传文件失败: ") + error + ", HTTP " + std::to_string(status) + ", 响应体: `" + body + "`", false, "", "Moonraker_Mqtt", "error");
// 尝试8080端口
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 尝试使用8080端口重新上传";
wcp_loger.add_log("尝试使用8080端口重新上传", false, "", "Moonraker_Mqtt", "info");
url = make_url_8080("server/files/upload");
auto http_8080 = Http::post(std::move(url));
set_auth(http_8080);
http_8080.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
.form_add("path", upload_parent_path.string()) // XXX: slashes on windows ???
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
.on_complete([&](std::string body, unsigned status) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << boost::format("%1%: 8080端口文件上传成功: HTTP %2%: %3%") % name % status % body;
wcp_loger.add_log(name + std::string(": 8080端口文件上传成功: HTTP ") + std::to_string(status) + ": " + body, false, "", "Moonraker_Mqtt", "info");
})
.on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] " << boost::format("%1%: 8080端口上传失败: %2%, HTTP %3%, 响应体: `%4%`") % name % error %
status % body;
wcp_loger.add_log(name + std::string(": 8080端口上传失败: ") + error + ", HTTP " + std::to_string(status) + ", 响应体: `" + body + "`", false, "", "Moonraker_Mqtt", "error");
error_fn(format_error(body, error, status));
res = false;
})
.on_progress([&](Http::Progress progress, bool& cancel) {
prorgess_fn(std::move(progress), cancel);
if (cancel) {
// Upload was canceled
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << name << ": 8080端口上传被取消";
wcp_loger.add_log(name + std::string(": 8080端口上传被取消"), false, "", "Moonraker_Mqtt", "info");
res = false;
}
})
#ifdef WIN32
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
#endif
.perform_sync();
})
.on_progress([&](Http::Progress progress, bool& cancel) {
prorgess_fn(std::move(progress), cancel);
if (cancel) {
// Upload was canceled
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] " << name << ": 上传被取消";
wcp_loger.add_log(name + std::string(": 上传被取消"), false, "", "Moonraker_Mqtt", "info");
res = false;
}
})
#ifdef WIN32
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
#endif
.perform_sync();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 主机名上传完成,结果: " << (res ? "成功" : "失败");
wcp_loger.add_log("主机名上传完成,结果: " + std::string((res ? "成功" : "失败")), false, "", "Moonraker_Mqtt", "info");
return res;
}
// Validate version text to confirm printer type
bool Moonraker::validate_version_text(const boost::optional<std::string>& version_text) const
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
bool result = version_text ? boost::starts_with(*version_text, "Moonraker") : true;
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 版本文本验证: " << (version_text ? *version_text : "")
<< ", 结果: " << (result ? "通过" : "失败");
wcp_loger.add_log("版本文本验证: " + (version_text ? *version_text : "") + ", 结果: " + (result ? "通过" : "失败"), false, "", "Moonraker_Mqtt", "info");
return result;
}
// Set authentication headers for HTTP requests
void Moonraker::set_auth(Http& http) const
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 设置认证头API密钥长度: " << m_apikey.length();
wcp_loger.add_log("设置认证头API密钥长度: " + std::to_string(m_apikey.length()), false, "", "Moonraker_Mqtt", "info");
http.header("X-Api-Key", m_apikey);
if (!m_cafile.empty()) {
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 设置CA文件: " << m_cafile;
wcp_loger.add_log("设置CA文件: " + m_cafile, false, "", "Moonraker_Mqtt", "info");
http.ca_file(m_cafile);
}
}
std::string Moonraker::make_url_8080(const std::string& path) const
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 构建8080端口URL路径: " << path;
wcp_loger.add_log("构建8080端口URL路径: " + path, false, "", "Moonraker_Mqtt", "info");
size_t pos = m_host.find(":");
std::string target_host = m_host;
if (pos != std::string::npos && pos != std::string("http:").length() - 1 && std::string("https:").length() - 1) {
target_host = target_host.substr(0, pos);
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 移除端口号,目标主机: " << target_host;
wcp_loger.add_log("移除端口号,目标主机: " + target_host, false, "", "Moonraker_Mqtt", "info");
}
std::string result;
if (target_host.find("http://") == 0 || target_host.find("https://") == 0) {
if (target_host.back() == '/') {
target_host = target_host.substr(0, target_host.length() - 1);
result = (boost::format("%1%:8080/%2%") % target_host % path).str();
} else {
result = (boost::format("%1%:8080/%2%") % target_host % path).str();
}
} else {
result = (boost::format("http://%1%:8080/%2%") % target_host % path).str();
}
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] 8080端口URL构建完成: " << result;
wcp_loger.add_log("8080端口URL构建完成: " + result, false, "", "Moonraker_Mqtt", "info");
return result;
}
// Construct full URL for API endpoint
std::string Moonraker::make_url(const std::string& path) const
{
if (m_host.find("http://") == 0 || m_host.find("https://") == 0) {
if (m_host.back() == '/') {
return (boost::format("%1%%2%") % m_host % path).str();
} else {
return (boost::format("%1%/%2%") % m_host % path).str();
}
} else {
if (m_host.find(":1884") != std::string::npos) {
std::string http_host = m_host.substr(0, m_host.find(":1884"));
return (boost::format("http://%1%/%2%") % http_host % path).str();
}
if (m_host.find(":8883") != std::string::npos) {
std::string http_host = m_host.substr(0, m_host.find(":8883"));
return (boost::format("http://%1%/%2%") % http_host % path).str();
}
return (boost::format("http://%1%/%2%") % m_host % path).str();
}
}
// Basic connect implementation
bool Moonraker::connect(wxString& msg, const nlohmann::json& params) {
return test(msg);
}
// Moonraker_mqtt
std::shared_ptr<MqttClient> Moonraker_Mqtt::m_mqtt_client = nullptr;
std::shared_ptr<MqttClient> Moonraker_Mqtt::m_mqtt_client_tls = nullptr;
TimeoutMap<int64_t, Moonraker_Mqtt::RequestCallback> Moonraker_Mqtt::m_request_cb_map;
std::string Moonraker_Mqtt::m_response_topic = "/response";
std::string Moonraker_Mqtt::m_status_topic = "/status";
std::string Moonraker_Mqtt::m_notification_topic = "/notification";
std::string Moonraker_Mqtt::m_request_topic = "/request";
std::string Moonraker_Mqtt::m_sn = "";
std::mutex Moonraker_Mqtt::m_sn_mtx;
std::string Moonraker_Mqtt::m_auth_topic = "/config/response";
std::string Moonraker_Mqtt::m_auth_req_topic = "/config/request";
nlohmann::json Moonraker_Mqtt::m_auth_info = nlohmann::json::object();
std::unordered_map<std::string, std::function<void(const nlohmann::json&)>> Moonraker_Mqtt::m_status_cbs;
std::unordered_map<std::string, std::function<void(const nlohmann::json&)>> Moonraker_Mqtt::m_notification_cbs;
Moonraker_Mqtt::Moonraker_Mqtt(DynamicPrintConfig* config, bool change_engine) : Moonraker(config) {
std::string host_info = config->option<ConfigOptionString>("print_host")->value;
auto& wcp_loger = GUI::WCP_Logger::getInstance();
if (change_engine) {
// 获取本地IP
std::string local_ip;
try {
#ifdef _WIN32
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
throw std::runtime_error("Failed to create socket");
}
#else
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
throw std::runtime_error("Failed to create socket");
}
#endif
// 连接到一个外部地址这里使用Google的DNS服务器
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(53);
inet_pton(AF_INET, "8.8.8.8", &addr.sin_addr);
if (::connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
#ifdef _WIN32
closesocket(sock);
#else
close(sock);
#endif
throw std::runtime_error("Failed to connect");
}
// 获取本地地址
struct sockaddr_in local_addr;
socklen_t len = sizeof(local_addr);
if (getsockname(sock, (struct sockaddr*)&local_addr, &len) < 0) {
#ifdef _WIN32
closesocket(sock);
#else
close(sock);
#endif
throw std::runtime_error("Failed to get local address");
}
// 转换为字符串
char ip_str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &local_addr.sin_addr, ip_str, INET_ADDRSTRLEN);
local_ip = ip_str;
#ifdef _WIN32
closesocket(sock);
#else
close(sock);
#endif
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Error getting local IP: " << e.what();
wcp_loger.add_log("获取本地IP失败: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
local_ip = "0.0.0.0"; // 失败时使用默认IP
}
m_mqtt_client.reset(new MqttClient("mqtt://" + host_info, local_ip, "", "", true));
m_mqtt_client_tls.reset();
BOOST_LOG_TRIVIAL(error) << "本地ip" << local_ip;
wcp_loger.add_log("本地ip: " + local_ip, false, "", "Moonraker_Mqtt", "error");
}
}
// set auth info
void Moonraker_Mqtt::set_auth_info(const nlohmann::json& info) {
m_auth_info = info;
}
nlohmann::json Moonraker_Mqtt::get_auth_info() {
json authinfo;
authinfo["user"] = m_user_name;
authinfo["password"] = m_password;
authinfo["ca"] = m_ca;
authinfo["cert"] = m_cert;
authinfo["key"] = m_key;
authinfo["clientId"] = m_client_id;
authinfo["port"] = m_port;
return authinfo;
}
bool Moonraker_Mqtt::set_engine(const std::shared_ptr<MqttClient>& engine, std::string& msg)
{
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 开始设置MQTT引擎 id: " << std::to_string(int64_t(engine.get()));
if (!engine) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 引擎指针为空,无法设置";
msg = "engine is null";
return false;
}
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 检查新引擎连接状态...";
if (!engine->CheckConnected()) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 新引擎连接检查失败";
msg = "engine connection failed";
return false;
}
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 新引擎连接状态正常";
if (m_mqtt_client_tls) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 检查旧引擎连接状态...";
if (m_mqtt_client_tls->CheckConnected()) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 旧引擎仍处于连接状态,开始断开...";
std::string dis_msg = "success";
bool disconnect_result = m_mqtt_client_tls->Disconnect(dis_msg);
if (disconnect_result) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 旧引擎断开成功: " << dis_msg;
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 旧引擎断开失败: " << dis_msg;
}
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 旧引擎已处于断开状态";
}
} else {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 没有旧的引擎需要断开";
}
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 设置新引擎指针";
m_mqtt_client_tls = engine;
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 设置消息回调函数";
m_mqtt_client_tls->SetMessageCallback([this](const std::string& topic, const std::string& payload) {
this->on_mqtt_tls_message_arrived(topic, payload);
});
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 引擎设置完成";
msg = "success";
return true;
}
// Ask for TLS info
bool Moonraker_Mqtt::ask_for_tls_info(const nlohmann::json& cn_params)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
if (!m_mqtt_client) {
return false;
}
if(m_mqtt_client->CheckConnected()) {
std::string dc_msg = "";
m_mqtt_client->Disconnect(dc_msg);
}
m_sn_mtx.lock();
m_sn = "";
m_sn_mtx.unlock();
std::string connection_msg = "";
bool is_connect = m_mqtt_client->Connect(connection_msg);
if(!is_connect || !cn_params.count("code") || cn_params["code"].get<std::string>() == "") {
return false;
}
std::string auth_code = cn_params["code"].get<std::string>();
std::string sub_msg = "success";
bool response_subscribed = m_mqtt_client->Subscribe(auth_code + m_auth_topic, 1, sub_msg);
if (!response_subscribed) {
return false;
}
m_mqtt_client->SetMessageCallback([this](const std::string& topic, const std::string& payload) {
this->on_mqtt_message_arrived(topic, payload);
});
json body;
body["jsonrpc"] = "2.0";
body["method"] = "server.request_key";
json params;
std::string clientid;
try {
clientid = m_mqtt_client->get_client_id();
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Error getting local IP: " << e.what();
wcp_loger.add_log("获取本地IP失败: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
clientid = "0.0.0.0"; // 失败时使用默认IP
}
if(clientid == "0.0.0.0") {
return false;
}
params["clientid"] = clientid;
body["params"] = params;
int64_t seq_id = m_seq_generator.generate_seq_id();
// 同步等待
std::promise<bool> auth_promise;
std::future<bool> auth_future = auth_promise.get_future();
auto callback = [this, &auth_promise](const nlohmann::json& res) {
try{
json result = res;
std::string state = result["state"].get<std::string>();
if (state != "success") {
auth_promise.set_value(false);
return;
}
// sn
m_sn_mtx.lock();
m_sn = result["sn"].get<std::string>();
m_sn_mtx.unlock();
m_client_id = result["clientid"].get<std::string>();
m_user_name = "";
m_password = "";
m_ca = result["ca"].get<std::string>();
m_cert = result["cert"].get<std::string>();
m_key = result["key"].get<std::string>();
m_port = result["port"].get<int>();
auth_promise.set_value(true);
}
catch(std::exception& e){
auth_promise.set_value(false);
}
};
auto timeout_callback = [this, &auth_promise]() {
// 待调整
auth_promise.set_value(false);
};
if (!add_response_target(seq_id, callback, timeout_callback, std::chrono::seconds(60))) {
return false;
}
body["id"] = seq_id;
std::string pub_msg = "";
if(!m_mqtt_client->Publish(auth_code + m_auth_req_topic, body.dump(), 1, pub_msg)){
return false;
}
// 等待response
auto status = auth_future.wait_for(std::chrono::seconds(70));
if(status == std::future_status::timeout){
return false;
}
return auth_future.get();
}
// Connect to MQTT broker
bool Moonraker_Mqtt::connect(wxString& msg, const nlohmann::json& params) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始MQTT连接流程";
wcp_loger.add_log("开始MQTT连接流程", false, "", "Moonraker_Mqtt", "info");
// 在创建新连接前检查参数
if(!params.count("ca") || !params.count("cert")
|| !params.count("key") || !params.count("port") || !params.count("clientId") || !params.count("sn")){
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 缺少TLS参数尝试获取认证信息";
wcp_loger.add_log("缺少TLS参数尝试获取认证信息", false, "", "Moonraker_Mqtt", "info");
bool flag = ask_for_tls_info(params);
if (!flag) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 获取TLS认证信息失败";
wcp_loger.add_log("获取TLS认证信息失败", false, "", "Moonraker_Mqtt", "error");
return false;
}
}else{
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 使用提供的TLS参数";
wcp_loger.add_log("使用提供的TLS参数", false, "", "Moonraker_Mqtt", "info");
m_user_name = params.count("user") ? params["user"].get<std::string>() : "";
m_password = params.count("password") ? params["password"].get<std::string>() : "";
m_ca = params["ca"].get<std::string>();
m_cert = params["cert"].get<std::string>();
m_key = params["key"].get<std::string>();
m_port = params["port"].get<int>();
m_client_id = params["clientId"].get<std::string>();
m_sn_mtx.lock();
m_sn = params["sn"].get<std::string>();
m_sn_mtx.unlock();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 设置SN: " << m_sn;
wcp_loger.add_log("设置SN: " + m_sn, false, "", "Moonraker_Mqtt", "info");
if (m_ca == "" || m_cert == "" || m_key == "") {
bool flag = ask_for_tls_info(params);
if (!flag) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 获取TLS认证信息失败";
wcp_loger.add_log("获取TLS认证信息失败", false, "", "Moonraker_Mqtt", "error");
return false;
}
}
}
// 验证证书格式
if (!m_ca.empty()) {
if (m_ca.find("-----BEGIN CERTIFICATE-----") == std::string::npos) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] CA证书格式不正确";
wcp_loger.add_log("CA证书格式不正确", false, "", "Moonraker_Mqtt", "error");
return false;
}
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] CA证书格式验证通过";
wcp_loger.add_log("CA证书格式验证通过", false, "", "Moonraker_Mqtt", "info");
}
if (!m_cert.empty()) {
if (m_cert.find("-----BEGIN CERTIFICATE-----") == std::string::npos) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 客户端证书格式不正确";
wcp_loger.add_log("客户端证书格式不正确", false, "", "Moonraker_Mqtt", "error");
return false;
}
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 客户端证书格式验证通过";
wcp_loger.add_log("客户端证书格式验证通过", false, "", "Moonraker_Mqtt", "info");
}
if (!m_key.empty()) {
if (m_key.find("-----BEGIN PRIVATE KEY-----") == std::string::npos
&& m_key.find("-----BEGIN RSA PRIVATE KEY-----") == std::string::npos) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 私钥格式不正确";
wcp_loger.add_log("私钥格式不正确", false, "", "Moonraker_Mqtt", "error");
return false;
}
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 私钥格式验证通过";
wcp_loger.add_log("私钥格式验证通过", false, "", "Moonraker_Mqtt", "info");
}
// 检查端口号
if (m_port <= 0 || m_port > 65535) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 无效的端口号: " << m_port;
wcp_loger.add_log("无效的端口号: " + std::to_string(m_port), false, "", "Moonraker_Mqtt", "error");
return false;
}
// 记录连接参数(不记录敏感信息的具体内容)
BOOST_LOG_TRIVIAL(debug) << "[Moonraker_Mqtt] MQTTS连接参数:"
<< "\n - 主机: " << m_host
<< "\n - 端口: " << m_port
<< "\n - 客户端ID: " << m_client_id
<< "\n - CA证书是否存在: " << (!m_ca.empty() ? "" : "")
<< "\n - 客户端证书是否存在: " << (!m_cert.empty() ? "" : "")
<< "\n - 私钥是否存在: " << (!m_key.empty() ? "" : "");
wcp_loger.add_log("MQTTS连接参数: " + m_host + ":" + std::to_string(m_port) + ", 客户端ID: " + m_client_id + ", CA证书是否存在: " + (!m_ca.empty() ? "" : "") + ", 客户端证书是否存在: " + (!m_cert.empty() ? "" : "") + ", 私钥是否存在: " + (!m_key.empty() ? "" : ""), false, "", "Moonraker_Mqtt", "info");
// 在创建新连接前,确保旧连接已断开
if (m_mqtt_client) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 断开旧的MQTT客户端连接";
wcp_loger.add_log("断开旧的MQTT客户端连接", false, "", "Moonraker_Mqtt", "info");
std::string dc_msg = "success";
m_mqtt_client->Disconnect(dc_msg);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_mqtt_client.reset();
}
if (m_mqtt_client_tls) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 断开旧的MQTTS客户端连接";
wcp_loger.add_log("断开旧的MQTTS客户端连接", false, "", "Moonraker_Mqtt", "info");
std::string dc_msg = "success";
m_mqtt_client_tls->Disconnect(dc_msg);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_mqtt_client_tls.reset();
}
// 创建新的 MQTTS 连接
std::string host_ip = m_host;
size_t pos = host_ip.find(":");
if (pos != std::string::npos) {
host_ip = host_ip.substr(0, pos);
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 提取主机IP: " << host_ip;
wcp_loger.add_log("提取主机IP: " + host_ip, false, "", "Moonraker_Mqtt", "info");
}
std::string mqtts_url = "mqtts://" + host_ip + ":" + std::to_string(m_port);
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 创建MQTTS客户端URL: " << mqtts_url << ", 客户端ID: " << m_client_id;
wcp_loger.add_log("创建MQTTS客户端URL: " + mqtts_url + ", 客户端ID: " + m_client_id, false, "", "Moonraker_Mqtt", "info");
m_mqtt_client_tls.reset(new MqttClient(mqtts_url, m_client_id, m_ca, m_cert, m_key));
if (!m_mqtt_client_tls) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] MQTT客户端创建失败";
wcp_loger.add_log("MQTT客户端创建失败", false, "", "Moonraker_Mqtt", "error");
return false;
}
std::string connection_msg = "";
bool is_connect = m_mqtt_client_tls->Connect(connection_msg);
msg = connection_msg;
if (!is_connect) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] MQTT连接失败";
wcp_loger.add_log("MQTT连接失败", false, "", "Moonraker_Mqtt", "error");
return false;
}
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] MQTTS连接成功";
wcp_loger.add_log("MQTTS连接成功", false, "", "Moonraker_Mqtt", "info");
m_sn_mtx.lock();
std::string tmp_sn = m_sn;
m_sn_mtx.unlock();
if(tmp_sn == ""){
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] SN为空无法订阅主题";
wcp_loger.add_log("SN为空无法订阅主题", false, "", "Moonraker_Mqtt", "error");
return false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::string no_sub_msg = "success";
bool notification_subscribed = m_mqtt_client_tls->Subscribe(tmp_sn + m_notification_topic, 1, no_sub_msg);
std::string res_sub_msg = "success";
bool response_subscribed = m_mqtt_client_tls->Subscribe(tmp_sn + m_response_topic, 1, res_sub_msg);
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 订阅主题结果 - 通知主题: " << (notification_subscribed ? "成功" : "失败")
<< ", 响应主题: " << (response_subscribed ? "成功" : "失败");
wcp_loger.add_log("订阅主题结果 - 通知主题: " + std::string((notification_subscribed ? "成功" : "失败")) + ", 响应主题: " + (response_subscribed ? "成功" : "失败"), false, "", "Moonraker_Mqtt", "info");
m_mqtt_client_tls->SetMessageCallback([this](const std::string& topic, const std::string& payload) {
this->on_mqtt_tls_message_arrived(topic, payload);
});
bool result = is_connect && notification_subscribed && response_subscribed;
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] MQTT连接流程完成结果: " << (result ? "成功" : "失败");
wcp_loger.add_log("MQTT连接流程完成结果: " + std::string((result ? "成功" : "失败")), false, "", "Moonraker_Mqtt", "info");
return result;
}
// Disconnect from MQTT broker
bool Moonraker_Mqtt::disconnect(wxString& msg, const nlohmann::json& params) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始断开MQTT连接";
wcp_loger.add_log("开始断开MQTT连接", false, "", "Moonraker_Mqtt", "info");
if (!m_mqtt_client_tls) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] MQTTS客户端不存在无需断开";
wcp_loger.add_log("MQTTS客户端不存在无需断开", false, "", "Moonraker_Mqtt", "info");
return false;
}
std::string dc_msg = "success";
bool flag = m_mqtt_client_tls->Disconnect(dc_msg);
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] MQTTS断开连接结果: " << (flag ? "成功" : "失败");
wcp_loger.add_log("MQTTS断开连接结果: " + std::string((flag ? "成功" : "失败")), false, "", "Moonraker_Mqtt", "info");
if (flag) {
m_status_cbs.clear();
m_notification_cbs.clear();
}
m_sn_mtx.lock();
m_sn = "";
m_sn_mtx.unlock();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 重置SN";
wcp_loger.add_log("重置SN", false, "", "Moonraker_Mqtt", "info");
// 等待一段时间让MQTT客户端完成清理避免内存访问问题
std::this_thread::sleep_for(std::chrono::milliseconds(100));
m_mqtt_client_tls.reset();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] MQTTS客户端已重置";
wcp_loger.add_log("MQTTS客户端已重置", false, "", "Moonraker_Mqtt", "info");
return flag;
}
// Subscribe to printer status updates
void Moonraker_Mqtt::async_subscribe_machine_info(const std::string& hash, std::function<void(const nlohmann::json&)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始订阅机器状态信息";
wcp_loger.add_log("开始订阅机器状态信息", false, "", "Moonraker_Mqtt", "info");
if (m_status_cbs.empty()) {
std::string main_layer = "+";
m_sn_mtx.lock();
main_layer = m_sn;
m_sn_mtx.unlock();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 使用SN主题: " << main_layer;
wcp_loger.add_log("使用SN主题: " + main_layer, false, "", "Moonraker_Mqtt", "info");
std::string sub_msg = "success";
bool res_status = m_mqtt_client_tls ? m_mqtt_client_tls->Subscribe(main_layer + m_status_topic, 1, sub_msg) : false;
bool res_notification = m_mqtt_client_tls ? m_mqtt_client_tls->Subscribe(main_layer + m_notification_topic, 1, sub_msg) : false;
if (!res_status || !res_notification) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 订阅状态主题失败";
wcp_loger.add_log("订阅状态主题失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
return;
}
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 成功订阅状态主题: " << main_layer + m_status_topic;
wcp_loger.add_log("成功订阅状态主题: " + main_layer + m_status_topic, false, "", "Moonraker_Mqtt", "info");
}
m_status_cbs.insert({hash, callback});
m_notification_cbs.insert({hash, callback});
callback(json::object());
}
// start print job
void Moonraker_Mqtt::async_start_print_job(const std::string& filename, std::function<void(const nlohmann::json&)> cb)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始启动打印任务,文件名: " << filename;
wcp_loger.add_log("开始启动打印任务,文件名: " + filename, false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.print.start";
json params = json::object();
params["filename"] = filename;
if (!send_to_request(method, params, true, cb,
[cb, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 启动打印任务超时";
wcp_loger.add_log("启动打印任务超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
cb(res);
}) &&
cb) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送启动打印请求失败";
wcp_loger.add_log("发送启动打印请求失败", false, "", "Moonraker_Mqtt", "error");
cb(json::value_t::null);
}
}
void Moonraker_Mqtt::async_pause_print_job(std::function<void(const nlohmann::json&)> cb) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始暂停打印任务";
wcp_loger.add_log("开始暂停打印任务", false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.print.pause";
json params = json::object();
if (!send_to_request(method, params, true, cb,
[cb, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 暂停打印任务超时";
wcp_loger.add_log("暂停打印任务超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
cb(res);
}) &&
cb) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送暂停打印请求失败";
wcp_loger.add_log("发送暂停打印请求失败", false, "", "Moonraker_Mqtt", "error");
cb(json::value_t::null);
}
}
void Moonraker_Mqtt::async_resume_print_job(std::function<void(const nlohmann::json&)> cb) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始恢复打印任务";
wcp_loger.add_log("开始恢复打印任务", false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.print.resume";
json params = json::object();
if (!send_to_request(method, params, true, cb,
[cb, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 恢复打印任务超时";
wcp_loger.add_log("恢复打印任务超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
cb(res);
}) &&
cb) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送恢复打印请求失败";
wcp_loger.add_log("发送恢复打印请求失败", false, "", "Moonraker_Mqtt", "error");
cb(json::value_t::null);
}
}
void Moonraker_Mqtt::test_async_wcp_mqtt_moonraker(const nlohmann::json& mqtt_request_params, std::function<void(const nlohmann::json&)> cb) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始测试MQTT Moonraker异步请求";
wcp_loger.add_log("开始测试MQTT Moonraker异步请求", false, "", "Moonraker_Mqtt", "info");
int64_t id = -1;
if (!mqtt_request_params.count("id") || !mqtt_request_params[id].is_number()) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 测试请求缺少有效ID";
wcp_loger.add_log("测试请求缺少有效ID", false, "", "Moonraker_Mqtt", "error");
cb(json::value_t::null);
return;
}
id = mqtt_request_params["id"].get<int64_t>();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 测试请求ID: " << id;
wcp_loger.add_log("测试请求ID: " + std::to_string(id), false, "", "Moonraker_Mqtt", "info");
if (id == -1) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 无效的请求ID";
wcp_loger.add_log("无效的请求ID", false, "", "Moonraker_Mqtt", "error");
cb(json::value_t::null);
return;
}
if (!add_response_target(id, cb, [cb, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 测试请求超时";
wcp_loger.add_log("测试请求超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
cb(res);
})){
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 添加响应目标失败";
wcp_loger.add_log("添加响应目标失败", false, "", "Moonraker_Mqtt", "error");
cb(json::value_t::null);
}
if (m_mqtt_client_tls) {
std::string main_layer = "+";
if (wait_for_sn()) {
m_sn_mtx.lock();
main_layer = m_sn;
m_sn_mtx.unlock();
if (main_layer == "+" || main_layer == "") {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] SN无效删除响应目标";
wcp_loger.add_log("SN无效删除响应目标", false, "", "Moonraker_Mqtt", "error");
delete_response_target(id);
cb(json::value_t::null);
return;
}
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 发布测试请求到主题: " << main_layer + m_request_topic;
wcp_loger.add_log("发布测试请求到主题: " + main_layer + m_request_topic, false, "", "Moonraker_Mqtt", "info");
std::string pub_msg = "success";
bool res = m_mqtt_client_tls->Publish(main_layer + m_request_topic, mqtt_request_params.dump(), 1, pub_msg);
if (!res) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发布测试请求失败";
wcp_loger.add_log("发布测试请求失败", false, "", "Moonraker_Mqtt", "error");
delete_response_target(id);
} else {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 测试请求发布成功";
wcp_loger.add_log("测试请求发布成功", false, "", "Moonraker_Mqtt", "info");
}
return;
}
}
}
void Moonraker_Mqtt::async_cancel_print_job(std::function<void(const nlohmann::json&)> cb)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始取消打印任务";
wcp_loger.add_log("开始取消打印任务", false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.print.cancel";
json params = json::object();
if (!send_to_request(method, params, true, cb,
[cb, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 取消打印任务超时";
wcp_loger.add_log("取消打印任务超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
cb(res);
}) &&
cb) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送取消打印请求失败";
wcp_loger.add_log("发送取消打印请求失败", false, "", "Moonraker_Mqtt", "error");
cb(json::value_t::null);
}
}
// Get printer info
void Moonraker_Mqtt::async_get_printer_info(std::function<void(const nlohmann::json& response)> callback) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取打印机信息";
wcp_loger.add_log("开始获取打印机信息", false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.info";
json params = json::object();
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 获取打印机信息超时";
wcp_loger.add_log("获取打印机信息超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送获取打印机信息请求失败";
wcp_loger.add_log("发送获取打印机信息请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// Send G-code commands to printer
void Moonraker_Mqtt::async_send_gcodes(const std::vector<std::string>& scripts, std::function<void(const nlohmann::json&)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始发送G代码数量: " << scripts.size();
wcp_loger.add_log("开始发送G代码数量: " + std::to_string(scripts.size()), false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.gcode.script";
std::string str_scripts = "";
for (size_t i = 0; i < scripts.size(); ++i) {
if (i != 0) {
str_scripts += "\n";
}
str_scripts += scripts[i];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 添加G代码: " << scripts[i];
wcp_loger.add_log("添加G代码: " + scripts[i], false, "", "Moonraker_Mqtt", "info");
}
json params;
params["script"] = str_scripts;
if (!send_to_request(method, params, true, callback, [callback, &wcp_loger](){
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 发送G代码超时";
wcp_loger.add_log("发送G代码超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) && callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送G代码请求失败";
wcp_loger.add_log("发送G代码请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// Unsubscribe from printer status updates
void Moonraker_Mqtt::async_unsubscribe_machine_info(const std::string& hash, std::function<void(const nlohmann::json&)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始取消订阅机器状态信息";
wcp_loger.add_log("开始取消订阅机器状态信息", false, "", "Moonraker_Mqtt", "info");
if (m_status_cbs.count(hash))
m_status_cbs.erase(hash);
if (m_notification_cbs.count(hash))
m_notification_cbs.erase(hash);
if (m_status_cbs.empty()) {
std::string main_layer = "+";
m_sn_mtx.lock();
main_layer = m_sn;
m_sn_mtx.unlock();
std::string un_sub_msg = "success";
bool res = m_mqtt_client_tls ? m_mqtt_client_tls->Unsubscribe(main_layer + m_status_topic, un_sub_msg) : false;
if (!res) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 取消订阅状态主题失败";
wcp_loger.add_log("取消订阅状态主题失败", false, "", "Moonraker_Mqtt", "error");
if (callback) {
callback(json::value_t::null);
}
return;
}
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 成功取消订阅状态主题: " << main_layer + m_status_topic;
wcp_loger.add_log("成功取消订阅状态主题: " + main_layer + m_status_topic, false, "", "Moonraker_Mqtt", "info");
callback(json::object());
} else {
callback(json::object());
}
}
// Set filters for printer status subscription
void Moonraker_Mqtt::async_set_machine_subscribe_filter(
const std::vector<std::pair<std::string, std::vector<std::string>>>& targets,
std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始设置机器订阅过滤器,目标数量: " << targets.size();
wcp_loger.add_log("开始设置机器订阅过滤器,目标数量: " + std::to_string(targets.size()), false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.objects.subscribe";
json params;
params["objects"] = json::object();
for (size_t i = 0; i < targets.size(); ++i) {
if (targets[i].second.size() == 0) {
params["objects"][targets[i].first] = json::value_t::null;
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 添加过滤器(全部): " << targets[i].first;
wcp_loger.add_log("添加过滤器(全部): " + targets[i].first, false, "", "Moonraker_Mqtt", "info");
} else {
params["objects"][targets[i].first] = json::array();
for (const auto& key : targets[i].second) {
params["objects"][targets[i].first].push_back(key);
}
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 添加过滤器: " << targets[i].first
<< ", 字段数量: " << targets[i].second.size();
wcp_loger.add_log("添加过滤器: " + targets[i].first + ", 字段数量: " + std::to_string(targets[i].second.size()), false, "", "Moonraker_Mqtt", "info");
}
}
if (!send_to_request(method, params, true, callback, [callback, &wcp_loger](){
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 设置订阅过滤器超时";
wcp_loger.add_log("设置订阅过滤器超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) && callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送设置订阅过滤器请求失败";
wcp_loger.add_log("发送设置订阅过滤器请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_machine_files_roots(std::function<void(const nlohmann::json& response)> callback) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取文件系统根目录";
wcp_loger.add_log("开始获取文件系统根目录", false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.roots";
json params = json::object();
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 获取文件系统根目录超时";
wcp_loger.add_log("获取文件系统根目录超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送获取文件系统根目录请求失败";
wcp_loger.add_log("发送获取文件系统根目录请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_machine_files_metadata(const std::string& filename, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取文件元数据,文件名: " << filename;
wcp_loger.add_log("开始获取文件元数据,文件名: " + filename, false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.metadata";
json params;
params["filename"] = filename;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 获取文件元数据超时";
wcp_loger.add_log("获取文件元数据超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送获取文件元数据请求失败";
wcp_loger.add_log("发送获取文件元数据请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_set_device_name(const std::string& device_name, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始设置设备名称,名称: " << device_name;
wcp_loger.add_log("开始设置设备名称,名称: " + device_name, false, "", "Moonraker_Mqtt", "info");
std::string method = "machine.set_device_name";
json params;
params["name"] = device_name;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 设置设备名称超时";
wcp_loger.add_log("设置设备名称超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送设置设备名称请求失败";
wcp_loger.add_log("发送设置设备名称请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_control_led(const std::string& name, int white, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始控制LED名称: " << name << ", 白色亮度: " << white;
wcp_loger.add_log("开始控制LED名称: " + name + ", 白色亮度: " + std::to_string(white), false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.control.led";
json params;
params["name"] = name;
params["white"] = white;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 控制LED超时";
wcp_loger.add_log("控制LED超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送控制LED请求失败";
wcp_loger.add_log("发送控制LED请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_control_print_speed(int percentage, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始控制打印速度,百分比: " << percentage;
wcp_loger.add_log("开始控制打印速度,百分比: " + std::to_string(percentage), false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.control.print_speed";
json params;
params["percentage"] = percentage;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 控制打印速度超时";
wcp_loger.add_log("控制打印速度超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送控制打印速度请求失败";
wcp_loger.add_log("发送控制打印速度请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_bedmesh_abort_probe_mesh(std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始中止热床调平";
wcp_loger.add_log("开始中止热床调平 ", false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.bed_mesh.abort_probe_mesh";
json params = json::object();
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 中止热床调平";
wcp_loger.add_log("中止热床调平", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送中止热床调平请求失败";
wcp_loger.add_log("发送中止热床调平请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_controlPurifier(int fan_speed,
int delay_time,
int work_time,
std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始控制空气净化器,风速: " << fan_speed << ", 延时: " << delay_time
<< ", 工作时间: " << work_time;
wcp_loger.add_log("开始控制空气净化器,风速: " + std::to_string(fan_speed) + ", 延时: " + std::to_string(delay_time) +
", 工作时间: " + std::to_string(work_time),
false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.control.purifier";
json params;
if (fan_speed != -1)
params["fan_speed"] = fan_speed;
if (delay_time != -1)
params["delay_time"] = delay_time;
if (work_time != -1)
params["work_time"] = work_time;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 控制空气净化器超时";
wcp_loger.add_log("控制空气净化器超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送控制空气净化器请求失败";
wcp_loger.add_log("发送控制空气净化器请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_control_main_fan(int speed, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始控制主风扇,速度: " << speed;
wcp_loger.add_log("开始控制主风扇,速度: " + std::to_string(speed), false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.control.main_fan";
json params;
params["speed"] = speed;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 控制主风扇超时";
wcp_loger.add_log("控制主风扇超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送控制主风扇请求失败";
wcp_loger.add_log("发送控制主风扇请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_control_generic_fan(const std::string& name,
int speed,
std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始控制通用风扇,名称: " << name << ", 速度: " << speed;
wcp_loger.add_log("开始控制通用风扇,名称: " + name + ", 速度: " + std::to_string(speed), false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.control.generic_fan";
json params;
params["name"] = name;
params["speed"] = speed;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 控制通用风扇超时";
wcp_loger.add_log("控制通用风扇超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送控制通用风扇请求失败";
wcp_loger.add_log("发送控制通用风扇请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_control_bed_temp(int temp, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始控制热床温度,目标温度: " << temp;
wcp_loger.add_log("开始控制热床温度,目标温度: " + std::to_string(temp), false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.control.bed_temp";
json params;
params["temp"] = temp;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 控制热床温度超时";
wcp_loger.add_log("控制热床温度超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送控制热床温度请求失败";
wcp_loger.add_log("发送控制热床温度请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_control_extruder_temp(int temp, int index, int map, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始控制挤出机温度,目标温度: " << temp << ", 挤出机索引: " << index;
wcp_loger.add_log("开始控制挤出机温度,目标温度: " + std::to_string(temp) + ", 挤出机索引: " + std::to_string(index), false, "",
"Moonraker_Mqtt", "info");
std::string method = "printer.control.extruder_temp";
json params;
params["temp"] = temp;
if (index != -1)
params["index"] = index;
if (map != -1)
params["map"] = map;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 控制挤出机温度超时";
wcp_loger.add_log("控制挤出机温度超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送控制挤出机温度请求失败";
wcp_loger.add_log("发送控制挤出机温度请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_files_thumbnails_base64(const std::string& path, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取文件缩略图,路径: " << path;
wcp_loger.add_log("开始获取文件缩略图,路径: " + path, false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.thumbnails_base64";
json params;
params["path"] = path;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 获取文件缩略图超时";
wcp_loger.add_log("获取文件缩略图超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送获取文件缩略图请求失败";
wcp_loger.add_log("发送获取文件缩略图请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_get_file_page_list(const std::string& root, int files_per_page, int page_number, std::function<void(const nlohmann::json& response)> callback){
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始按页获取文件";
wcp_loger.add_log("开始按页获取文件", false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.list_page";
json params;
params["root"] = root;
params["files_per_page"] = files_per_page;
params["page_number"] = page_number;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 按页获取文件超时";
wcp_loger.add_log("按页获取文件超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 按页获取文件失败";
wcp_loger.add_log("按页获取文件失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_exception_query(std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始查询异常状态";
wcp_loger.add_log("开始查询异常状态", false, "", "Moonraker_Mqtt", "info");
std::string method = "server.exception.query";
json params;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 查询异常状态超时";
wcp_loger.add_log("查询异常状态超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 查询异常状态失败";
wcp_loger.add_log("查询异常状态失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_server_client_manager_set_userinfo(const nlohmann::json& user, std::function<void(const nlohmann::json& response)> callback) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始设置已绑定用户信息";
wcp_loger.add_log("开始设置已绑定用户信息", false, "", "Moonraker_Mqtt", "info");
std::string method = "server.client_manager.set_userinfo";
if (!user.count("auther") || !user["auther"].count("id") || !user["auther"].count("nickname")) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 设置已绑定用户信息失败id或nickname不存在";
wcp_loger.add_log("设置已绑定用户信息失败id或nickname不存在", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
return;
}
json params = user;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 设置已绑定用户信息超时";
wcp_loger.add_log("设置已绑定用户信息超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送设置已绑定用户信息请求失败";
wcp_loger.add_log("发送设置已绑定用户信息请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_machine_files_thumbnails(const std::string& filename, std::function<void(const nlohmann::json& response)> callback) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取文件缩略图,文件名: " << filename;
wcp_loger.add_log("开始获取文件缩略图,文件名: " + filename, false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.thumbnails";
json params;
params["filename"] = filename;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 获取文件缩略图超时";
wcp_loger.add_log("获取文件缩略图超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送获取文件缩略图请求失败";
wcp_loger.add_log("发送获取文件缩略图请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_machine_files_directory(const std::string& path, bool extend, std::function<void(const nlohmann::json& response)> callback) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取目录内容,路径: " << path << ", 扩展信息: " << extend;
wcp_loger.add_log("开始获取目录内容,路径: " + path + ", 扩展信息: " + std::to_string(extend), false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.get_directory";
json params;
params["path"] = path;
params["extended"] = extend;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 获取目录内容超时";
wcp_loger.add_log("获取目录内容超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送获取目录内容请求失败";
wcp_loger.add_log("发送获取目录内容请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_camera_start(const std::string& domain, int interval, bool expect_pw, std::function<void(const nlohmann::json& response)> callback) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始启动摄像头监控,域名: " << domain;
wcp_loger.add_log("开始启动摄像头监控,域名: " + domain, false, "", "Moonraker_Mqtt", "info");
std::string method = "camera.start_monitor";
json params;
params["domain"] = domain;
params["interval"] = interval;
params["expect_pw"] = expect_pw;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 启动摄像头监控超时";
wcp_loger.add_log("启动摄像头监控超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送启动摄像头监控请求失败";
wcp_loger.add_log("发送启动摄像头监控请求失败", false, "", "Moonraker_Mqtt", "error");
sentryReportLog(SENTRY_LOG_TRACE, "bury_point_open video cmd error", BP_VIDEO_ABNORMAL);
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_delete_machine_file(const std::string& path, std::function<void(const nlohmann::json& response)> callback) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始删除文件,路径: " << path;
wcp_loger.add_log("开始删除文件,路径: " + path, false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.delete_file";
json params;
params["path"] = path;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 删除文件超时";
wcp_loger.add_log("删除文件超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送删除文件请求失败";
wcp_loger.add_log("发送删除文件请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_canmera_stop(const std::string& domain, std::function<void(const nlohmann::json& response)> callback) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始停止摄像头监控,域名: " << domain;
wcp_loger.add_log("开始停止摄像头监控,域名: " + domain, false, "", "Moonraker_Mqtt", "info");
std::string method = "camera.stop_monitor";
json params;
params["domain"] = domain;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 停止摄像头监控超时";
wcp_loger.add_log("停止摄像头监控超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送停止摄像头监控请求失败";
wcp_loger.add_log("发送停止摄像头监控请求失败", false, "", "Moonraker_Mqtt", "error");
sentryReportLog(SENTRY_LOG_TRACE, "bury_point_stop video cmd error", BP_VIDEO_ABNORMAL);
callback(json::value_t::null);
}
}
// 请求上传延时摄影文件
void Moonraker_Mqtt::async_upload_camera_timelapse(const nlohmann::json& targets,
std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始请求上传延时摄影文件";
wcp_loger.add_log("开始请求上传延时摄影文件", false, "", "Moonraker_Mqtt", "info");
std::string method = "camera.upload_timelapse_instance";
json params = json::object();
params = targets;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 请求上传延时摄影文件超时";
wcp_loger.add_log("请求上传延时摄影文件超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送请求上传延时摄影文件失败";
wcp_loger.add_log("发送请求上传延时摄影文件失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// 获取延时摄影列表
void Moonraker_Mqtt::async_get_timelapse_instance(const nlohmann::json& targets, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始请求获取延时摄影文件列表";
wcp_loger.add_log("开始请求获取延时摄影文件列表", false, "", "Moonraker_Mqtt", "info");
std::string method = "camera.get_timelapse_instance";
json params = json::object();
params = targets;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 请求获取延时摄影文件列表超时";
wcp_loger.add_log("请求获取延时摄影文件列表超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送请求获取延时摄影文件列表失败";
wcp_loger.add_log("发送请求获取延时摄影文件列表失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// 请求删除延时摄影文件
void Moonraker_Mqtt::async_delete_camera_timelapse(const nlohmann::json& targets,
std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始请求删除延时摄影文件";
wcp_loger.add_log("开始请求删除延时摄影文件", false, "", "Moonraker_Mqtt", "info");
std::string method = "camera.delete_timelapse_instance";
json params = json::object();
params = targets;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 请求删除延时摄影文件超时";
wcp_loger.add_log("请求删除延时摄影文件超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送请求删除延时摄影文件失败";
wcp_loger.add_log("发送请求删除延时摄影文件失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// 请求缺陷检测配置
void Moonraker_Mqtt::async_defect_detaction_config(const nlohmann::json& targets, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始请求缺陷检测配置";
wcp_loger.add_log("开始请求缺陷检测配置", false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.defect_detection.config";
json params = json::object();
params = targets;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 请求缺陷检测配置超时";
wcp_loger.add_log("请求缺陷检测配置超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送请求缺陷检测配置失败";
wcp_loger.add_log("发送请求缺陷检测配置失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// 请求设备下载云文件并打印
void Moonraker_Mqtt::async_start_cloud_print(const nlohmann::json& targets,
std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始请求设备开始云打印";
wcp_loger.add_log("开始请求设备云打印", false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.start_cloud_print";
json params = json::object();
params = targets;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 请求设备云打印超时";
wcp_loger.add_log("请求设备云打印超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送请求设备开启云打印失败";
wcp_loger.add_log("发送请求设备开启云打印失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// 请求设备开启云打印
void Moonraker_Mqtt::async_pull_cloud_file(const nlohmann::json& targets, std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始请求设备下载云文件";
wcp_loger.add_log("开始请求设备下载云文件", false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.pull";
json params = json::object();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 添加云文件下载目标, 属性数量: " << targets.size();
wcp_loger.add_log("添加云文件下载目标, 属性数量: " + std::to_string(targets.size()), false, "", "Moonraker_Mqtt", "info");
params = targets;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 请求设备下载文件超时";
wcp_loger.add_log("请求设备下载文件超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送请求设备下载文件超时请求失败";
wcp_loger.add_log("发送请求设备下载文件超时请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
void Moonraker_Mqtt::async_cancel_pull_cloud_file(std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 请求设备取消上传";
wcp_loger.add_log("请求设备取消上传", false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.cancel_pull";
json params = json::object();
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 请求设备取消上传超时";
wcp_loger.add_log("请求设备取消上传超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送设备取消上传请求失败";
wcp_loger.add_log("发送设备取消上传请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// Query device information (firmware version)
// Query printer information
void Moonraker_Mqtt::async_get_device_info(std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始查询固件信息";
wcp_loger.add_log("开始查询固件信息", false, "", "Moonraker_Mqtt", "info");
std::string method = "system.get_device_info";
json params;
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 查询固件信息超时";
wcp_loger.add_log("查询固件信息超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送查询固件信息请求失败";
wcp_loger.add_log("发送查询固件信息请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// Query printer information
void Moonraker_Mqtt::async_get_machine_info(
const std::vector<std::pair<std::string, std::vector<std::string>>>& targets,
std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始查询打印机信息,目标数量: " << targets.size();
wcp_loger.add_log("开始查询打印机信息,目标数量: " + std::to_string(targets.size()), false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.objects.query";
json params;
params["objects"] = json::object();
for (size_t i = 0; i < targets.size(); ++i) {
if (targets[i].second.size() == 0) {
params["objects"][targets[i].first] = json::value_t::null;
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 查询对象(全部属性): " << targets[i].first;
wcp_loger.add_log("查询对象(全部属性): " + targets[i].first, false, "", "Moonraker_Mqtt", "info");
} else {
params["objects"][targets[i].first] = json::array();
for (const auto& key : targets[i].second) {
params["objects"][targets[i].first].push_back(key);
}
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 查询对象: " << targets[i].first
<< ", 属性数量: " << targets[i].second.size();
wcp_loger.add_log("查询对象: " + targets[i].first + ", 属性数量: " + std::to_string(targets[i].second.size()), false, "", "Moonraker_Mqtt", "info");
}
}
if (!send_to_request(method, params, true, callback, [callback, &wcp_loger](){
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 查询打印机信息超时";
wcp_loger.add_log("查询打印机信息超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) && callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送查询打印机信息请求失败";
wcp_loger.add_log("发送查询打印机信息请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// Get File state
void Moonraker_Mqtt::async_server_files_get_status(std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取系统文件状态";
wcp_loger.add_log("开始获取系统文件状态信息", false, "", "Moonraker_Mqtt", "info");
std::string method = "server.files.get_status";
json params = json::object();
if (!send_to_request(method, params, true, callback,
[callback, &wcp_loger]() {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 获取系统文件状态超时";
wcp_loger.add_log("获取系统文件状态超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) &&
callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送获取系统文件状态请求失败";
wcp_loger.add_log("发送获取系统文件状态请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// Get system info of the machine
void Moonraker_Mqtt::async_get_system_info(std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取系统信息";
wcp_loger.add_log("开始获取系统信息", false, "", "Moonraker_Mqtt", "info");
std::string method = "machine.system_info";
json params = json::object();
if (!send_to_request(method, params, true, callback, [callback, &wcp_loger](){
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 获取系统信息超时";
wcp_loger.add_log("获取系统信息超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) && callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送获取系统信息请求失败";
wcp_loger.add_log("发送获取系统信息请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// Get list of available printer objects
void Moonraker_Mqtt::async_get_machine_objects(std::function<void(const nlohmann::json& response)> callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 开始获取可用打印机对象列表";
wcp_loger.add_log("开始获取可用打印机对象列表", false, "", "Moonraker_Mqtt", "info");
std::string method = "printer.objects.list";
json params = json::object();
if (!send_to_request(method, params, true, callback, [callback, &wcp_loger](){
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 获取打印机对象列表超时";
wcp_loger.add_log("获取打印机对象列表超时", false, "", "Moonraker_Mqtt", "warning");
json res;
res["error"] = "timeout";
callback(res);
}) && callback) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发送获取打印机对象列表请求失败";
wcp_loger.add_log("发送获取打印机对象列表请求失败", false, "", "Moonraker_Mqtt", "error");
callback(json::value_t::null);
}
}
// Send request to printer via MQTT
bool Moonraker_Mqtt::send_to_request(
const std::string& method,
const json& params,
bool need_response,
std::function<void(const nlohmann::json& response)> callback,
std::function<void()> timeout_callback)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 发送请求,方法: " << method << ", 需要响应: " << need_response;
wcp_loger.add_log("发送请求,方法: " + method + ", 需要响应: " + std::to_string(need_response), false, "", "Moonraker_Mqtt", "info");
json body;
body["jsonrpc"] = "2.0";
body["method"] = method;
if (!params.empty()) {
body["params"] = params;
}
int64_t seq_id = m_seq_generator.generate_seq_id();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 生成序列ID: " << seq_id;
wcp_loger.add_log("生成序列ID: " + std::to_string(seq_id), false, "", "Moonraker_Mqtt", "info");
if (need_response) {
if (!add_response_target(seq_id, callback, timeout_callback)) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 添加响应目标失败";
wcp_loger.add_log("添加响应目标失败", false, "", "Moonraker_Mqtt", "error");
return false;
}
body["id"] = seq_id;
}
if (m_mqtt_client_tls) {
std::string main_layer = "+";
m_sn_mtx.lock();
main_layer = m_sn;
m_sn_mtx.unlock();
if (main_layer == "+" || main_layer == "") {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] SN无效删除响应目标";
wcp_loger.add_log("SN无效删除响应目标", false, "", "Moonraker_Mqtt", "error");
delete_response_target(seq_id);
return false;
}
std::string topic = main_layer + m_request_topic;
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 发布到主题: " << topic;
wcp_loger.add_log("发布到主题: " + topic, false, "", "Moonraker_Mqtt", "info");
std::string pub_msg = "success";
bool res = m_mqtt_client_tls->Publish(topic, body.dump(), 1, pub_msg);
if (!res) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 发布请求失败,方法: " << method;
wcp_loger.add_log("发布请求失败,方法: " + method, false, "", "Moonraker_Mqtt", "error");
delete_response_target(seq_id);
} else {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 请求发布成功,方法: " << method;
wcp_loger.add_log("请求发布成功,方法: " + method, false, "", "Moonraker_Mqtt", "info");
}
return res;
}
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] MQTTS客户端不可用";
wcp_loger.add_log("MQTTS客户端不可用", false, "", "Moonraker_Mqtt", "error");
return false;
}
// Register callback for response to a request
bool Moonraker_Mqtt::add_response_target(
int64_t id,
std::function<void(const nlohmann::json&)> callback,
std::function<void()> timeout_callback,
std::chrono::milliseconds timeout)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 注册响应回调ID: " << id << ", 超时: " << timeout.count() << "ms";
wcp_loger.add_log("注册响应回调ID: " + std::to_string(id) + ", 超时: " + std::to_string(timeout.count()) + "ms", false, "", "Moonraker_Mqtt", "info");
return m_request_cb_map.add(
id,
RequestCallback(std::move(callback), std::move(timeout_callback)),
timeout
);
}
// Remove registered callback
void Moonraker_Mqtt::delete_response_target(int64_t id) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 删除响应目标ID: " << id;
wcp_loger.add_log("删除响应目标ID: " + std::to_string(id), false, "", "Moonraker_Mqtt", "info");
m_request_cb_map.remove(id);
}
bool Moonraker_Mqtt::check_sn_arrived() {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
bool result = wait_for_sn();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 检查SN到达状态: " << (result ? "已到达" : "未到达");
wcp_loger.add_log("检查SN到达状态: " + std::string((result ? "已到达" : "未到达")), false, "", "Moonraker_Mqtt", "info");
return result;
}
// Get and remove callback for a request
std::function<void(const json&)> Moonraker_Mqtt::get_request_callback(int64_t id)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 获取并移除请求回调ID: " << id;
wcp_loger.add_log("获取并移除请求回调ID: " + std::to_string(id), false, "", "Moonraker_Mqtt", "info");
auto request_cb = m_request_cb_map.get_and_remove(id);
return request_cb ? request_cb->success_cb : nullptr;
}
// Handle incoming MQTTs messages
void Moonraker_Mqtt::on_mqtt_tls_message_arrived(const std::string& topic, const std::string& payload) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 收到MQTTS消息主题: " << topic << ", 载荷长度: " << payload.length();
wcp_loger.add_log("收到MQTTS消息主题: " + topic + ", 载荷长度: " + std::to_string(payload.length()), false, "", "Moonraker_Mqtt", "info");
try {
if (topic.find(m_response_topic) != std::string::npos) {
size_t pos = topic.find("/response");
if (pos != std::string::npos) {
std::string sn = topic.substr(0, pos);
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 从响应主题提取SN: " << sn;
wcp_loger.add_log("从响应主题提取SN: " + sn, false, "", "Moonraker_Mqtt", "info");
m_sn_mtx.lock();
m_sn = sn;
m_sn_mtx.unlock();
}
on_response_arrived(payload);
} else if (topic.find(m_status_topic) != std::string::npos) {
size_t pos = topic.find("/status");
if (pos != std::string::npos) {
std::string sn = topic.substr(0, pos);
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 从状态主题提取SN: " << sn;
wcp_loger.add_log("从状态主题提取SN: " + sn, false, "", "Moonraker_Mqtt", "info");
m_sn_mtx.lock();
m_sn = sn;
m_sn_mtx.unlock();
}
on_status_arrived(payload);
} else if (topic.find(m_notification_topic) != std::string::npos) {
size_t pos = topic.find("/notification");
if (pos != std::string::npos) {
std::string sn = topic.substr(0, pos);
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 从通知主题提取SN: " << sn;
wcp_loger.add_log("从通知主题提取SN: " + sn, false, "", "Moonraker_Mqtt", "info");
m_sn_mtx.lock();
m_sn = sn;
m_sn_mtx.unlock();
}
on_notification_arrived(payload);
}
else {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 收到未知主题的消息: " << topic;
wcp_loger.add_log("收到未知主题的消息: " + topic, false, "", "Moonraker_Mqtt", "warning");
return;
}
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 处理MQTTS消息异常: " << e.what();
wcp_loger.add_log("处理MQTTS消息异常: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
}
}
// Handle incoming MQTT messages
void Moonraker_Mqtt::on_mqtt_message_arrived(const std::string& topic, const std::string& payload)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 收到MQTT消息主题: " << topic << ", 载荷长度: " << payload.length();
wcp_loger.add_log("收到MQTT消息主题: " + topic + ", 载荷长度: " + std::to_string(payload.length()), false, "", "Moonraker_Mqtt", "info");
try {
if (topic.find(m_auth_topic) != std::string::npos) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 处理认证响应消息";
wcp_loger.add_log("处理认证响应消息", false, "", "Moonraker_Mqtt", "info");
on_auth_arrived(payload);
} else {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 收到未知主题的MQTT消息: " << topic;
wcp_loger.add_log("收到未知主题的MQTT消息: " + topic, false, "", "Moonraker_Mqtt", "warning");
return;
}
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 处理MQTT消息异常: " << e.what();
wcp_loger.add_log("处理MQTT消息异常: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
}
}
// Handle auth messages
void Moonraker_Mqtt::on_auth_arrived(const std::string& payload) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 处理认证到达消息";
wcp_loger.add_log("处理认证到达消息", false, "", "Moonraker_Mqtt", "info");
try {
json body = json::parse(payload);
if(!body.count("id")){
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 认证响应缺少ID字段";
wcp_loger.add_log("认证响应缺少ID字段", false, "", "Moonraker_Mqtt", "warning");
return;
}
int64_t id = body["id"].get<int64_t>();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 认证响应ID: " << id;
wcp_loger.add_log("认证响应ID: " + std::to_string(id), false, "", "Moonraker_Mqtt", "info");
auto cb = get_request_callback(id);
delete_response_target(id);
if (!cb) {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 未找到对应的认证回调";
wcp_loger.add_log("未找到对应的认证回调", false, "", "Moonraker_Mqtt", "warning");
return;
}
json res = body["result"];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 认证响应处理完成";
wcp_loger.add_log("认证响应处理完成", false, "", "Moonraker_Mqtt", "info");
cb(res);
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 处理认证响应异常: " << e.what();
wcp_loger.add_log("处理认证响应异常: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
}
}
// Handle response messages
void Moonraker_Mqtt::on_response_arrived(const std::string& payload)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 处理响应到达消息";
wcp_loger.add_log("处理响应到达消息", false, "", "Moonraker_Mqtt", "info");
try {
json body = json::parse(payload);
if (!body.count("id")) {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 响应消息缺少ID字段";
wcp_loger.add_log("响应消息缺少ID字段", false, "", "Moonraker_Mqtt", "warning");
return;
}
int64_t id = -1;
id = body["id"].get<int64_t>();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 响应ID: " << id;
wcp_loger.add_log("响应ID: " + std::to_string(id), false, "", "Moonraker_Mqtt", "info");
auto cb = get_request_callback(id);
delete_response_target(id);
if (!cb) {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 未找到对应的响应回调ID: " << id;
wcp_loger.add_log("未找到对应的响应回调ID: " + std::to_string(id), false, "", "Moonraker_Mqtt", "warning");
return;
}
json res;
if (/*id.find("mqtt") != std::string::npos*/ id == 20252025) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 特殊MQTT请求直接返回原始响应";
wcp_loger.add_log("特殊MQTT请求直接返回原始响应", false, "", "Moonraker_Mqtt", "info");
cb(body);
} else {
if (!body.count("result")) {
if (body.count("error")) {
json error = body["error"];
res["error"] = error;
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 响应包含错误信息";
wcp_loger.add_log("响应包含错误信息", false, "", "Moonraker_Mqtt", "warning");
}
} else {
res["data"] = body["result"];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 响应包含结果数据";
wcp_loger.add_log("响应包含结果数据", false, "", "Moonraker_Mqtt", "info");
}
res["method"] = "";
if (body.count("method")) {
res["method"] = body["method"];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 响应包含方法: " << body["method"].get<std::string>();
wcp_loger.add_log("响应包含方法: " + body["method"].get<std::string>(), false, "", "Moonraker_Mqtt", "info");
}
cb(res);
}
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 处理响应消息异常: " << e.what();
wcp_loger.add_log("处理响应消息异常: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
}
}
// Handle status update messages
void Moonraker_Mqtt::on_status_arrived(const std::string& payload)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 处理状态更新消息";
wcp_loger.add_log("处理状态更新消息", false, "", "Moonraker_Mqtt", "info");
try {
json body = json::parse(payload);
json data;
if (body.count("params")) {
data["data"] = body["params"];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 状态更新包含参数";
wcp_loger.add_log("状态更新包含参数", false, "", "Moonraker_Mqtt", "info");
} else if (body.count("result") && body["result"].count("status")) {
data["data"] = body["result"]["status"];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 状态更新包含结果状态";
wcp_loger.add_log("状态更新包含结果状态", false, "", "Moonraker_Mqtt", "info");
} else {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 状态更新消息格式无效";
wcp_loger.add_log("状态更新消息格式无效", false, "", "Moonraker_Mqtt", "info");
return;
}
// test: 如果有method则进行传递
data["method"] = "";
if (body.count("method")){
data["method"] = body["method"];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 状态更新包含方法: " << body["method"].get<std::string>();
wcp_loger.add_log("状态更新包含方法: " + body["method"].get<std::string>(), false, "", "Moonraker_Mqtt", "info");
}
if (m_status_cbs.empty()) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 状态回调未设置";
wcp_loger.add_log("状态回调未设置", false, "", "Moonraker_Mqtt", "info");
return;
}
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 调用状态回调";
wcp_loger.add_log("调用状态回调", false, "", "Moonraker_Mqtt", "info");
for (const auto& func : m_status_cbs) {
func.second(data);
}
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 处理状态更新异常: " << e.what();
wcp_loger.add_log("处理状态更新异常: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
}
}
// Handle notification messages
void Moonraker_Mqtt::on_notification_arrived(const std::string& payload)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 处理通知消息,载荷长度: " << payload.length();
wcp_loger.add_log("处理通知消息,载荷长度: " + std::to_string(payload.length()), false, "", "Moonraker_Mqtt", "info");
try {
// TODO: 实现通知消息处理逻辑
json body = json::parse(payload);
json data;
if (body.count("params")) {
data["data"] = body["params"];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 状态更新包含参数";
wcp_loger.add_log("状态更新包含参数", false, "", "Moonraker_Mqtt", "info");
} else if (body.count("result") && body["result"].count("status")) {
data["data"] = body["result"]["status"];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 状态更新包含结果状态";
wcp_loger.add_log("状态更新包含结果状态", false, "", "Moonraker_Mqtt", "info");
} else {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 状态更新消息格式无效";
wcp_loger.add_log("状态更新消息格式无效", false, "", "Moonraker_Mqtt", "warning");
return;
}
data["method"] = "";
if (body.count("method")) {
data["method"] = body["method"];
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 状态更新包含方法: " << body["method"].get<std::string>();
wcp_loger.add_log("状态更新包含方法: " + body["method"].get<std::string>(), false, "", "Moonraker_Mqtt", "info");
}
if (m_notification_cbs.empty()) {
return;
}
for (const auto& func : m_notification_cbs) {
func.second(data);
}
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Moonraker_Mqtt] 处理通知消息异常: " << e.what();
wcp_loger.add_log("处理通知消息异常: " + std::string(e.what()), false, "", "Moonraker_Mqtt", "error");
}
}
// 添加一个辅助函数来等待SN
bool Moonraker_Mqtt::wait_for_sn(int timeout_seconds)
{
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 等待SN超时时间: " << timeout_seconds << "";
wcp_loger.add_log("等待SN超时时间: " + std::to_string(timeout_seconds) + "", false, "", "Moonraker_Mqtt", "info");
using namespace std::chrono;
auto start = steady_clock::now();
while (true) {
{
std::lock_guard<std::mutex> lock(m_sn_mtx);
if (!m_sn.empty()) {
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] SN已获取: " << m_sn;
wcp_loger.add_log("SN已获取: " + m_sn, false, "", "Moonraker_Mqtt", "info");
return true;
}
}
auto now = steady_clock::now();
if (duration_cast<seconds>(now - start).count() >= timeout_seconds) {
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 等待SN超时";
wcp_loger.add_log("等待SN超时", false, "", "Moonraker_Mqtt", "warning");
return false;
}
std::this_thread::sleep_for(milliseconds(100));
}
}
void Moonraker_Mqtt::set_connection_lost(std::function<void()> callback) {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
BOOST_LOG_TRIVIAL(warning) << "[Moonraker_Mqtt] 设置连接丢失回调";
wcp_loger.add_log("设置连接丢失回调", false, "", "Moonraker_Mqtt", "info");
if (m_mqtt_client_tls)
m_mqtt_client_tls->SetConnectionFailureCallback(callback);
}
std::string Moonraker_Mqtt::get_sn() {
auto& wcp_loger = GUI::WCP_Logger::getInstance();
std::string res = "";
m_sn_mtx.lock();
res = m_sn;
m_sn_mtx.unlock();
BOOST_LOG_TRIVIAL(info) << "[Moonraker_Mqtt] 获取SN: " << res;
wcp_loger.add_log("获取SN: " + res, false, "", "Moonraker_Mqtt", "info");
return res;
}
} // namespace Slic3r