Fixed bug in HMS module

This commit is contained in:
Martin Ziegler
2025-12-04 08:18:26 +01:00
parent 3917f0a3d1
commit dd02acd97a
8 changed files with 443 additions and 410 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ async def get_printer_status(printer_id: int, db: AsyncSession = Depends(get_db)
# Convert HMS errors to response format
hms_errors = [
HMSErrorResponse(code=e.code, module=e.module, severity=e.severity)
HMSErrorResponse(code=e.code, attr=e.attr, module=e.module, severity=e.severity)
for e in (state.hms_errors or [])
]
+1
View File
@@ -39,6 +39,7 @@ class PrinterResponse(PrinterBase):
class HMSErrorResponse(BaseModel):
code: str
attr: int = 0 # Attribute value for constructing wiki URL
module: int
severity: int # 1=fatal, 2=serious, 3=common, 4=info
+17 -15
View File
@@ -26,6 +26,7 @@ class MQTTLogEntry:
class HMSError:
"""Health Management System error from printer."""
code: str
attr: int # Attribute value for constructing wiki URL
module: int
severity: int # 1=fatal, 2=serious, 3=common, 4=info
message: str = ""
@@ -967,23 +968,24 @@ class BambuMQTTClient:
if isinstance(hms_list, list):
for hms in hms_list:
if isinstance(hms, dict):
# HMS format: {"attr": code, "code": full_code}
# The code is a hex string, severity is in bits
code = hms.get("code", hms.get("attr", "0"))
if isinstance(code, int):
code = hex(code)
# Parse severity from code (typically last 4 bits indicate level)
try:
code_int = int(str(code).replace("0x", ""), 16) if code else 0
severity = (code_int >> 16) & 0xF # Extract severity bits
module = (code_int >> 24) & 0xFF # Extract module bits
except (ValueError, TypeError):
severity = 3
module = 0
# HMS format: {"attr": attribute_code, "code": error_code}
# attr contains module/severity info, code contains error number
# Both are needed to construct the wiki URL
attr = hms.get("attr", 0)
code = hms.get("code", 0)
if isinstance(attr, str):
attr = int(attr.replace("0x", ""), 16) if attr else 0
if isinstance(code, str):
code = int(code.replace("0x", ""), 16) if code else 0
# Severity is in attr byte 1 (bits 8-15)
severity = (attr >> 8) & 0xF
# Module is in attr byte 3 (bits 24-31)
module = (attr >> 24) & 0xFF
self.state.hms_errors.append(HMSError(
code=str(code),
code=f"0x{code:x}" if code else "0x0",
attr=attr,
module=module,
severity=severity if severity > 0 else 3,
severity=severity if severity > 0 else 2,
))
# Parse SD card status
+1 -1
View File
@@ -280,7 +280,7 @@ def printer_state_to_dict(state: PrinterState, printer_id: int | None = None) ->
"total_layers": state.total_layers,
"temperatures": state.temperatures,
"hms_errors": [
{"code": e.code, "module": e.module, "severity": e.severity}
{"code": e.code, "attr": e.attr, "module": e.module, "severity": e.severity}
for e in (state.hms_errors or [])
],
}
+1
View File
@@ -37,6 +37,7 @@ export interface Printer {
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
}
+54 -25
View File
@@ -1,3 +1,4 @@
// HMS Error Modal - Updated Dec 4 2025 for attr field support
import { useEffect } from 'react';
import { X, AlertTriangle, AlertCircle, Info, ExternalLink } from 'lucide-react';
import type { HMSError } from '../api/client';
@@ -8,20 +9,25 @@ interface HMSErrorModalProps {
onClose: () => void;
}
// HMS error code descriptions (common ones)
// HMS error code descriptions keyed by full HMS code (attr + code combined)
// Format: "AAAA_BBBB_CCCC_DDDD" where AAAA_BBBB is from attr, CCCC_DDDD is from code
const HMS_DESCRIPTIONS: Record<string, string> = {
'0x20054': 'The heatbed temperature is abnormal. The sensor may be disconnected or damaged.',
'0x50005': 'Motor driver overheated. Let the printer cool down.',
'0x50006': 'Motor driver communication error.',
'0x70001': 'AMS communication error.',
'0x70002': 'AMS filament runout.',
'0x70003': 'AMS filament not detected.',
'0xC0003': 'First layer inspection failed.',
'0xC0004': 'Nozzle clog detected.',
'0xC8000': 'Foreign object detected on print bed.',
'0x50000': 'Motor X axis lost steps.',
'0x50001': 'Motor Y axis lost steps.',
'0x50002': 'Motor Z axis lost steps.',
// H2D specific errors
'0700_5500_0002_0001': 'A binding error occurred between AMS and the extruder. Please perform AMS initialization again.',
'0500_0300_0002_000E': 'Some modules are incompatible with the printer firmware version. Please update firmware.',
// Common errors
'0300_0100_0002_0054': 'The heatbed temperature is abnormal. The sensor may be disconnected or damaged.',
'0500_0100_0005_0005': 'Motor driver overheated. Let the printer cool down.',
'0500_0100_0005_0006': 'Motor driver communication error.',
'0700_0100_0007_0001': 'AMS communication error.',
'0700_0100_0007_0002': 'AMS filament runout.',
'0700_0100_0007_0003': 'AMS filament not detected.',
'0C00_0100_000C_0003': 'First layer inspection failed.',
'0C00_0100_000C_0004': 'Nozzle clog detected.',
'0C00_0100_000C_8000': 'Foreign object detected on print bed.',
'0500_0100_0005_0000': 'Motor X axis lost steps.',
'0500_0100_0005_0001': 'Motor Y axis lost steps.',
'0500_0100_0005_0002': 'Motor Z axis lost steps.',
};
function getSeverityInfo(severity: number): { label: string; color: string; bgColor: string; Icon: typeof AlertTriangle } {
@@ -38,18 +44,38 @@ function getSeverityInfo(severity: number): { label: string; color: string; bgCo
}
}
function getHMSWikiUrl(code: string): string {
// Convert hex code to format used by Bambu Lab wiki
// Example: 0x20054 -> HMS_0200_0005_0004
const codeNum = parseInt(code.replace('0x', ''), 16);
const part1 = ((codeNum >> 24) & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const part2 = ((codeNum >> 16) & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const part3 = ((codeNum >> 8) & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const part4 = (codeNum & 0xFF).toString(16).padStart(2, '0').toUpperCase();
return `https://wiki.bambulab.com/en/x1/troubleshooting/hmscode/HMS_${part1}${part2}_${part3}${part4}`;
function getFullHMSCode(attr: number, code: number): string {
// Construct the full HMS code from attr and code
// Format: AAAA_BBBB_CCCC_DDDD
// AAAA_BBBB from attr, CCCC_DDDD from code
const a1 = ((attr >> 24) & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const a2 = ((attr >> 16) & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const a3 = ((attr >> 8) & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const a4 = (attr & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const c1 = ((code >> 24) & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const c2 = ((code >> 16) & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const c3 = ((code >> 8) & 0xFF).toString(16).padStart(2, '0').toUpperCase();
const c4 = (code & 0xFF).toString(16).padStart(2, '0').toUpperCase();
return `${a1}${a2}_${a3}${a4}_${c1}${c2}_${c3}${c4}`;
}
function getHMSWikiUrl(attr: number, code: number, printerName: string): string {
// Construct wiki URL from attr and code
const fullCode = getFullHMSCode(attr, code);
// Use H2 wiki path for H2D printers, otherwise use X1 path
const isH2 = printerName.toLowerCase().includes('h2');
const basePath = isH2 ? 'h2' : 'x1';
return `https://wiki.bambulab.com/en/${basePath}/troubleshooting/hmscode/${fullCode}`;
}
export function HMSErrorModal({ printerName, errors, onClose }: HMSErrorModalProps) {
// Debug: log errors to see what data we're receiving
console.log('HMSErrorModal errors:', JSON.stringify(errors, null, 2));
// Close on Escape key
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
@@ -87,8 +113,11 @@ export function HMSErrorModal({ printerName, errors, onClose }: HMSErrorModalPro
<div className="space-y-3">
{errors.map((error, index) => {
const { label, color, bgColor, Icon } = getSeverityInfo(error.severity);
const description = HMS_DESCRIPTIONS[error.code] || 'Unknown error. Click the link below for details.';
const wikiUrl = getHMSWikiUrl(error.code);
const codeNum = parseInt(error.code.replace('0x', ''), 16) || 0;
const fullHMSCode = getFullHMSCode(error.attr, codeNum);
const description = HMS_DESCRIPTIONS[fullHMSCode] || 'Unknown error. Click the link below for details.';
const wikiUrl = getHMSWikiUrl(error.attr, codeNum, printerName);
const displayCode = `HMS_${fullHMSCode.replace(/_/g, '-')}`;
return (
<div
@@ -99,7 +128,7 @@ export function HMSErrorModal({ printerName, errors, onClose }: HMSErrorModalPro
<Icon className={`w-5 h-5 ${color} flex-shrink-0 mt-0.5`} />
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1">
<span className={`font-mono text-sm ${color}`}>{error.code}</span>
<span className={`font-mono text-sm ${color}`}>{displayCode}</span>
<span className={`text-xs px-2 py-0.5 rounded-full ${bgColor} ${color}`}>
{label}
</span>
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -7,7 +7,7 @@
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png" />
<script type="module" crossorigin src="/assets/index-KY24LvJj.js"></script>
<script type="module" crossorigin src="/assets/index-06aT7AZk.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BAV1KG6Z.css">
</head>
<body>