mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-08 08:11:14 +00:00
fix: make the AMS device UI work on non-Bambu printer agents
Resolve the filament list's printer model from the agent-reported model id or the selected printer profile, so the AMS Materials Setting dropdown and its Confirm button work on OrcaSonar. Third-party trays pre-fill and allow editing their temps, and the popup's initial selection no longer overwrites them. Render explicitly-empty trays as "Empty" instead of "?" using a wire-derived DevAmsTray::is_empty, while keeping the slot editable. Hide the flow-dynamics K/N controls for non-Bambu agents — tile, dialog, validation and sends — with Bambu behavior unchanged. Tests cover model resolution, the K/N gate and empty-tray classification.
This commit is contained in:
@@ -1601,6 +1601,23 @@ TEST_CASE("Filaments offered for a machine follow the app's compatibility rule",
|
||||
}
|
||||
}
|
||||
|
||||
// An agent-reported model id (SSDP modelNumber, manual binding) must resolve to the display
|
||||
// name printer profiles use as printer_model; the AMS dialogs look filaments up by it.
|
||||
TEST_CASE("Printer model ids resolve to vendor display names", "[Preset][Bundle]")
|
||||
{
|
||||
PresetBundle bundle;
|
||||
VendorProfile qidi("Qidi");
|
||||
qidi.name = "Qidi";
|
||||
VendorProfile::PrinterModel model;
|
||||
model.model_id = "Qidi-Q1Pro";
|
||||
model.name = "Qidi Q1 Pro";
|
||||
qidi.models.push_back(model);
|
||||
bundle.vendors.emplace(qidi.id, qidi);
|
||||
|
||||
CHECK(bundle.get_printer_model_display_name("Qidi-Q1Pro") == "Qidi Q1 Pro");
|
||||
CHECK(bundle.get_printer_model_display_name("unknown-model").empty());
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ add_executable(${_TEST_NAME}_tests
|
||||
test_dev_mapping.cpp
|
||||
test_filament_bitmap_utils.cpp
|
||||
test_device_progress.cpp
|
||||
test_ams_item.cpp
|
||||
test_device_manager_integration.cpp
|
||||
test_web_media_controller.cpp
|
||||
test_scene_raycaster.cpp
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// 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);
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <slic3r/GUI/DeviceCore/DevManager.h>
|
||||
#include <slic3r/GUI/DeviceManager.hpp>
|
||||
#include <libslic3r/AppConfig.hpp>
|
||||
#include <libslic3r/PresetBundle.hpp>
|
||||
#include <libslic3r/PrintConfig.hpp>
|
||||
#include "slic3r/Utils/IPrinterAgent.hpp"
|
||||
#include "slic3r/Utils/CloudProvider.hpp"
|
||||
#include <slic3r/Utils/NetworkAgent.hpp>
|
||||
@@ -276,3 +278,52 @@ TEST_CASE("Orca per-command AMS gate requires fms and the advertised command", "
|
||||
obj->printer_agent_id = "bbl";
|
||||
CHECK(obj->orca_ams_command_supported("print.anything"));
|
||||
}
|
||||
|
||||
// The AMS dialogs resolve their filament list from the connected device's model. OrcaSonar's
|
||||
// model id is optional (the agent falls back to "orcasonar"), so the resolver must stand in
|
||||
// with the selected printer profile instead of yielding no model at all.
|
||||
TEST_CASE("Filament printer model resolution falls back to the selected profile", "[DeviceManager][integration]")
|
||||
{
|
||||
PresetBundle bundle;
|
||||
|
||||
VendorProfile qidi("Qidi");
|
||||
qidi.name = "Qidi";
|
||||
VendorProfile::PrinterModel model;
|
||||
model.model_id = "Qidi-Q1Pro";
|
||||
model.name = "Qidi Q1 Pro";
|
||||
qidi.models.push_back(model);
|
||||
bundle.vendors.emplace(qidi.id, qidi);
|
||||
|
||||
// A vendor model id the device reported resolves through the vendor catalog.
|
||||
CHECK(resolve_filament_printer_model("Qidi-Q1Pro", &bundle) == "Qidi Q1 Pro");
|
||||
|
||||
// The OrcaSonar fallback id has no vendor model; the selected profile stands in.
|
||||
CHECK(resolve_filament_printer_model("orcasonar", &bundle).empty());
|
||||
bundle.printers.get_selected_preset().config.set_key_value("printer_model", new ConfigOptionString("Generic Klipper Printer"));
|
||||
CHECK(resolve_filament_printer_model("orcasonar", &bundle) == "Generic Klipper Printer");
|
||||
CHECK(resolve_filament_printer_model("", &bundle) == "Generic Klipper Printer");
|
||||
|
||||
CHECK(resolve_filament_printer_model("orcasonar", nullptr).empty());
|
||||
}
|
||||
|
||||
// The per-tray K/N records are Bambu firmware's flow-dynamics calibration. Agents with no
|
||||
// printer-side records must not offer the AMS K/N controls (they would show a synthesized
|
||||
// default and then refuse to confirm it).
|
||||
TEST_CASE("Flow-dynamics K/N is offered for Bambu agents only", "[DeviceManager][integration]")
|
||||
{
|
||||
MachineObject bbl(nullptr, nullptr, "test", "bbl-device", "127.0.0.1");
|
||||
bbl.printer_agent_id = "bbl";
|
||||
CHECK(bbl.supports_extrusion_cali());
|
||||
|
||||
MachineObject orca(nullptr, nullptr, "test", "orca-device", "127.0.0.1");
|
||||
orca.printer_agent_id = "orca";
|
||||
CHECK_FALSE(orca.supports_extrusion_cali());
|
||||
|
||||
MachineObject moonraker(nullptr, nullptr, "test", "moonraker-device", "127.0.0.1");
|
||||
moonraker.printer_agent_id = "moonraker";
|
||||
CHECK_FALSE(moonraker.supports_extrusion_cali());
|
||||
|
||||
// No agent id predates the agent split and keeps the Bambu path.
|
||||
MachineObject legacy(nullptr, nullptr, "test", "legacy-device", "127.0.0.1");
|
||||
CHECK(legacy.supports_extrusion_cali());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user