Fix AMS-HT mapping for left nozzle on H2D Pro (#318)

AMS-HT global tray ID was calculated as ams_id * 4 (= 512 for unit 128)
but AMS-HT uses the raw ams_id directly since it has a single tray.
The backend misidentified 512 as an external spool, producing wrong
ams_mapping2. Fixed in 4 locations: frontend getGlobalTrayId(), backend
start_print() ams_mapping2 builder, print scheduler, and Spoolman tracking.
This commit is contained in:
maziggy
2026-02-10 13:54:21 +01:00
parent 94ba65e3bc
commit c5fff9bc15
7 changed files with 14 additions and 6 deletions
+1
View File
@@ -45,6 +45,7 @@ All notable changes to Bambuddy will be documented in this file.
- **GitHub Backup Description Misleading** — The "App Settings" backup card said "excludes sensitive data" but the complete database is pushed. Updated description to "complete database."
- **Support Bundle Shows 0 AMS Units** — The support info always reported `ams_unit_count: 0` because it expected `raw_data["ams"]` to be a nested dict (`{"ams": [...]}`) but the MQTT handler stores it as a flat list. Now handles both formats.
- **Firmware Badge Shown for Models Without API Data** ([#311](https://github.com/maziggy/bambuddy/issues/311)) — Printers whose model has no firmware data in Bambu Lab's API (e.g. H2C on public beta firmware) showed a misleading green "up to date" badge. The badge is now hidden when the API returns no `latest_version`, since there is nothing to compare against.
- **AMS-HT Mapping Fails for Left Nozzle on H2D Pro** ([#318](https://github.com/maziggy/bambuddy/issues/318)) — Printing with the left nozzle on dual-nozzle printers (H2D/H2D Pro) using AMS-HT failed with "Failed to get AMS mapping table." The global tray ID for AMS-HT units (ams_id >= 128) was calculated as `ams_id * 4 + tray_id` (= 512), but AMS-HT uses the raw `ams_id` (128) since it has a single tray. The backend then misidentified 512 as an external spool. Fixed in frontend tray ID calculation, backend `ams_mapping2` builder, print scheduler, and Spoolman tracking.
### Documentation
- **Supported Printers Updated** — Updated README, website, and wiki to list all 12 supported Bambu Lab printer models: X1, X1C, X1E, P1P, P1S, P2S, A1, A1 Mini, H2D, H2D Pro, H2C, H2S. Removed outdated "Testers Needed" messaging and Tested/Needs Testing distinctions — all models are now uniformly listed as supported. Added H2C printer image to website. Added H2D Pro, H2C columns to wiki feature comparison tables and new P2 Series section.
+3
View File
@@ -2076,6 +2076,9 @@ class BambuMQTTClient:
# For ams_mapping2, slot_id is 0 (main) or 1 (deputy), not the tray_id
external_slot = 0 if tray_id == 254 else 1
ams_mapping2.append({"ams_id": 255, "slot_id": external_slot})
elif tray_id >= 128:
# AMS-HT: global tray ID IS the ams_id (single tray per unit)
ams_mapping2.append({"ams_id": tray_id, "slot_id": 0})
else:
# Regular AMS tray: Global tray ID = (ams_id * 4) + slot_id
ams_id = tray_id // 4
+2 -1
View File
@@ -511,7 +511,8 @@ class PrintScheduler:
# Normalize color: remove alpha, add hash
color = self._normalize_color(tray_color)
# Calculate global tray ID
global_tray_id = ams_id * 4 + tray_id
# AMS-HT units have IDs starting at 128 with a single tray
global_tray_id = ams_id if ams_id >= 128 else ams_id * 4 + tray_id
filaments.append(
{
+2 -1
View File
@@ -58,7 +58,8 @@ def build_ams_tray_lookup(raw_data: dict) -> dict[int, dict]:
ams_id = ams_unit.get("id", 0)
for tray in ams_unit.get("tray", []):
tray_id = tray.get("id", 0)
global_tray_id = ams_id * 4 + tray_id
# AMS-HT units have IDs starting at 128 with a single tray
global_tray_id = ams_id if ams_id >= 128 else ams_id * 4 + tray_id
lookup[global_tray_id] = {
"tray_uuid": tray.get("tray_uuid", ""),
"tag_uid": tray.get("tag_uid", ""),
@@ -129,7 +129,7 @@ class TestBuildLoadedFilaments:
result = scheduler._build_loaded_filaments(MockStatus())
assert len(result) == 1
assert result[0]["is_ht"] is True
assert result[0]["global_tray_id"] == 512 # 128 * 4 + 0
assert result[0]["global_tray_id"] == 128 # AMS-HT uses ams_id directly
def test_build_loaded_filaments_with_external(self, scheduler):
"""Should include external spool."""
@@ -134,7 +134,7 @@ describe('buildLoadedFilaments', () => {
const result = buildLoadedFilaments(status);
expect(result[0].isHt).toBe(true);
expect(result[0].globalTrayId).toBe(512); // 128 * 4 + 0
expect(result[0].globalTrayId).toBe(128); // AMS-HT uses ams_id directly
});
});
+4 -2
View File
@@ -78,10 +78,10 @@ export function formatSlotLabel(
/**
* Calculate global tray ID for MQTT command.
* Used in the ams_mapping array sent to the printer.
* @param amsId - AMS unit ID
* @param amsId - AMS unit ID (0-3 for regular AMS, 128+ for AMS-HT)
* @param trayId - Tray/slot ID within the AMS unit
* @param isExternal - Whether this is the external spool holder
* @returns Global tray ID (0-15 for AMS, 254 for external)
* @returns Global tray ID (0-15 for AMS, 128+ for AMS-HT, 254 for external)
*/
export function getGlobalTrayId(
amsId: number,
@@ -89,6 +89,8 @@ export function getGlobalTrayId(
isExternal: boolean
): number {
if (isExternal) return 254;
// AMS-HT units have IDs starting at 128 with a single tray — use ID directly
if (amsId >= 128) return amsId;
return amsId * 4 + trayId;
}