feat: add filament mapping and AMS capability gates for the orca printer agent

Parse connector-scope capabilities from get_capabilities: supported_features, capabilities.protocol.features and supported_commands are read for orca devices even when the reply has no flags block, reset before each parse, and left untouched for Bambu.

Gate macro-backed AMS commands on fms plus the advertised command (change filament, select tray, control, user settings, RFID, drying stop); gate slot metadata writes on filament_slots. Unknown capability is not support.

Serialize PrintParams::ams_mapping2 into print.gcode_file.filament_mapping with the array position as filament_index and {255,255} dropped. The field is omitted when empty, so an unmapped print stays byte-identical. A mapped print is refused visibly while ORCA_FILAMENT_MAPPING_CORRELATION_VERIFIED is false or the connector did not advertise filament_mapping; the GUI predicate shares the serializer's definition so both gates agree. Refuse a partially mapped print that leaves a used filament without a target.

Return a non-success result from start_local_print_with_record so PrintJob falls back to start_print instead of treating an unsent print as success.

Tests cover serializer keying and omission, GUI/agent gate agreement, payload shape, the with_record result, capability parsing, and the per-command AMS gate.
This commit is contained in:
Lam Wei Lun
2026-09-26 22:50:58 +08:00
parent 87eb8de001
commit adcc470cff
11 changed files with 607 additions and 12 deletions
+27
View File
@@ -10,6 +10,8 @@
#include "DeviceCore/DevManager.h"
#include "DeviceCore/DevStorage.h"
#include "slic3r/Utils/NetworkAgentFactory.hpp"
#include "FilamentMappingUtils.hpp"
namespace Slic3r {
namespace GUI {
@@ -692,6 +694,8 @@ bool SendMultiMachinePage::get_ams_mapping_result(std::string &mapping_array_str
return true;
}
// Mapping helpers live in FilamentMappingUtils.hpp, shared with SelectMachine.
void SendMultiMachinePage::on_send(wxCommandEvent& event)
{
event.Skip();
@@ -740,6 +744,29 @@ void SendMultiMachinePage::on_send(wxCommandEvent& event)
if (!wxGetApp().is_blocking_printing(obj)) {
PrintParams params = request_params(obj);
// OrcaSonar: a mapped print requires the connector to advertise
// filament_mapping, and a partially mapped print must not silently drop a
// used filament. Any entry the serializer would put on the wire engages the
// gate, external slots ({255,0}/{254,0}) included; the extra-spool branch
// rewrites to exactly those. Bambu is unchanged.
if (obj->printer_agent_id == ORCA_PRINTER_AGENT_ID) {
const bool mapping_available = obj->is_support_filament_mapping && ORCA_FILAMENT_MAPPING_CORRELATION_VERIFIED;
if (!mapping_available && has_engaged_filament_mapping(params.ams_mapping2)) {
BOOST_LOG_TRIVIAL(warning) << "SendMultiMachinePage: filament mapping unavailable (capability=" << obj->is_support_filament_mapping
<< ", correlation_verified=" << ORCA_FILAMENT_MAPPING_CORRELATION_VERIFIED << "); refusing mapped print for "
<< obj->get_dev_id();
MessageDialog msg_wingow(nullptr, _L("AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."), "", wxICON_WARNING | wxOK);
msg_wingow.ShowModal();
return;
}
if (params.task_use_ams && has_any_mapped_target(m_ams_mapping_result) &&
has_used_filament_without_target(m_ams_mapping_result)) {
BOOST_LOG_TRIVIAL(warning) << "SendMultiMachinePage: a used filament has no target; refusing print for " << obj->get_dev_id();
MessageDialog msg_wingow(nullptr, _L("A filament used by this print has no AMS mapping. Assign it before printing."), "", wxICON_WARNING | wxOK);
msg_wingow.ShowModal();
return;
}
}
print_params.push_back(params);
}
}