mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-22 03:49:18 +02:00
fix(spool-assign): defer MQTT for empty AMS slot, replay on physical insert
The SpoolBuddy "weigh-then-assign" workflow tried to configure an empty AMS slot at assign time, but Bambu firmware silently drops ams_filament_setting and extrusion_cali_sel for unloaded slots — the MQTT calls completed and the modal closed, yet BambuStudio kept showing the slot as default-PLA forever. assign_spool now detects an empty target slot (fingerprint_type empty) and persists the SpoolAssignment without publishing MQTT, returning a new pending_config flag so the frontend can swap "Assigned!" for "Slot will configure when you insert the spool." on_ams_change watches for the slot to load (state == 11, which fires for 3rd-party tags too even when tray_type stays empty) and replays the deferred ams_filament_setting + extrusion_cali_sel — including the printer-kp realignment that converts PFUS-prefix cloud user presets to the P-prefix local-preset filament_id the slicer actually accepts. The full assign-time MQTT block was extracted into apply_spool_to_slot_via_mqtt so both the assign endpoint and the on_ams_change replay path use the same resolution logic; the helper takes ~270 lines of duplication out of assign_spool.
This commit is contained in:
@@ -2346,6 +2346,7 @@ export interface SpoolAssignment {
|
||||
fingerprint_type: string | null;
|
||||
spool?: InventorySpool | null;
|
||||
configured: boolean;
|
||||
pending_config?: boolean; // Slot was empty at assign time; will configure on insert
|
||||
created_at: string;
|
||||
ams_label?: string | null; // User-defined friendly name for the AMS unit
|
||||
}
|
||||
|
||||
@@ -167,27 +167,37 @@ export function AssignToAmsModal({ isOpen, onClose, spool, printerId }: AssignTo
|
||||
}, [isDualNozzle, amsExtruderMap]);
|
||||
|
||||
// Assign spool to AMS slot — single API call, backend handles both
|
||||
// DB record AND MQTT auto-configuration (same as SpoolStation).
|
||||
// DB record AND MQTT auto-configuration (same as SpoolStation). When the
|
||||
// target slot is currently empty, the backend persists the assignment and
|
||||
// skips the MQTT publish (firmware drops it anyway); on_ams_change re-fires
|
||||
// the full configuration when filament is later inserted. The response's
|
||||
// `pending_config` flag distinguishes that from the immediate-apply path
|
||||
// so we can adjust the success toast.
|
||||
const configureMutation = useMutation({
|
||||
mutationFn: async ({ amsId, trayId }: { amsId: number; trayId: number }) => {
|
||||
if (!printerId) throw new Error('No printer selected');
|
||||
|
||||
await api.assignSpool({
|
||||
return await api.assignSpool({
|
||||
spool_id: spool.id,
|
||||
printer_id: printerId,
|
||||
ams_id: amsId,
|
||||
tray_id: trayId,
|
||||
});
|
||||
|
||||
// Slot preset mapping is now saved by the backend in assign_spool()
|
||||
// after successful MQTT configuration, using the authoritative
|
||||
// slicer_filament_name from the spool record.
|
||||
},
|
||||
onSuccess: () => {
|
||||
onSuccess: (assignment) => {
|
||||
setStatusType('success');
|
||||
setStatusMessage(t('spoolbuddy.modal.assignSuccess', 'Assigned!'));
|
||||
if (assignment?.pending_config) {
|
||||
setStatusMessage(
|
||||
t(
|
||||
'spoolbuddy.modal.assignPendingInsert',
|
||||
'Assigned. Slot will configure when you insert the spool.',
|
||||
),
|
||||
);
|
||||
} else {
|
||||
setStatusMessage(t('spoolbuddy.modal.assignSuccess', 'Assigned!'));
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ['slotPresets'] });
|
||||
setTimeout(() => onClose(), 1500);
|
||||
setTimeout(() => onClose(), assignment?.pending_config ? 2500 : 1500);
|
||||
},
|
||||
onError: (err) => {
|
||||
setStatusType('error');
|
||||
|
||||
@@ -5032,6 +5032,7 @@ export default {
|
||||
assign: 'Zuweisen',
|
||||
assigning: 'Zuweisen...',
|
||||
assignSuccess: 'Zugewiesen!',
|
||||
assignPendingInsert: 'Zugewiesen. Slot wird beim Einsetzen der Spule konfiguriert.',
|
||||
assignError: 'Fehler beim Zuweisen. Bitte erneut versuchen.',
|
||||
noPrinterSelected: 'Drucker auswählen...',
|
||||
noAmsDetected: 'Kein AMS an diesem Drucker erkannt',
|
||||
|
||||
@@ -5041,6 +5041,7 @@ export default {
|
||||
assign: 'Assign',
|
||||
assigning: 'Assigning...',
|
||||
assignSuccess: 'Assigned!',
|
||||
assignPendingInsert: 'Assigned. Slot will configure when you insert the spool.',
|
||||
assignError: 'Failed to assign spool. Please try again.',
|
||||
noPrinterSelected: 'Select a printer...',
|
||||
noAmsDetected: 'No AMS detected on this printer',
|
||||
|
||||
@@ -5020,6 +5020,7 @@ export default {
|
||||
assign: 'Assigner',
|
||||
assigning: 'Attribution...',
|
||||
assignSuccess: 'Assigné !',
|
||||
assignPendingInsert: 'Assigné. Le slot sera configuré lors de l\'insertion de la bobine.',
|
||||
assignError: 'Échec de l\'attribution de la bobine. Veuillez réessayer.',
|
||||
noPrinterSelected: 'Sélectionner une imprimante...',
|
||||
noAmsDetected: 'Aucun AMS détecté sur cette imprimante',
|
||||
|
||||
@@ -5019,6 +5019,7 @@ export default {
|
||||
assign: 'Assegna',
|
||||
assigning: 'Assegnazione...',
|
||||
assignSuccess: 'Assegnato!',
|
||||
assignPendingInsert: 'Assegnato. Lo slot verrà configurato all\'inserimento della bobina.',
|
||||
assignError: 'Impossibile assegnare la bobina. Riprovare.',
|
||||
noPrinterSelected: 'Seleziona una stampante...',
|
||||
noAmsDetected: 'Nessun AMS rilevato su questa stampante',
|
||||
|
||||
@@ -5032,6 +5032,7 @@ export default {
|
||||
assign: '割り当て',
|
||||
assigning: '割り当て中...',
|
||||
assignSuccess: '割り当て完了!',
|
||||
assignPendingInsert: '割り当てました。スプールを挿入したときにスロットが設定されます。',
|
||||
assignError: 'スプールの割り当てに失敗しました。再試行してください。',
|
||||
noPrinterSelected: 'プリンターを選択...',
|
||||
noAmsDetected: 'このプリンターにAMSが検出されません',
|
||||
|
||||
@@ -5019,6 +5019,7 @@ export default {
|
||||
assign: 'Atribuir',
|
||||
assigning: 'Atribuindo...',
|
||||
assignSuccess: 'Atribuído!',
|
||||
assignPendingInsert: 'Atribuído. O slot será configurado quando você inserir o carretel.',
|
||||
assignError: 'Falha ao atribuir carretel. Tente novamente.',
|
||||
noPrinterSelected: 'Selecionar uma impressora...',
|
||||
noAmsDetected: 'Nenhum AMS detectado nesta impressora',
|
||||
|
||||
@@ -5019,6 +5019,7 @@ export default {
|
||||
assign: '分配',
|
||||
assigning: '分配中...',
|
||||
assignSuccess: '已分配!',
|
||||
assignPendingInsert: '已分配。插入耗材后将配置槽位。',
|
||||
assignError: '分配耗材失败。请重试。',
|
||||
noPrinterSelected: '选择打印机...',
|
||||
noAmsDetected: '此打印机未检测到 AMS',
|
||||
|
||||
@@ -5019,6 +5019,7 @@ export default {
|
||||
assign: '分配',
|
||||
assigning: '分配中...',
|
||||
assignSuccess: '已分配!',
|
||||
assignPendingInsert: '已分配。插入耗材後將設定槽位。',
|
||||
assignError: '分配耗材失敗。請重試。',
|
||||
noPrinterSelected: '選擇印表機...',
|
||||
noAmsDetected: '此印表機未偵測到 AMS',
|
||||
|
||||
Reference in New Issue
Block a user