mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-21 10:15:04 +02:00
fix(queue): enforce sliced-model compatibility on cross-model dispatch (#2578)
A queue item's "Any <model>" button labeled itself from the file's slice metadata while the scheduler used the row's target_model, so an X1C-sliced item targeting H2D showed "Any X1C" above "assign to first idle H2D". The mismatch itself was created silently: sliced-for metadata loads async, and switching to model mode before it arrived pre-selected the alphabetically first model (H2D on a mixed farm), after which the model dropdown hid itself. Nothing validated compatibility, so the scheduler would hand X1C G-code to an H2D. Frontend: never default the target silently, keep the dropdown visible in model mode (incompatible models disabled), label from the actual target, warn on mismatch, block submit when incompatible. Backend: new GCODE_COMPAT_FAMILIES table (X1/X1C/X1E/P1P/P1S interchange; everything else exact-match; missing metadata never blocks). Queue create and update reject incompatible targets with 400; the scheduler holds back pre-existing mismatched rows with an actionable waiting_reason instead of dispatching them.
This commit is contained in:
@@ -18,6 +18,28 @@ export function getPrinterImage(model: string | null | undefined): string {
|
||||
return '/img/printers/default.png';
|
||||
}
|
||||
|
||||
// G-code interchange families (#2578). Mirrors backend GCODE_COMPAT_FAMILIES
|
||||
// in backend/app/utils/printer_models.py — keep the two in sync. A sliced 3MF
|
||||
// may target a different model ONLY within its family; everything else is
|
||||
// exact-match only.
|
||||
const GCODE_COMPAT_FAMILIES: ReadonlyArray<ReadonlySet<string>> = [
|
||||
new Set(['X1', 'X1C', 'X1E', 'P1P', 'P1S']),
|
||||
];
|
||||
|
||||
/** True when G-code sliced for one model may be dispatched to the other.
|
||||
* Unknown/missing metadata on either side returns true (can't validate). */
|
||||
export function isGcodeCompatible(
|
||||
slicedForModel: string | null | undefined,
|
||||
targetModel: string | null | undefined,
|
||||
): boolean {
|
||||
if (!slicedForModel || !targetModel) return true;
|
||||
const norm = (m: string) => m.trim().toUpperCase().replace(/[\s-]/g, '');
|
||||
const a = norm(slicedForModel);
|
||||
const b = norm(targetModel);
|
||||
if (a === b) return true;
|
||||
return GCODE_COMPAT_FAMILIES.some((family) => family.has(a) && family.has(b));
|
||||
}
|
||||
|
||||
export function getWifiStrength(rssi: number): { labelKey: string; color: string; bars: number } {
|
||||
if (rssi >= -50) return { labelKey: 'printers.wifiSignal.excellent', color: 'text-bambu-green', bars: 4 };
|
||||
if (rssi >= -60) return { labelKey: 'printers.wifiSignal.good', color: 'text-bambu-green', bars: 3 };
|
||||
|
||||
Reference in New Issue
Block a user