mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-06 07:11:10 +00:00
Follow-up to the feature/OrcaSonar review. Scopes the new behavior to the OrcaSonar agent, fixes several AMS-sync and lifecycle bugs, and makes the MQTT tests run in CI. Non-OrcaSonar agents keep their existing behavior. ## Changes Discovery - Gate the background SSDP scan to a configured OrcaSonar machine instead of running for every non-BBL profile; drive discovery on demand from the machine-select popup and back off idle rounds from 5s to 60s. - Add NSLocalNetworkUsageDescription and NSBonjourServices to both macOS Info.plist templates. AMS sync - Resolve id-less printer-set trays by material type in get_ams_cobox_infos and the sidebar badge loop, matching sync_ams_list, so combo arrays and badges stay aligned. - Keep a printer-set tray that resolved by type out of the "unknown or incompatible filaments" dialog. AMS device UI - Gate the "Empty" tray classification, and the editable temperature fields, to the OrcaSonar agent; Bambu keeps "?" and read-only presets. - Validate AMS material temps on confirm: reject out-of-range values and min > max before the command is sent. Storage tab - Bind the show/hide handler on the panel's ancestors (StoragePanel and MonitorPanel) and unbind on destruction, so the Bambu file system stops when the tab is left. Transport - Load /etc/ssl/cert.pem on macOS in add_platform_root_certificates, after set_default_verify_paths. - Release lifecycle_mutex before start()'s connect wait so stop() can cancel the attempt and signal completion instead of stalling the UI thread. Localization - Add OrcaFilesPanel.cpp to list.txt and regenerate the catalogs. ## Tests - Un-hide the loopback MockBroker integration tests (ephemeral port, no network) so ctest registers and runs them. - Mock broker tracks SUBSCRIBE/UNSUBSCRIBE and delivers push_report only to a subscribed topic; the reconnect test asserts the re-SUBSCRIBE. - Add bbl empty-tray cases, an AMS combo-alignment case, and unknowns assertions to the AMS sync tests.
136 lines
4.8 KiB
C++
136 lines
4.8 KiB
C++
// why: match the GUI include order to avoid rpcndr.h byte/std::byte
|
|
// ambiguity in the Windows COM headers.
|
|
#ifdef WIN32
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#ifndef NOMINMAX
|
|
#define NOMINMAX
|
|
#endif
|
|
#include <Windows.h>
|
|
#endif
|
|
|
|
#include <catch2/catch_all.hpp>
|
|
|
|
#include <wx/timer.h>
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
#include "slic3r/GUI/Widgets/AMSItem.hpp"
|
|
#include "slic3r/GUI/DeviceCore/DevFilaSystem.h"
|
|
|
|
using json = nlohmann::json;
|
|
using namespace Slic3r;
|
|
using namespace Slic3r::GUI;
|
|
|
|
// A configured slot the wire reports as having no filament (all material fields
|
|
// present and empty) is "Empty", not the unknown "?" the UI draws for a tray
|
|
// whose info is missing. The distinction must survive into the AMS panel model.
|
|
TEST_CASE("Configured empty AMS trays remain distinct from unknown trays", "[AMSItem]")
|
|
{
|
|
MachineObject machine(nullptr, nullptr, "test", "test-device", "127.0.0.1");
|
|
machine.printer_agent_id = "orca";
|
|
|
|
const json print_json = json::parse(R"({
|
|
"ams": {
|
|
"ams_exist_bits": "1",
|
|
"tray_exist_bits": "3",
|
|
"ams": [ { "id": "0", "info": "0001", "tray": [
|
|
{ "id": "0", "tag_uid": "0000000000000000", "tray_info_idx": "", "tray_type": "", "tray_color": "00000000" },
|
|
{ "id": "1" }
|
|
] } ]
|
|
}
|
|
})");
|
|
DevFilaSystemParser::ParseV1_0(print_json, &machine, machine.GetFilaSystem().get(), false);
|
|
|
|
const auto& ams_list = machine.GetFilaSystem()->GetAmsList();
|
|
const auto ams_it = ams_list.find("0");
|
|
REQUIRE(ams_it != ams_list.end());
|
|
auto* ams = ams_it->second;
|
|
REQUIRE(ams != nullptr);
|
|
REQUIRE(ams->GetTray("0") != nullptr);
|
|
CHECK(ams->GetTray("0")->is_empty);
|
|
|
|
AMSinfo info;
|
|
REQUIRE(info.parse_ams_info(&machine, ams));
|
|
REQUIRE(info.cans.size() == 2);
|
|
|
|
CHECK(info.cans[0].is_empty);
|
|
CHECK(info.cans[0].material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND);
|
|
CHECK_FALSE(info.cans[1].is_empty);
|
|
CHECK(info.cans[1].material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND);
|
|
}
|
|
|
|
TEST_CASE("Empty external slots remain distinct from unknown slots", "[AMSItem]")
|
|
{
|
|
MachineObject machine(nullptr, nullptr, "test", "test-device", "127.0.0.1");
|
|
machine.printer_agent_id = "orca";
|
|
|
|
DevAmsTray empty_slot = machine.parse_vt_tray(json::parse(R"({
|
|
"id": "255", "tag_uid": "0000000000000000", "tray_info_idx": "", "tray_type": "", "tray_color": "00000000"
|
|
})"));
|
|
CHECK(empty_slot.is_empty);
|
|
|
|
AMSinfo empty_info;
|
|
empty_info.parse_ext_info(&machine, empty_slot);
|
|
CHECK(empty_info.cans[0].is_empty);
|
|
CHECK(empty_info.cans[0].material_state == AMSCanType::AMS_CAN_TYPE_VIRTUAL);
|
|
|
|
DevAmsTray unknown_slot = machine.parse_vt_tray(json::parse(R"({"id": "254"})"));
|
|
CHECK_FALSE(unknown_slot.is_empty);
|
|
|
|
AMSinfo unknown_info;
|
|
unknown_info.parse_ext_info(&machine, unknown_slot);
|
|
CHECK_FALSE(unknown_info.cans[0].is_empty);
|
|
CHECK(unknown_info.cans[0].material_state == AMSCanType::AMS_CAN_TYPE_VIRTUAL);
|
|
}
|
|
|
|
// Only the OrcaSonar agent opts into the "Empty" classification. Bambu and other
|
|
// agents keep the unknown "?" for a present-but-blank tray, so they must leave the
|
|
// empty flag untouched.
|
|
TEST_CASE("Bambu-style agents keep blank AMS trays as unknown", "[AMSItem]")
|
|
{
|
|
MachineObject machine(nullptr, nullptr, "test", "test-device", "127.0.0.1");
|
|
machine.printer_agent_id = "bbl";
|
|
|
|
const json print_json = json::parse(R"({
|
|
"ams": {
|
|
"ams_exist_bits": "1",
|
|
"tray_exist_bits": "3",
|
|
"ams": [ { "id": "0", "info": "0001", "tray": [
|
|
{ "id": "0", "tag_uid": "0000000000000000", "tray_info_idx": "", "tray_type": "", "tray_color": "00000000" },
|
|
{ "id": "1" }
|
|
] } ]
|
|
}
|
|
})");
|
|
DevFilaSystemParser::ParseV1_0(print_json, &machine, machine.GetFilaSystem().get(), false);
|
|
|
|
const auto& ams_list = machine.GetFilaSystem()->GetAmsList();
|
|
const auto ams_it = ams_list.find("0");
|
|
REQUIRE(ams_it != ams_list.end());
|
|
auto* ams = ams_it->second;
|
|
REQUIRE(ams != nullptr);
|
|
REQUIRE(ams->GetTray("0") != nullptr);
|
|
CHECK_FALSE(ams->GetTray("0")->is_empty);
|
|
|
|
AMSinfo info;
|
|
REQUIRE(info.parse_ams_info(&machine, ams));
|
|
REQUIRE(info.cans.size() == 2);
|
|
CHECK_FALSE(info.cans[0].is_empty);
|
|
}
|
|
|
|
TEST_CASE("Bambu-style agents keep blank external slots as unknown", "[AMSItem]")
|
|
{
|
|
MachineObject machine(nullptr, nullptr, "test", "test-device", "127.0.0.1");
|
|
machine.printer_agent_id = "bbl";
|
|
|
|
DevAmsTray empty_slot = machine.parse_vt_tray(json::parse(R"({
|
|
"id": "255", "tag_uid": "0000000000000000", "tray_info_idx": "", "tray_type": "", "tray_color": "00000000"
|
|
})"));
|
|
CHECK_FALSE(empty_slot.is_empty);
|
|
|
|
AMSinfo info;
|
|
info.parse_ext_info(&machine, empty_slot);
|
|
CHECK_FALSE(info.cans[0].is_empty);
|
|
}
|