fix(ElegooLink): pass printer SN to CC2 device panel URL (#13878)
* fix(ElegooLink): pass printer SN to CC2 device panel URL The CC2 panel subscribes to MQTT topics keyed by the printer serial number. Without sn= in the URL it uses a wrong hardcoded fallback SN, subscribes to the wrong topics, and shows Offline permanently even though the printer is reachable. - Cache the SN in elegoo_cc2_test() (already fetches it, was discarding it) - Look up cache in get_print_host_webui(); fall back to a short LAN HTTP call on first use before the test has run - Append sn= to the panel URL - Clear the wrong hardcoded fallback SN/IP from the panel bundle - Add a small synchronous boot script to the panel that fetches the SN from the printer before the bundle reads URLSearchParams, as a fallback for unpatched binaries * fix(ElegooLink): persist CC2 serial number in AppConfig dev_sn section Store the printer SN under [dev_sn] keyed by normalized print_host after a successful connection test or system/info fetch. Reuse it on later sessions before hitting the network, matching how access_code is keyed by dev_id for other LAN printers. * fix(ElegooLink): answer get_sn IPC instantly from dev_sn cache The CC2 panel always calls get_sn with a 10s timeout. Remove the HTTP fallback from get_sn() and resolve IPC from dev_sn/memory only so Device tab load is not blocked after sn= is already in the URL. * fix(ElegooLink): skip get_sn IPC when URL already has sn The CC2 device panel calls get_sn with a 10s timeout on every MQTT connect even when Orca passes sn= in the query string. Use the URL serial immediately and only fall back to IPC when it is missing. * refactor(ElegooLink): resolve CC2 SN via PrintHost::get_sn in GUI Drop the ElegooLink.hpp include from PrinterWebViewHandler; the webview IPC handler uses the existing PrintHost virtual instead. Keep CC2 serial lookup helpers file-local in ElegooLink.cpp and share them between get_sn() and get_print_host_webui(). * chore: drop redundant <memory> include in PrinterWebViewHandler --------- Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -98,8 +98,6 @@ public:
|
||||
stop_upload = true;
|
||||
if (upload_thread.joinable())
|
||||
upload_thread.join();
|
||||
if (sn_thread.joinable())
|
||||
sn_thread.join();
|
||||
}
|
||||
|
||||
void on_script_message(wxWebViewEvent &evt) override
|
||||
@@ -287,35 +285,21 @@ private:
|
||||
|
||||
void handle_get_sn_request(const std::string& request_id, const std::string& method)
|
||||
{
|
||||
if (sn_request_in_progress.exchange(true)) {
|
||||
send_ipc_message("response", request_id, method, 1, "SN request already in progress");
|
||||
return;
|
||||
// Panel always calls get_sn with a 10s IPC timeout. Answer immediately from
|
||||
// dev_sn / cache — do not spawn a thread or perform HTTP (panel uses URL sn on miss).
|
||||
std::string sn;
|
||||
if (DynamicPrintConfig* config = get_active_printer_config()) {
|
||||
const std::unique_ptr<PrintHost> host(PrintHost::get_print_host(config));
|
||||
if (host)
|
||||
sn = host->get_sn();
|
||||
}
|
||||
|
||||
if (sn_thread.joinable())
|
||||
sn_thread.join();
|
||||
|
||||
sn_thread = std::thread([this, request_id, method]() {
|
||||
std::string sn;
|
||||
|
||||
DynamicPrintConfig* config = get_active_printer_config();
|
||||
std::unique_ptr<PrintHost> print_host(config == nullptr ? nullptr : PrintHost::get_print_host(config));
|
||||
if (print_host != nullptr)
|
||||
sn = print_host->get_sn();
|
||||
|
||||
sn_request_in_progress = false;
|
||||
json data = {
|
||||
{"sn", sn}
|
||||
};
|
||||
send_ipc_message("response", request_id, method, 0, "success", dump_json(data));
|
||||
});
|
||||
json data = { { "sn", sn } };
|
||||
send_ipc_message("response", request_id, method, 0, "success", dump_json(data));
|
||||
}
|
||||
|
||||
std::atomic<bool> upload_in_progress { false };
|
||||
std::atomic<bool> sn_request_in_progress { false };
|
||||
std::atomic<bool> stop_upload { false };
|
||||
std::thread upload_thread;
|
||||
std::thread sn_thread;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "ElegooLink.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <exception>
|
||||
#include <boost/format.hpp>
|
||||
@@ -60,6 +62,52 @@ namespace Slic3r {
|
||||
namespace {
|
||||
|
||||
constexpr const char* ELEGOO_CC2_DEFAULT_TOKEN = "123456";
|
||||
// AppConfig section for CC2 serial numbers, keyed by normalized print_host (host/IP).
|
||||
constexpr const char* ELEGOO_DEV_SN_SECTION = "dev_sn";
|
||||
|
||||
static std::mutex s_sn_cache_mutex;
|
||||
static std::map<std::string, std::string> s_sn_cache;
|
||||
|
||||
std::string sn_cache_key(const std::string& host_ip, const std::string& token)
|
||||
{
|
||||
return host_ip + ":" + token;
|
||||
}
|
||||
|
||||
void cache_sn(const std::string& host_ip, const std::string& token, const std::string& sn)
|
||||
{
|
||||
if (host_ip.empty() || token.empty() || sn.empty())
|
||||
return;
|
||||
std::lock_guard<std::mutex> lock(s_sn_cache_mutex);
|
||||
s_sn_cache[sn_cache_key(host_ip, token)] = sn;
|
||||
}
|
||||
|
||||
std::string lookup_sn(const std::string& host_ip, const std::string& token)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_sn_cache_mutex);
|
||||
auto it = s_sn_cache.find(sn_cache_key(host_ip, token));
|
||||
return it != s_sn_cache.end() ? it->second : std::string{};
|
||||
}
|
||||
|
||||
std::string load_sn_from_config(const std::string& host_ip)
|
||||
{
|
||||
if (host_ip.empty())
|
||||
return {};
|
||||
AppConfig* app_cfg = GUI::get_app_config();
|
||||
if (app_cfg == nullptr)
|
||||
return {};
|
||||
return app_cfg->get(ELEGOO_DEV_SN_SECTION, host_ip);
|
||||
}
|
||||
|
||||
void persist_sn(const std::string& host_ip, const std::string& token, const std::string& sn)
|
||||
{
|
||||
if (host_ip.empty() || sn.empty())
|
||||
return;
|
||||
cache_sn(host_ip, token, sn);
|
||||
AppConfig* app_cfg = GUI::get_app_config();
|
||||
if (app_cfg == nullptr)
|
||||
return;
|
||||
app_cfg->set_str(ELEGOO_DEV_SN_SECTION, host_ip, sn);
|
||||
}
|
||||
|
||||
enum class ElegooPrinterType {
|
||||
Other,
|
||||
@@ -193,6 +241,30 @@ namespace Slic3r {
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string lookup_cc2_serial_impl(const std::string& printer_model,
|
||||
const std::string& print_host,
|
||||
const std::string& apikey)
|
||||
{
|
||||
if (classify_printer_model(printer_model) != ElegooPrinterType::CC2)
|
||||
return {};
|
||||
|
||||
const std::string host_ip = get_host_from_url(print_host);
|
||||
const std::string token = get_cc2_token(apikey);
|
||||
std::string sn = lookup_sn(host_ip, token);
|
||||
if (sn.empty())
|
||||
sn = load_sn_from_config(host_ip);
|
||||
return sn;
|
||||
}
|
||||
|
||||
std::string lookup_cc2_serial(DynamicPrintConfig* config)
|
||||
{
|
||||
if (config == nullptr)
|
||||
return {};
|
||||
return lookup_cc2_serial_impl(config->opt_string("printer_model"),
|
||||
config->opt_string("print_host"),
|
||||
config->opt_string("printhost_apikey"));
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
// 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)
|
||||
@@ -336,8 +408,30 @@ namespace Slic3r {
|
||||
std::string web_path = resources_dir() + "/plugins/elegoolink/web/lan_service_web/index.html";
|
||||
std::replace(web_path.begin(), web_path.end(), '\\', '/');
|
||||
web_path = "file://" + web_path;
|
||||
web_path += "?access_code=" + get_cc2_token(config->opt_string("printhost_apikey"));
|
||||
web_path += "&ip=" + get_host_from_url(host) + "&id=elegoo_123456";
|
||||
|
||||
const std::string token = get_cc2_token(config->opt_string("printhost_apikey"));
|
||||
const std::string host_ip = get_host_from_url(host);
|
||||
|
||||
// Pass sn= so the panel can subscribe to the correct MQTT topics.
|
||||
std::string sn = lookup_cc2_serial(config);
|
||||
if (sn.empty()) {
|
||||
std::string error_msg;
|
||||
auto http = Http::get("http://" + host_ip + "/system/info?X-Token=" + escape_string(token));
|
||||
http.timeout_connect(3).timeout_max(5);
|
||||
http.header("X-Token", token);
|
||||
http.header("Accept", "application/json");
|
||||
http.on_complete([&](std::string body, unsigned /*status*/) {
|
||||
parse_cc2_response(body, error_msg, &sn);
|
||||
}).perform_sync();
|
||||
if (!sn.empty())
|
||||
persist_sn(host_ip, token, sn);
|
||||
}
|
||||
|
||||
web_path += "?access_code=" + token;
|
||||
web_path += "&ip=" + host_ip;
|
||||
if (!sn.empty())
|
||||
web_path += "&sn=" + sn;
|
||||
web_path += "&id=elegoo_123456";
|
||||
|
||||
const std::string lang = GUI::wxGetApp().current_language_code_safe().utf8_string();
|
||||
if (!lang.empty())
|
||||
@@ -376,33 +470,9 @@ namespace Slic3r {
|
||||
|
||||
std::string ElegooLink::get_sn() const
|
||||
{
|
||||
if (classify_printer_model(m_printerModel) != ElegooPrinterType::CC2)
|
||||
return "";
|
||||
|
||||
const char* name = get_name();
|
||||
std::string sn;
|
||||
const auto token = cc2_token();
|
||||
auto http = Http::get(make_cc2_info_url());
|
||||
http.timeout_connect(10)
|
||||
.timeout_max(15);
|
||||
http.header("X-Token", token);
|
||||
http.header("Accept", "application/json");
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting CC2 device info for SN: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
})
|
||||
.on_complete([&](std::string body, unsigned status) {
|
||||
std::string error_message;
|
||||
if (!parse_cc2_response(body, error_message, &sn)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("%1%: Failed to parse CC2 SN response, HTTP %2%, reason: %3%") % name % status % error_message;
|
||||
sn.clear();
|
||||
}
|
||||
})
|
||||
#ifdef WIN32
|
||||
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
|
||||
#endif // WIN32
|
||||
.perform_sync();
|
||||
|
||||
return sn;
|
||||
// Panel IPC calls this on every load with a 10s timeout. Never block on HTTP
|
||||
// here — URL sn= and dev_sn must be enough; HTTP is only for get_print_host_webui.
|
||||
return lookup_cc2_serial_impl(m_printerModel, m_host, m_apikey);
|
||||
}
|
||||
|
||||
bool ElegooLink::elegoo_test(wxString& msg) const{
|
||||
@@ -481,6 +551,7 @@ namespace Slic3r {
|
||||
msg = format_error(body, error_message.empty() ? "CC2 device not detected" : error_message, status);
|
||||
return;
|
||||
}
|
||||
persist_sn(get_host_from_url(m_host), token, serial_number);
|
||||
res = true;
|
||||
})
|
||||
#ifdef WIN32
|
||||
|
||||
Reference in New Issue
Block a user