Fix current gen Qidi printer AMS sync (#16679)

Newer Qidi firmware for the Q2, Q2C, Plus 5 and Max 4 stores a slot's color as a hex list and its filament as a material id, and filament sync crashed on it. Each slot is now read in either form, the filament type comes from the box object, and any other JSON type error fails the sync instead of closing Orca.
This commit is contained in:
TheLegendTubaGuy authored and GitHub committed 2026-10-20 19:16:54 -05:00
1 parent 25fd549d17
commit 07da005fab
1 file changed
+25 -6
+25 -6
View File
@@ -73,7 +73,14 @@ bool QidiPrinterAgent::fetch_filament_info(std::string dev_id, FilamentSyncMode
// 3. Fetch slot info and build AmsTrayData directly
std::vector<AmsTrayData> trays;
int box_count = 0;
if (!fetch_slot_info(device_info.base_url, device_info.api_key, dict, series_id, trays, box_count, error)) {
bool slots_ok = false;
try {
slots_ok = fetch_slot_info(device_info.base_url, device_info.api_key, dict, series_id, trays, box_count, error);
} catch (const nlohmann::json::exception& e) {
// A slot value of an unexpected type fails the sync instead of escaping to the UI
error = e.what();
}
if (!slots_ok) {
BOOST_LOG_TRIVIAL(warning) << "QidiPrinterAgent::fetch_filament_info: Failed to fetch slot info: " << error;
return false;
}
@@ -91,7 +98,7 @@ bool QidiPrinterAgent::fetch_slot_info(const std::string& base_url,
int& box_count,
std::string& error)
{
std::string url = join_url(base_url, "/printer/objects/query?save_variables=variables");
std::string url = join_url(base_url, "/printer/objects/query?save_variables=variables&multi_color_controller=box");
for (int i = 0; i < 16; ++i) {
url += "&box_stepper%20slot" + std::to_string(i) + "=runout_button";
}
@@ -164,9 +171,12 @@ bool QidiPrinterAgent::fetch_slot_info(const std::string& base_url,
AmsTrayData tray;
tray.slot_index = i;
// Read slot variables
const int color_index = variables.value("color_slot" + std::to_string(i), 1);
const int filament_type = variables.value("filament_slot" + std::to_string(i), 1);
// Read slot variables. Newer firmware stores a hex color list and a material id instead of dictionary
// indexes, and only in the slots it has rewritten, so each slot is checked for both forms.
const auto color_value = variables.value("color_slot" + std::to_string(i), nlohmann::json(1));
const auto filament_value = variables.value("filament_slot" + std::to_string(i), nlohmann::json(1));
const int color_index = color_value.is_number() ? color_value.get<int>() : 0;
const int filament_type = filament_value.is_number() ? filament_value.get<int>() : 0;
const int vendor_type = variables.value("vendor_slot" + std::to_string(i), 0);
// Check filament presence via runout sensor
@@ -187,6 +197,13 @@ bool QidiPrinterAgent::fetch_slot_info(const std::string& base_url,
if (filament_it != dict.filaments.end()) {
filament_name = filament_it->second;
}
if (filament_value.is_string()) {
const nlohmann::json::json_pointer decoded_type("/multi_color_controller/box/box" + std::to_string(i / 4) +
"_filament_info_" + std::to_string(i % 4) + "_filament_type");
if (status.contains(decoded_type) && status[decoded_type].is_string()) {
filament_name = status[decoded_type].get<std::string>();
}
}
tray.tray_type = normalize_filament_type(filament_name);
// Try Qidi-specific setting ID first; fall back to visible preset by type
@@ -202,7 +219,9 @@ bool QidiPrinterAgent::fetch_slot_info(const std::string& base_url,
// Look up color from dictionary
auto color_it = dict.colors.find(color_index);
if (color_it != dict.colors.end()) {
if (color_value.is_array() && !color_value.empty() && color_value[0].is_string()) {
tray.tray_color = color_value[0].get<std::string>();
} else if (color_it != dict.colors.end()) {
tray.tray_color = color_it->second;
} else {
tray.tray_color = "FFFFFFFF";