feat(gui): warn when the hotend rack inventory falls short of the sliced plate

Follow-up to the rack-aware pre-print checks: after the blocking checks
pass, warn (without disabling Send) when the plate needs more matching
hotends than the rack printer currently holds - suggesting rack setup,
a nozzle info refresh, or a re-slice to avoid filament waste - or when
the only matches rely on unreliable nozzle information.

Text-only warning rows; this message board has no refresh or
don't-show-again buttons.
This commit is contained in:
SoftFever
2026-07-13 00:55:52 +08:00
parent 2fecfc291f
commit 30aa7d9557
5 changed files with 99 additions and 0 deletions

View File

@@ -18786,3 +18786,12 @@ msgstr ""
#, possible-c-format, possible-boost-format
msgid "The hardness of current material (%s) exceeds the hardness of %s(%s). It may cause nozzle wear, leading to material leakage and unstable flow. Please exercise caution when using it."
msgstr ""
msgid "There are not enough available hotends currently."
msgstr ""
msgid "Please re-slice to avoid filament waste."
msgstr ""
msgid "The reported hotend information may be unreliable."
msgstr ""

View File

@@ -61,6 +61,8 @@ std::string PrePrintChecker::get_print_status_info(PrintDialogStatus status)
case PrintStatusNozzleNoMatchedHotends: return "PrintStatusNozzleNoMatchedHotends";
case PrintStatusNozzleRackMaximumInstalled: return "PrintStatusNozzleRackMaximumInstalled";
case PrintStatusRackReading: return "PrintStatusRackReading";
case PrintStatusRackNozzleNumUnmeetWarning: return "PrintStatusRackNozzleNumUnmeetWarning";
case PrintStatusHasUnreliableNozzleWarning: return "PrintStatusHasUnreliableNozzleWarning";
case PrintStatusWarningExtFilamentNotMatch: return "PrintStatusWarningExtFilamentNotMatch";
case PrintStatusFilamentWarningNozzleHRC: return "PrintStatusFilamentWarningNozzleHRC";
case PrintStatusReadingFinished: return "PrintStatusReadingFinished";

View File

@@ -97,6 +97,8 @@ enum PrintDialogStatus : unsigned int {
PrintStatusToolHeadCoolingFanWarning,
PrintStatusRackNozzleMappingWarning,
PrintStatusFilaSwitcherSlicingNotMatch,
PrintStatusRackNozzleNumUnmeetWarning,
PrintStatusHasUnreliableNozzleWarning,
PrintStatusPrinterWarningEnd,
// Warnings for filament

View File

@@ -2008,6 +2008,11 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxSt
// Rack hotend info is being read: block Send until it finishes.
Enable_Refresh_Button(true);
Enable_Send_Button(false);
} else if (status == PrintDialogStatus::PrintStatusRackNozzleNumUnmeetWarning ||
status == PrintDialogStatus::PrintStatusHasUnreliableNozzleWarning) {
// Advisory rack inventory shortfalls: allow Send.
Enable_Refresh_Button(true);
Enable_Send_Button(true);
}
/*enter perpare mode*/
@@ -3571,6 +3576,81 @@ bool SelectMachineDialog::CheckErrorRackStatus(MachineObject* obj_)
return true;
}
void SelectMachineDialog::CheckWarningRackStatus(MachineObject* obj_)
{
if (!obj_) {
return;
}
const auto& nozzle_sys = obj_->GetNozzleSystem();
const auto& rack = nozzle_sys->GetNozzleRack();
if (!rack->IsSupported()) {
return;
}
auto nozzle_group_res = DevUtilBackend::GetNozzleGroupResult(m_plater);
if (!nozzle_group_res) {
return;
}
if (m_print_type != FROM_NORMAL) {
return;// there are no slicing data when print from sdcard
}
const auto& nozzle_vec = nozzle_group_res->get_used_nozzles_in_extruder(LOGIC_R_EXTRUDER_ID);
if (nozzle_vec.empty()) {
return;// no need to check if no right nozzles used in slicing
}
std::unordered_map<NozzleDef, int> need_nozzle_map;
for (const auto& slicing_nozzle : nozzle_vec) {
try {
NozzleDef data;
data.nozzle_diameter = std::stof(slicing_nozzle.diameter);
data.nozzle_flow_type = DevNozzle::ToNozzleFlowType(slicing_nozzle.volume_type);
need_nozzle_map[data]++;
} catch (const std::exception& e) {
assert(0);
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "exception: " << e.what();
}
}
for (const auto& need_nozzle : need_nozzle_map) {
const auto& nozzle_info = need_nozzle.first;
const auto& installed_nozzles = nozzle_sys->CollectNozzles(MAIN_EXTRUDER_ID, nozzle_info.nozzle_flow_type, nozzle_info.nozzle_diameter);
int installed_count = installed_nozzles.size();
int installed_reliable_count = 0;
for (const auto& nozzle : installed_nozzles) {
if (nozzle.IsInfoReliable()) {
installed_reliable_count++;
}
}
// check if enough nozzles installed
if (need_nozzle.second > installed_count) {
wxString msg = _L("There are not enough available hotends currently.");
msg += " ";
if (rack->GetCaliStatus() != DevNozzleRack::Rack_CALI_OK) {
msg += _L("Please complete the hotend rack setup and try again.");
} else if (nozzle_sys->HasUnknownNozzles()) {
msg += _L("Please refresh the nozzle information and try again.");
} else {
msg += _L("Please re-slice to avoid filament waste.");
}
show_status(PrintDialogStatus::PrintStatusRackNozzleNumUnmeetWarning, { msg });
break;
}
// check if unreliable nozzle maybe used
if (need_nozzle.second > installed_reliable_count && nozzle_sys->HasUnreliableNozzles()) {
// Orca: text-only warning; this message board has no refresh / don't-show-again buttons.
show_status(PrintDialogStatus::PrintStatusHasUnreliableNozzleWarning,
{ _L("The reported hotend information may be unreliable.") + " " + _L("Please refresh the nozzle information and try again.") });
}
}
}
// Compare the extruder nozzle info between slicing file and installed on printer
bool SelectMachineDialog::CheckErrorExtruderNozzleWithSlicing(MachineObject* obj_)
{
@@ -4156,6 +4236,9 @@ void SelectMachineDialog::update_show_status(MachineObject* obj_)
// check extension tool warning
UpdateStatusCheckWarning_ExtensionTool(obj_);
// check rack nozzle warning
CheckWarningRackStatus(obj_);
/** normal check **/
show_status(PrintDialogStatus::PrintStatusReadyToGo);
}

View File

@@ -521,6 +521,9 @@ public:
// Block Send while a rack printer is still reading its hotend information.
bool CheckErrorRackStatus(MachineObject* obj_);
// Warn (without blocking) when the rack inventory looks insufficient for the sliced plate:
// fewer matching hotends than the plate needs, or matches relying on unreliable nozzle info.
void CheckWarningRackStatus(MachineObject* obj_);
// Compare the slicing file's nozzle requirements (validity, flow, diameter) against the
// printer; the rack extruder is checked against its whole inventory (mounted + rack).
bool CheckErrorExtruderNozzleWithSlicing(MachineObject* obj_);//return true if no errors