Show Bambu's own HMS descriptions and the real alert level (issue #2728)

Document HMS levels, Bambu's descriptions and uncounted faults (issue #2728)
This commit is contained in:
maziggy
2026-09-28 13:57:02 +02:00
parent 6e113036c2
commit 033eff1254
34 changed files with 8877 additions and 2066 deletions
@@ -6,30 +6,42 @@ import { describe, it, expect, vi, afterEach } from 'vitest';
import { screen, fireEvent, cleanup, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render } from '../utils';
import { HMSErrorModal, filterKnownHMSErrors } from '../../components/HMSErrorModal';
import {
HMSErrorModal,
filterKnownHMSErrors,
filterUncountedHMSErrors,
isSevereHMSError,
} from '../../components/HMSErrorModal';
import { http, HttpResponse } from 'msw';
import { server } from '../mocks/server';
import type { HMSError } from '../../api/client';
// Error code 0300_400C = "The task was canceled." (known code in the database)
// The backend resolves each fault's text from the catalogue generated out of
// Bambu Studio and sends it as `description` (#2728); the fixtures carry it the
// way the status response does. The frontend has no table of its own.
// 0300_400C, "The task was canceled."
const knownError: HMSError = {
attr: 0x0300,
code: '0x400C',
severity: 2,
severity: 1,
description: 'The task was canceled.',
};
// Error code FFFF_FFFF = unknown (not in the database)
// A code Bambu publishes no text for: description null, no actions.
const unknownError: HMSError = {
attr: 0xFFFF,
code: '0xFFFF',
severity: 1,
description: null,
};
// Error code 0700_8011 = AMS filament runout (#2587).
// 0700_8011, AMS filament runout (#2587).
const runoutError: HMSError = {
attr: 0x0700,
code: '0x8011',
severity: 2,
description: 'AMS filament ran out. Please insert a new filament into the same AMS slot.',
};
describe('HMSErrorModal', () => {
@@ -57,9 +69,11 @@ describe('HMSErrorModal', () => {
expect(screen.getByText('The task was canceled.')).toBeInTheDocument();
});
it('shows no errors message when all errors are unknown', () => {
it('lists a fault without text collapsed instead of hiding it (#2728)', () => {
render(<HMSErrorModal {...defaultProps} errors={[unknownError]} />);
expect(screen.getByText('No errors')).toBeInTheDocument();
expect(screen.queryByText('No errors')).not.toBeInTheDocument();
expect(screen.getByText('Also reported, not counted (1)')).toBeInTheDocument();
expect(screen.getByText('[FFFF-FFFF]')).toBeInTheDocument();
});
it('shows no errors message when errors array is empty', () => {
@@ -79,9 +93,10 @@ describe('HMSErrorModal', () => {
expect(screen.queryByText('Clear Errors')).not.toBeInTheDocument();
});
it('hides clear button when all errors are unknown codes', () => {
it('offers clear when the printer holds only faults without text', () => {
// The printer is still holding them, and clearing is how they go away.
render(<HMSErrorModal {...defaultProps} errors={[unknownError]} />);
expect(screen.queryByText('Clear Errors')).not.toBeInTheDocument();
expect(screen.getByText('Clear Errors')).toBeInTheDocument();
});
it('disables clear button when user lacks permission', () => {
@@ -199,12 +214,15 @@ describe('HMSErrorModal', () => {
code: '0x10007',
severity: 1,
full_code: '0500050000010007',
// Bambu's own text, which says to update Studio or Handy.
description: 'MQTT Command verification failed. Please update Studio (including the network plugin) or Handy.',
};
it('surfaces the error instead of filtering it out', () => {
it('surfaces the error in Bambuddy\'s words, not Bambu\'s', () => {
render(<HMSErrorModal {...defaultProps} errors={[verifyFailedError]} />);
expect(screen.queryByText('No errors')).not.toBeInTheDocument();
expect(screen.getByText(/could not verify it/i)).toBeInTheDocument();
expect(screen.queryByText(/update Studio/i)).not.toBeInTheDocument();
});
it('counts towards the known-error filter', () => {
@@ -233,6 +251,111 @@ describe('HMSErrorModal', () => {
});
});
describe('severity is Bambu\'s alert level (#2728)', () => {
it.each([
[1, 'Error'],
[2, 'Warning'],
[3, 'Notice'],
[0, 'Unknown level'],
[6, 'Unknown level'],
])('labels level %i as %s', (severity, label) => {
render(<HMSErrorModal {...defaultProps} errors={[{ ...knownError, severity }]} />);
expect(screen.getByText(label)).toBeInTheDocument();
});
it('treats stopping and pausing faults as severe, and nothing else', () => {
expect([0, 1, 2, 3, 4, 6].map((severity) => isSevereHMSError({ ...knownError, severity }))).toEqual([
false, true, true, false, false, false,
]);
});
});
describe('what counts (#2728)', () => {
// The reporter's three P2S faults as the backend now sends them. Bambu
// describes the first; it lists the other two with no text.
const p2s: HMSError[] = [
{
attr: 83886848,
code: '0x2000e',
severity: 2,
full_code: '050003000002000E',
description: "Some modules are incompatible with the printer's firmware version.",
},
{ attr: 83887616, code: '0x20070', severity: 2, full_code: '0500060000020070', description: null },
{ attr: 83886592, code: '0x3000a', severity: 3, full_code: '050002000003000A', description: null },
];
it('counts a fault Bambu describes and leaves the others out of the count', () => {
expect(filterKnownHMSErrors(p2s).map((e) => e.full_code)).toEqual(['050003000002000E']);
expect(filterUncountedHMSErrors(p2s).map((e) => e.full_code)).toEqual([
'0500060000020070',
'050002000003000A',
]);
});
it('still counts an actionable fault without text, so its buttons render', () => {
const actionable: HMSError = { ...unknownError, actions: ['IGNORE_RESUME'] };
expect(filterKnownHMSErrors([actionable])).toHaveLength(1);
expect(filterUncountedHMSErrors([actionable])).toHaveLength(0);
});
it('shows every fault the printer holds, counted ones first', () => {
render(<HMSErrorModal {...defaultProps} errors={p2s} />);
expect(screen.getByText('[0500-0300-0002-000E]')).toBeInTheDocument();
expect(screen.getByText(/Some modules are incompatible/)).toBeInTheDocument();
expect(screen.getByText('Also reported, not counted (2)')).toBeInTheDocument();
expect(screen.getByText('[0500-0600-0002-0070]')).toBeInTheDocument();
expect(screen.getByText('[0500-0200-0003-000A]')).toBeInTheDocument();
});
it('does not count an hms[] notice without actions, but lists it with its text', () => {
// 0300-9700-0003-0001: a printer can hold this through a whole print.
const topCover: HMSError = {
attr: 0x03009700,
code: '0x30001',
severity: 3,
full_code: '0300970000030001',
description: 'The top cover is open.',
};
expect(filterKnownHMSErrors([topCover])).toHaveLength(0);
render(<HMSErrorModal {...defaultProps} errors={[topCover]} />);
expect(screen.getByText('Also reported, not counted (1)')).toBeInTheDocument();
expect(screen.getByText('The top cover is open.')).toBeInTheDocument();
});
it('counts an hms[] notice that offers actions', () => {
const notice: HMSError = {
attr: 0x03009700,
code: '0x30001',
severity: 3,
full_code: '0300970000030001',
description: 'The top cover is open.',
actions: ['OK_BUTTON'],
};
expect(filterKnownHMSErrors([notice])).toHaveLength(1);
});
it('still counts a print_error prompt at the notice level', () => {
const prompt: HMSError = {
attr: 0x1880c003,
code: '0xc003',
severity: 3,
full_code: '1880C003',
description: 'Unable to start drying.',
};
expect(filterKnownHMSErrors([prompt])).toHaveLength(1);
});
it('never counts level 0', () => {
expect(filterKnownHMSErrors([{ ...knownError, severity: 0 }])).toHaveLength(0);
});
it('has no collapsed group when everything is described', () => {
render(<HMSErrorModal {...defaultProps} errors={[knownError]} />);
expect(screen.queryByTestId('hms-uncounted')).not.toBeInTheDocument();
});
});
describe('interactions', () => {
it('calls onClose when X button is clicked', async () => {
const user = userEvent.setup();
@@ -11,35 +11,25 @@
* meaning: print ended, plate may need clearing). FAILED-with-HMS still
* counts as a problem because there's a real fault to investigate.
*
* Mirrors the logic at PrintersPage.tsx:917-948 and the classifyPrinterStatus
* helper at PrintersPage.tsx:1028 — kept as inline copies so this test
* doesn't need the helpers to be exported.
* Mirrors the classifyPrinterStatus helper in PrintersPage.tsx as an inline
* copy so this test doesn't need it exported. The HMS filter is the real one:
* a copy of it here once kept the old catalogue rule after the rule changed.
*/
import { describe, it, expect } from 'vitest';
import { filterKnownHMSErrors } from '../../components/HMSErrorModal';
import type { HMSError } from '../../api/client';
type Status = {
connected: boolean;
state: string | null;
hms_errors?: { code: string; attr: number; severity: number; actions?: string[] }[];
hms_errors?: HMSError[];
};
type Bucket = 'printing' | 'paused' | 'finished' | 'idle' | 'offline' | 'error';
const KNOWN_HMS_CODES = new Set(['0300_4057', '0500_4038']);
function filterKnownHMSErrors(errors: Status['hms_errors']): NonNullable<Status['hms_errors']> {
return (errors ?? []).filter((e) => {
const codeNum = parseInt(e.code.replace('0x', ''), 16) || 0;
const module = ((e.attr >> 16) & 0xFFFF).toString(16).padStart(4, '0').toUpperCase();
const code = (codeNum & 0xFFFF).toString(16).padStart(4, '0').toUpperCase();
if (KNOWN_HMS_CODES.has(`${module}_${code}`)) return true;
return (e.actions?.length ?? 0) > 0;
});
}
function classifyPrinterStatus(status: Status | undefined): Bucket {
if (!status?.connected) return 'offline';
const knownHms = filterKnownHMSErrors(status.hms_errors);
const knownHms = filterKnownHMSErrors(status.hms_errors ?? []);
if (knownHms.length > 0) return 'error';
switch (status.state) {
case 'RUNNING': return 'printing';
@@ -64,7 +54,7 @@ describe('FAILED-without-HMS bucketing', () => {
const reallyFailedPrinter: Status = {
connected: true,
state: 'FAILED',
hms_errors: [{ code: '0x4057', attr: 0x0300_0000, severity: 1 }],
hms_errors: [{ code: '0x4057', attr: 0x0300_4057, severity: 1, full_code: '03004057', description: 'Z-axis step loss detected.' }],
};
expect(classifyPrinterStatus(reallyFailedPrinter)).toBe('error');
});
@@ -73,7 +63,8 @@ describe('FAILED-without-HMS bucketing', () => {
const cancelEcho: Status = {
connected: true,
state: 'FAILED',
hms_errors: [{ code: '0x2001b', attr: 0x0C00_0C00, severity: 1 }], // 0C00_001B not in known set
// The H2S post-cancel echo 0C00-0100-0002-001B: Bambu lists it with no text.
hms_errors: [{ code: '0x2001b', attr: 0x0C00_0100, severity: 2, full_code: '0C0001000002001B', description: null }],
};
expect(classifyPrinterStatus(cancelEcho)).toBe('finished');
});
@@ -101,7 +92,7 @@ describe('FAILED-without-HMS bucketing', () => {
const offline: Status = {
connected: false,
state: 'FAILED',
hms_errors: [{ code: '0x4057', attr: 0x0300_0000, severity: 1 }],
hms_errors: [{ code: '0x4057', attr: 0x0300_4057, severity: 1, full_code: '03004057', description: 'Z-axis step loss detected.' }],
};
expect(classifyPrinterStatus(offline)).toBe('offline');
});
+7 -6
View File
@@ -429,7 +429,9 @@ export interface HMSError {
code: string;
attr: number; // Attribute value for constructing wiki URL
module: number;
severity: number; // 1=fatal, 2=serious, 3=common, 4=info
// Bambu's alert level: 1 error (task stopped), 2 warning (task paused),
// 3 notification, 0 invalid (#2728).
severity: number;
actions?: string[]; // List of user-facing action keys (e.g. "CHECK_FILAMENT")
job_id?: string; // Optional job ID for actions that require it (e.g. "CHECK_ASSISTANT")
// Canonical hex identifier the firmware matches against — 8 chars for
@@ -437,11 +439,10 @@ export interface HMSError {
// this back as HmsActionBody.print_error so we don't truncate the 64-bit
// identifier into the silent-rejection short code (#1830).
full_code?: string;
// The backend's resolved catalogue sentence for this fault (#2926). English
// only, and null when the catalogue does not cover the code. Resolved with the
// same lookup order this file's consumers use (full_code, then the G1_G4
// collapse), so it agrees with what HMSErrorModal renders — the modal still
// resolves its own text, and this is here for parity with the API.
// The backend's catalogue sentence for this fault (#2926), from the table
// generated out of Bambu Studio for this printer model (#2728). English only.
// Null when Bambu publishes no text for the code. The frontend has no table of
// its own: this field decides both the text and whether the fault counts.
description?: string | null;
}
File diff suppressed because it is too large Load Diff
+7
View File
@@ -3107,6 +3107,13 @@ export default {
noErrors: 'Keine Fehler',
viewOnWiki: 'Im Bambu Lab Wiki ansehen',
mqttVerifyFailedRemedy: 'Aktiviere den Entwicklermodus am Drucker, starte den Drucker neu und starte den Auftrag dann erneut.',
mqttVerifyFailedDescription: "Der Drucker hat einen Befehl abgelehnt, weil er ihn nicht verifizieren konnte. Drucke, Temperaturänderungen und Filamentladevorgänge von Bambuddy werden ignoriert, bis das behoben ist.",
severityError: "Fehler",
severityWarning: "Warnung",
severityNotice: "Hinweis",
severityUnknown: "Unbekannte Stufe",
uncountedSummary: "Außerdem gemeldet, nicht gezählt ({{n}})",
uncountedHint: "Hinweise, die kein Eingreifen brauchen, und Codes, zu denen Bambu keinen Text veröffentlicht. Sie zählen auf der Druckerkarte nicht als Problem und lösen keine Benachrichtigung aus.",
unknownCode: 'Unbekannter HMS-Code — Details siehe Bambu Lab Wiki.',
clearInstructions: 'Löschen Sie die Fehler am Drucker, um sie hier zu entfernen.',
clearErrors: 'Fehler löschen',
+7
View File
@@ -3137,6 +3137,13 @@ export default {
noErrors: 'No errors',
viewOnWiki: 'View on Bambu Lab Wiki',
mqttVerifyFailedRemedy: 'Enable Developer Mode on the printer, restart the printer, then start the job again.',
mqttVerifyFailedDescription: "The printer rejected a command because it could not verify it. Prints, temperature changes and filament loads sent from Bambuddy will be ignored until this is fixed.",
severityError: "Error",
severityWarning: "Warning",
severityNotice: "Notice",
severityUnknown: "Unknown level",
uncountedSummary: "Also reported, not counted ({{n}})",
uncountedHint: "Notices that don't need you, and codes Bambu publishes no text for. They don't count as problems on the printer card and don't send notifications.",
unknownCode: 'Unknown HMS code — see the Bambu Lab wiki for details.',
clearInstructions: 'Clear errors on the printer to dismiss them here.',
clearErrors: 'Clear Errors',
+7
View File
@@ -3109,6 +3109,13 @@ export default {
noErrors: 'No hay errores',
viewOnWiki: 'Ver en la wiki de Bambu Lab',
mqttVerifyFailedRemedy: 'Activa el modo desarrollador en la impresora, reinicia la impresora y vuelve a iniciar el trabajo.',
mqttVerifyFailedDescription: "La impresora rechazó un comando porque no pudo verificarlo. Las impresiones, los cambios de temperatura y las cargas de filamento enviados desde Bambuddy se ignorarán hasta que se solucione.",
severityError: "Fallo",
severityWarning: "Advertencia",
severityNotice: "Aviso",
severityUnknown: "Nivel desconocido",
uncountedSummary: "También notificados, sin contar ({{n}})",
uncountedHint: "Avisos que no requieren tu intervención y códigos para los que Bambu no publica texto. No cuentan como problemas en la tarjeta de la impresora ni envían notificaciones.",
unknownCode: 'Código HMS desconocido — consulta la wiki de Bambu Lab para más detalles.',
clearInstructions: 'Borre los errores en la impresora para descartarlos aquí.',
clearErrors: 'Borrar errores',
+7
View File
@@ -3096,6 +3096,13 @@ export default {
noErrors: 'Aucune erreur',
viewOnWiki: 'Voir sur le Wiki Bambu Lab',
mqttVerifyFailedRemedy: "Activez le mode developpeur sur l'imprimante, redemarrez l'imprimante, puis relancez la tache.",
mqttVerifyFailedDescription: "L'imprimante a refusé une commande parce qu'elle n'a pas pu la vérifier. Les impressions, changements de température et chargements de filament envoyés depuis Bambuddy seront ignorés tant que ce n'est pas corrigé.",
severityError: "Erreur",
severityWarning: "Avertissement",
severityNotice: "Avis",
severityUnknown: "Niveau inconnu",
uncountedSummary: "Également signalés, non comptés ({{n}})",
uncountedHint: "Avis qui ne demandent aucune action, et codes pour lesquels Bambu ne publie aucun texte. Ils ne comptent pas comme problèmes sur la carte de l'imprimante et n'envoient pas de notification.",
unknownCode: 'Code HMS inconnu — consultez le wiki Bambu Lab pour plus de détails.',
clearInstructions: 'Effacez les erreurs sur l\'imprimante pour les retirer ici.',
clearErrors: 'Effacer les erreurs',
+7
View File
@@ -3095,6 +3095,13 @@ export default {
noErrors: 'Nessun errore',
viewOnWiki: 'Vedi su Bambu Lab Wiki',
mqttVerifyFailedRemedy: 'Attiva la modalita sviluppatore sulla stampante, riavvia la stampante e avvia di nuovo il lavoro.',
mqttVerifyFailedDescription: "La stampante ha rifiutato un comando perché non è riuscita a verificarlo. Stampe, cambi di temperatura e caricamenti di filamento inviati da Bambuddy verranno ignorati finché non viene risolto.",
severityError: "Errore",
severityWarning: "Avviso",
severityNotice: "Notifica",
severityUnknown: "Livello sconosciuto",
uncountedSummary: "Segnalati anche, non conteggiati ({{n}})",
uncountedHint: "Notifiche che non richiedono interventi e codici per cui Bambu non pubblica testo. Non contano come problemi nella scheda della stampante e non inviano notifiche.",
unknownCode: 'Codice HMS sconosciuto — consulta la wiki di Bambu Lab per i dettagli.',
clearInstructions: 'Cancella gli errori sulla stampante per rimuoverli qui.',
clearErrors: 'Cancella errori',
+7
View File
@@ -3107,6 +3107,13 @@ export default {
noErrors: 'エラーなし',
viewOnWiki: 'Bambu Lab Wikiで表示',
mqttVerifyFailedRemedy: 'プリンターで開発者モードを有効にし、プリンターを再起動してから、ジョブをもう一度開始してください。',
mqttVerifyFailedDescription: "プリンターがコマンドを検証できなかったため拒否しました。これが解決されるまで、Bambuddy から送信された印刷、温度変更、フィラメントのロードは無視されます。",
severityError: "エラー",
severityWarning: "警告",
severityNotice: "通知",
severityUnknown: "不明なレベル",
uncountedSummary: "報告済み・カウント対象外({{n}})",
uncountedHint: "対応不要のお知らせと、Bambu が説明文を公開していないコードです。プリンターカードでは問題として数えられず、通知も送信されません。",
unknownCode: '不明なHMSコード — 詳細はBambu Lab Wikiを参照してください。',
clearInstructions: 'プリンターでエラーをクリアするとここからも消えます。',
clearErrors: 'エラーをクリア',
+7
View File
@@ -2955,6 +2955,13 @@ export default {
noErrors: '오류 없음',
viewOnWiki: 'Bambu Lab 위키에서 보기',
mqttVerifyFailedRemedy: '프린터에서 개발자 모드를 활성화하고 프린터를 재시작한 다음 작업을 다시 시작하세요.',
mqttVerifyFailedDescription: "프린터가 명령을 확인할 수 없어 거부했습니다. 이 문제가 해결될 때까지 Bambuddy에서 보낸 출력, 온도 변경, 필라멘트 로드는 무시됩니다.",
severityError: "오류",
severityWarning: "경고",
severityNotice: "알림",
severityUnknown: "알 수 없는 수준",
uncountedSummary: "보고됨, 집계 제외 ({{n}})",
uncountedHint: "조치가 필요 없는 알림과 Bambu가 설명을 공개하지 않은 코드입니다. 프린터 카드에서 문제로 집계되지 않으며 알림도 보내지 않습니다.",
unknownCode: '알 수 없는 HMS 코드 — 자세한 내용은 Bambu Lab 위키를 참조하세요.',
clearInstructions: '오류를 해제하려면 프린터에서 오류를 지우세요.',
clearErrors: '오류 지우기',
+7
View File
@@ -3137,6 +3137,13 @@ export default {
noErrors: 'Geen fouten',
viewOnWiki: 'Bekijken op Bambu Lab Wiki',
mqttVerifyFailedRemedy: 'Schakel Developer Mode op de printer in, start de printer opnieuw en start daarna de taak opnieuw.',
mqttVerifyFailedDescription: "De printer heeft een opdracht geweigerd omdat hij die niet kon verifiëren. Prints, temperatuurwijzigingen en filamentladingen vanuit Bambuddy worden genegeerd totdat dit is opgelost.",
severityError: "Fout",
severityWarning: "Waarschuwing",
severityNotice: "Melding",
severityUnknown: "Onbekend niveau",
uncountedSummary: "Ook gemeld, niet meegeteld ({{n}})",
uncountedHint: "Meldingen die geen actie vragen, en codes waarvoor Bambu geen tekst publiceert. Ze tellen op de printerkaart niet als probleem en sturen geen melding.",
unknownCode: 'Onbekende HMS-code — zie de Bambu Lab-wiki voor details.',
clearInstructions: 'Wis fouten op de printer om ze hier te verwijderen.',
clearErrors: 'Fouten wissen',
+7
View File
@@ -3095,6 +3095,13 @@ export default {
noErrors: 'Nenhum erro',
viewOnWiki: 'Ver no Bambu Lab Wiki',
mqttVerifyFailedRemedy: 'Ative o Modo Desenvolvedor na impressora, reinicie a impressora e inicie o trabalho novamente.',
mqttVerifyFailedDescription: "A impressora rejeitou um comando porque não conseguiu verificá-lo. Impressões, mudanças de temperatura e carregamentos de filamento enviados pelo Bambuddy serão ignorados até que isso seja corrigido.",
severityError: "Erro",
severityWarning: "Aviso",
severityNotice: "Notificação",
severityUnknown: "Nível desconhecido",
uncountedSummary: "Também relatados, não contados ({{n}})",
uncountedHint: "Avisos que não exigem ação e códigos para os quais a Bambu não publica texto. Eles não contam como problemas no cartão da impressora e não enviam notificações.",
unknownCode: 'Código HMS desconhecido — consulte o wiki da Bambu Lab para mais detalhes.',
clearInstructions: 'Limpe os erros na impressora para descartá-los aqui.',
clearErrors: 'Limpar Erros',
+7
View File
@@ -2947,6 +2947,13 @@ export default {
noErrors: "Ошибок нет",
viewOnWiki: "Открыть в Bambu Lab Wiki",
mqttVerifyFailedRemedy: "Включите режим разработчика на принтере, перезагрузите принтер и запустите задание снова.",
mqttVerifyFailedDescription: "Принтер отклонил команду, потому что не смог её проверить. Печать, изменение температуры и загрузка филамента из Bambuddy будут игнорироваться, пока это не исправлено.",
severityError: "Ошибка",
severityWarning: "Предупреждение",
severityNotice: "Уведомление",
severityUnknown: "Неизвестный уровень",
uncountedSummary: "Также сообщено, не учитывается ({{n}})",
uncountedHint: "Уведомления, не требующие действий, и коды, для которых Bambu не публикует текст. Они не считаются проблемами в карточке принтера и не отправляют оповещения.",
unknownCode: "Неизвестный код HMS — подробности см. в Bambu Lab Wiki.",
clearInstructions: "Устраните ошибки на принтере, чтобы они исчезли из этого списка.",
clearErrors: "Очистить ошибки",
+7
View File
@@ -3137,6 +3137,13 @@ errors: {
noErrors: 'Inga fel',
viewOnWiki: 'Visa på Bambu Lab Wiki',
mqttVerifyFailedRemedy: 'Aktivera utvecklarläge på skrivaren, starta om skrivaren och starta sedan jobbet igen.',
mqttVerifyFailedDescription: "Skrivaren avvisade ett kommando eftersom den inte kunde verifiera det. Utskrifter, temperaturändringar och filamentladdningar från Bambuddy ignoreras tills detta är åtgärdat.",
severityError: "Fel",
severityWarning: "Varning",
severityNotice: "Meddelande",
severityUnknown: "Okänd nivå",
uncountedSummary: "Även rapporterade, räknas inte ({{n}})",
uncountedHint: "Meddelanden som inte kräver någon åtgärd, och koder som Bambu inte publicerar någon text för. De räknas inte som problem på skrivarkortet och skickar inga aviseringar.",
unknownCode: 'Okänd HMS-kod — se Bambu Lab wiki för detaljer.',
clearInstructions: 'Rensa fel på skrivaren för att avfärda dem här.',
clearErrors: 'Rensa fel',
+7
View File
@@ -3110,6 +3110,13 @@ export default {
noErrors: 'Hata yok',
viewOnWiki: 'Bambu Lab Wiki\'de görüntüle',
mqttVerifyFailedRemedy: 'Yazicida Gelistirici Modunu etkinlestirin, yaziciyi yeniden baslatin ve isi tekrar baslatin.',
mqttVerifyFailedDescription: "Yazıcı bir komutu doğrulayamadığı için reddetti. Bu düzeltilene kadar Bambuddy'den gönderilen baskılar, sıcaklık değişiklikleri ve filament yüklemeleri yok sayılacak.",
severityError: "Hata",
severityWarning: "Uyarı",
severityNotice: "Bildirim",
severityUnknown: "Bilinmeyen seviye",
uncountedSummary: "Ayrıca bildirildi, sayılmadı ({{n}})",
uncountedHint: "İşlem gerektirmeyen bildirimler ve Bambu'nun metin yayınlamadığı kodlar. Yazıcı kartında sorun olarak sayılmazlar ve bildirim göndermezler.",
unknownCode: 'Bilinmeyen HMS kodu — ayrıntılar için Bambu Lab wiki sayfasına bakın.',
clearInstructions: 'Buradan kapatmak için yazıcıdaki hataları temizleyin.',
clearErrors: 'Hataları Temizle',
+7
View File
@@ -3135,6 +3135,13 @@ export default {
noErrors: "Помилок немає",
viewOnWiki: "Переглянути на Bambu Lab Wiki",
mqttVerifyFailedRemedy: "Увімкніть режим розробника на принтері, перезавантажте принтер і запустіть завдання знову.",
mqttVerifyFailedDescription: "Принтер відхилив команду, бо не зміг її перевірити. Друк, зміни температури та завантаження філаменту з Bambuddy ігноруватимуться, доки це не буде виправлено.",
severityError: "Помилка",
severityWarning: "Попередження",
severityNotice: "Сповіщення",
severityUnknown: "Невідомий рівень",
uncountedSummary: "Також повідомлено, не враховано ({{n}})",
uncountedHint: "Сповіщення, що не потребують дій, і коди, для яких Bambu не публікує текст. Вони не рахуються як проблеми на картці принтера і не надсилають сповіщень.",
unknownCode: "Невідомий код HMS — подробиці дивіться у вікі Bambu Lab.",
clearInstructions: "Усуньте помилки на принтері, щоб вони зникли тут.",
clearErrors: "Очистити помилки",
+7
View File
@@ -3095,6 +3095,13 @@ export default {
noErrors: '无错误',
viewOnWiki: '在拓竹 Wiki 上查看',
mqttVerifyFailedRemedy: '在打印机上启用开发者模式,重启打印机,然后重新开始该任务。',
mqttVerifyFailedDescription: "打印机无法验证某条命令,因此拒绝了它。在此问题解决之前,从 Bambuddy 发送的打印、温度调整和耗材加载都会被忽略。",
severityError: "错误",
severityWarning: "警告",
severityNotice: "通知",
severityUnknown: "未知级别",
uncountedSummary: "另有未计入的代码({{n}})",
uncountedHint: "无需处理的通知,以及 Bambu 未公布说明文字的代码。它们不会在打印机卡片上计为问题,也不会发送通知。",
unknownCode: '未知 HMS 代码 — 详情请参阅拓竹 Wiki。',
clearInstructions: '在打印机上清除错误以在此处消除它们。',
clearErrors: '清除错误',
+7
View File
@@ -3095,6 +3095,13 @@ export default {
noErrors: '無錯誤',
viewOnWiki: '在拓竹 Wiki 上檢視',
mqttVerifyFailedRemedy: '在印表機上啟用開發者模式,重新啟動印表機,然後重新開始該工作。',
mqttVerifyFailedDescription: "印表機無法驗證某條指令,因此拒絕了它。在此問題解決之前,從 Bambuddy 傳送的列印、溫度調整和線材載入都會被忽略。",
severityError: "錯誤",
severityWarning: "警告",
severityNotice: "通知",
severityUnknown: "未知等級",
uncountedSummary: "另有未計入的代碼({{n}})",
uncountedHint: "無需處理的通知,以及 Bambu 未公布說明文字的代碼。它們不會在印表機卡片上計為問題,也不會傳送通知。",
unknownCode: '未知 HMS 代碼 — 詳情請參閱拓竹 Wiki。',
clearInstructions: '在印表機上清除錯誤以在此處消除它們。',
clearErrors: '清除錯誤',
+3 -3
View File
@@ -173,7 +173,7 @@ import { EmbeddedCameraViewer } from '../components/EmbeddedCameraViewer';
import { CameraWall } from '../components/CameraWall';
import { ContextMenu, type ContextMenuItem } from '../components/ContextMenu';
import { MQTTDebugModal } from '../components/MQTTDebugModal';
import { HMSErrorModal, filterKnownHMSErrors } from '../components/HMSErrorModal';
import { HMSErrorModal, filterKnownHMSErrors, isSevereHMSError } from '../components/HMSErrorModal';
import { AiDetectionModal } from '../components/AiDetectionModal';
import { aiDetectionClass, type AiDetection } from '../utils/aiDetection';
import { PrinterQueueWidget } from '../components/PrinterQueueWidget';
@@ -3978,7 +3978,7 @@ function PrinterCard({
{/* Connection indicator dot for compact mode */}
{viewMode === 'compact' && (() => {
const hmsErrors = status?.connected && status.hms_errors ? filterKnownHMSErrors(status.hms_errors) : [];
const hasSevere = hmsErrors.some(e => e.severity <= 2);
const hasSevere = hmsErrors.some(isSevereHMSError);
const hasWarning = hmsErrors.length > 0;
const pipColor = !status?.connected
? 'bg-status-error'
@@ -4124,7 +4124,7 @@ function PrinterCard({
onClick={() => setShowHMSModal(true)}
className={`flex items-center gap-1 px-2 py-1 rounded-full text-xs cursor-pointer hover:opacity-80 transition-opacity ${
knownErrors.length > 0
? knownErrors.some(e => e.severity <= 2)
? knownErrors.some(isSevereHMSError)
? 'bg-status-error/20 text-status-error'
: 'bg-status-warning/20 text-status-warning'
: 'bg-status-ok/20 text-status-ok'