mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-08 07:01:40 +02:00
dev
10
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
61e2841d16 |
Correct the drying settings path and the print-drying comment (issue #2518)
The changelog named Settings -> Print Queue -> Auto-Drying; the toggle lives in the Queue Auto-Drying card under Settings -> Workflow. The scheduler comment and a test docstring called print_drying a permission overlay rather than a trigger, but since #1816 it starts mid-print cycles on its own regardless of queue state. |
||
|
|
568702486b | feat: Wait for sustained AMS humidity before an ambient auto-dry starts (issue #2518) | ||
|
|
4440738904 |
fix(drying): dry a composite spool as its base material (issue #3067)
The reporter's AMS-HT would not auto-dry PA6-CF, and drying the same spool by hand worked. The scheduler reduced a tray to a preset key by splitting on spaces only, so "PA6-CF" stayed "PA6-CF", matched none of the eight rows the preset table has, and the tray was read as holding nothing worth drying. The AMS was then passed over on every scheduler sweep, silently, because every caller reads "no row" as "nothing to do for this tray". It was never only nylon. Of the 41 types a printer can report, 33 had no row under that rule, and 20 of those have a base material sitting right there: every -CF, -GF and -AERO variant of PLA, PETG, ABS, ASA, PC and PA. Doing it by hand worked because the drying popover has resolved composites since exact key first, so a row the user added for the exact type still wins, then the suffix, then an alias map reading PA6, PA11, PA12, PAHT, PPA and Nylon as PA. PPA is the one alias that is a judgement rather than a spelling. Polyphthalamide is a distinct polymer, not a grade of nylon -- but it is an aromatic polyamide, it takes up moisture the same way, and PA's row is the hottest the table has. A material with no row and no alias is still skipped rather than dried at a number nothing here can source. That is where this parts company with the popover, which falls back to PLA because a dropdown has to show something. The table is user-editable JSON, so a preset row can be present and empty. That has always meant "skip this material" and still does: the temp and hours reads fall back per field to 55C/12h, which would dry a PLA spool at 55 degrees. Two more callers had the same line and move with it: per-filament humidity thresholds, where the override set for a material never applied to that material's composites, and the chamber preheat target, which had the suffix half of this from #2902 but not the aliases. The preheat test for that half reimplemented the lookup inline rather than calling it, so it would have passed whatever the function did. It calls it now. |
||
|
|
71709c16aa |
Stop tearing down AMS drying for a print that cannot start (#2801)
A printer in FINISH with an unacknowledged plate and something pending in its queue stopped and restarted drying once per scheduler tick, for as long as the plate stayed unacknowledged. The reporter's Home Assistant history recorded about 2000 state changes over ten days. No cycle ever ran long enough to remove moisture, and cycles the user had started by hand on other AMS units of the same printer were torn down with it. Two concerns had become tangled. Plate-clear answers "is the bed ready for the next job" and says nothing about whether the AMS may heat. The gap between a finished print and the acknowledgment is when drying is most useful -- the printer is free and nobody is waiting on it -- and leaving the plate unacknowledged is also how people hold the queue by hand, so the hold was costing them the drying it should have enabled. Four faults, all in print_scheduler. The "print takes priority" stop sat inside the not-idle branch. Drying is not one of the things _is_printer_idle looks at, so stopping a cycle can never turn a non-idle printer into an idle one: the stop was futile every time it fired, and never fired on the dispatches where it was supposed to mean something. It now runs when the printer is actually dispatchable, and only where the model cannot dry through a print -- #2758 settled that capable hardware should keep its cycle. mid_print was inferred from busy_printers, which means "the queue could not dispatch here this pass", not "is printing". A plate-held printer was therefore treated as printing: the mid-print spool-protection cap silently lowered its drying temperature, the cycle was logged as (mid-print) in FINISH, and it bypassed the very gate meant to hold it. busy_printers keeps its dispatch role; auto-drying now gets a narrow set snapshotted before the item loop -- running, held post-dispatch, or mid-upload -- and mid_print comes from the printer's own state. The interlock comment at the seed already documented this hazard and worked around it by staying out of the set; this generalises that instead of adding a third special case. The other call site was already passing the narrow set, so the wide one was the inconsistency. _stop_drying sent a stop to every AMS reporting dry_time > 0. One auto-dried unit was enough to kill a manual cycle on a different unit of the same printer, contradicting the contract _sync_drying_state already documents: the entry gate only knows about cycles Bambuddy began, so the action must not reach past them. Consequence worth stating -- after a restart Bambuddy cannot prove a running cycle is its own, so it leaves it alone rather than risk stopping somebody's manual dry. Fourth, and the reason #2770's guard did not catch this: a reading at or below the threshold popped the unit's whole entry, ended_at included, so the 30-minute re-arm cooldown went with it. An AMS reads higher warm than cool, which is #2770's own finding, so a unit a point or two above the threshold dipped below it as it cooled, wiped its history, and re-armed immediately. Lifting a suspension now clears the judgement and keeps the clock. queue_drying_block changes behaviour as a result. It previously had no effect on dispatch at all -- both branches skipped anyway, and it only decided whether drying was needlessly killed. With the stop on the dispatch path it now does what it says: a queued print waits for a running cycle. Off by default. Reported by @superflyer11, who traced both defects to the line and brought ten days of external sensor history to date the cadence. |
||
|
|
328bac450a |
Stop auto-drying re-arming into a threshold it can never reach (#2770)
An H2D armed five 12-hour drying cycles inside four hours, one of them six seconds after the previous one ended, and none ran more than a couple of hours. Two things combine. The firmware ends a cycle when it decides the filament is dry rather than when the clock runs out, and reports no fault doing it -- across this printer's history the run length tracks how wet the spools were, from nearly the full 12 hours starting at 32% down to minutes once the unit sat at 10-13%. That part is the AMS doing its job. The loop is ours. An AMS reports higher relative humidity while it is warm than once it has cooled: the same unit read 10-13% cold and 15-20% through every cycle. With the threshold at 14% the reading at the moment a cycle ended was always still above it, so the next 30-second pass armed another 12-hour cycle. Nothing counted, nothing waited, and it only stopped when the box finally cooled enough to read 13%. Auto-drying now waits 30 minutes after a cycle ends before arming another on the same unit, and gives up on a unit after two consecutive cycles that bring the reading no lower -- logging why and sending a new notification, on by default because it reports that Bambuddy has stopped acting. Progress is judged against the lowest reading any cycle on that unit has ended at, not against the threshold, so a genuinely wet spool in a humid room coming down 40-37-35 keeps drying however far it still is from the target; comparing against the best so far rather than the previous end stops a sensor wobbling by one point reading as progress every other cycle. The suspension lifts by itself once the reading falls below the threshold. Neither guard can stop a running cycle, and a cycle Bambuddy cut short for a print, or that the user stopped by hand, is not counted against the unit -- so a farm that dries between queue jobs is unaffected. The threshold field now warns below 20%, and every cycle end logs the unit's temperature and humidity, which is what made this diagnosable. The same bundle showed unrelated tasks failing with "database is locked", each inside a 30.000-second Discord connect timeout. Alarms are raised from inside the loop that records sensor history, at a point where the new rows are added but not committed; the first read in the notification path flushed them to satisfy itself, opening a write transaction, and the provider was then contacted over the network with that transaction still open. SQLite allows one writer and 30 seconds outlives the 15-second busy timeout, so every other write in that window failed. The two reads that run before a provider is contacted no longer flush the caller's pending work, and the connect timeout is 5 seconds rather than 30 -- the body keeps the full 30, so image uploads on a slow uplink are unaffected. SQLite only; Postgres has no single-writer limit. |
||
|
|
53ae5fb620 |
fix(drying): don't stop a running AMS dry on an unreliable humidity re-check (#1892)
Auto-drying stopped manually started (and pre-restart) AMS drying cycles after exactly 30 minutes. The already-drying branch in _check_auto_drying() applied a humidity-based auto-stop despite its own "track but don't stop" comment, and the humidity re-check is unreliable: RH drops steeply in heated air, so the sensor reads ~15-20% within minutes of the dryer starting even with saturated filament. humidity <= threshold was thus effectively always true, and the _min_drying_seconds=1800 floor pinned the stop to the 30-minute mark. This also truncated Bambuddy's own preset-duration dries. Remove the humidity-based early-stop entirely: a running dry now runs to its configured duration (firmware stops it). Scheduling stops (print priority, queue no longer needing the dry) are unchanged via _stop_drying(). Drop the now-unused _min_drying_seconds. |
||
|
|
8d6f701f1d |
feat(drying): continue drying while printing + gate rotate-spool when tray loaded (issue #1816)
Continue Auto-Drying while a print is running on capable hardware. New Settings > Print Queue > "Continue drying while printing" toggle (default OFF). Extends _check_auto_drying in print_scheduler.py to evaluate running printers when supports_drying_while_printing(model, firmware) returns true. Strict allowlist verified per Bambu wiki release notes for "Print While Drying" / "printing while filament is drying": H2D 01.03.00.00+, H2C/H2S/P2S/H2D Pro 01.02.00.00+, X2D/A2L 01.01.00.00+, X1C 01.11.02.00+. P1*, A1, A1 Mini, X1 (non-C), X1E intentionally excluded. Mid-print drying temperature is capped at max(40, preset_temp - 5) to protect spools from heat damage inside the hot enclosure during a print, matching Bambu's own "lower drying temperature during printing" guidance. Rotate-spool toggle in the drying popover is now disabled when any tray in the targeted AMS has filament threaded into the feed tube (tray.state === 11). The whole AMS rotates as one mechanism, so a single loaded slot locks the entire unit. Previously the toggle was always clickable and the firmware rejected with dry_sf_reason=[3] (ConsumableAtAmsOutlet) after the click. The first cut keyed on the printer-level tray_now but missed the H2D's typical post-print state where tray_now resets to 255 while filament stays in the tube — the per-tray state field reports it correctly. Submission also clamps rotateTray off so a stale-true state from a previous AMS can't leak through. Backend: supports_drying_while_printing in printer_manager.py covers display names and internal SSDP/MQTT codes (O1D, O1E/O2D, O1C/O1C2, O1S, N6, BL-P001, N7, N9). New print_drying_enabled boolean in settings schema. Frontend: toggle on SettingsPage, gate + clamp on PrintersPage drying popover using existing amsData cache. i18n: 3 new keys x 11 locales, no English fallback. Tests: 7 cases on the gate matrix (TestSupportsDryingWhilePrinting), 4 cases on the scheduler mid-print path (TestMidPrintDrying), 9 cases on the rotate gate state transitions. Full backend pytest -n 30 green (4251/4251), ruff clean, frontend npm run build clean, i18n parity 5355 leaves per locale. |
||
|
|
68b9d741d9 |
feat(humidity): per-filament humidity threshold for auto-drying + alarms (#1605)
Reporter @thenewguy runs an engineering farm with one AMS per material
(PLA, ASA, Nylon, PVB, HIPS) — Bambuddy's single global ams_humidity_fair
threshold (default 60%) was driving both the queue / ambient auto-drying
trigger AND the hourly humidity alarm uniformly, which is wrong for
multi-material setups where Nylon wants <10% and PLA is fine at 60%.
Drying RUN parameters were already per-filament via drying_presets;
this commit adds the missing per-filament TRIGGER.
New setting ams_humidity_thresholds — JSON map of filament-type to
threshold percent with a "default" key for unknown / unmapped types.
Empty / unset → both consumers fall back to ams_humidity_fair so the
upgrade is silent.
Resolver lives in PrintScheduler.resolve_humidity_threshold(trays,
thresholds, fallback) — picks the lowest (most-restrictive) threshold
across all loaded tray types, matching the conservative-params strategy
_get_conservative_drying_params already uses for temp / hours. Empty
tray slots contribute no constraint; all-empty AMS falls through to the
"default" key. Filament names normalized to uppercase base (so
"PLA Basic" / "pla basic" both map to PLA).
Two consumer sites rewired through the same resolver so the scheduler
and the alarm path can never disagree about whether an AMS is "too
humid":
- print_scheduler.py::_check_auto_drying — per-AMS humidity comparison
for start / stop / skip decisions.
- main.py AMS sensor / alarm worker — hourly humidity alarm notifier.
UI: new table in Settings → Workflow → Auto-Drying, below the existing
Drying Presets table. Default row + 8 default filament types
(PLA / PETG / TPU / ABS / ASA / PA / PC / PVA) pre-filled from the
current ams_humidity_fair value so the editor starts sensibly.
Input pattern: draft-on-edit / commit-on-blur (transient humidityDrafts
state per row). onChange only updates the draft; onBlur (and Enter)
parses + clamps to [5, 95] + commits. Empty value on blur clears the
override and falls back to default. Caught mid-PR via a typing test:
the naive per-keystroke clamp snapped "3" → 5 before the user could
type the second digit of "30".
Setting is in the public _UI_PREFERENCE_FIELDS allowlist (same rationale
as drying_presets and ams_humidity_fair — non-sensitive integer map,
no SETTINGS_READ permission required for badge-color rendering).
|
||
|
|
14855ba8f4 |
Add ambient drying mode and fix block mode humidity auto-stop (#292)
Ambient drying: automatically dry filament on idle printers when humidity exceeds threshold, regardless of queue state. Separate toggle from queue auto-drying — both can run simultaneously. Uses the same presets, humidity threshold, and power constraint detection. Fix: block mode (wait for drying) previously skipped the humidity auto-stop check for already-drying printers, causing drying to continue indefinitely. Now only prevents starting new drying. |
||
|
|
cffba4a911 |
Add queue auto-drying, configurable drying presets, and AMS PSU detection (#292)
Queue auto-drying: scheduler automatically starts drying on idle printers with scheduled queue prints when AMS humidity exceeds the configured threshold. Uses conservative parameters (lowest temp, longest duration) for mixed filaments. Drying stops when humidity drops below threshold (30-minute minimum prevents oscillation), when scheduled items are removed, or when the feature is disabled. Optional "block queue" mode delays the next print until drying completes. Configurable presets: temperature and duration per filament type, editable in Settings → Print Queue, used by both manual drying popover and queue auto-drying. Separate presets for AMS 2 Pro (n3f) and AMS-HT (n3s) reflecting different heating capabilities. PSU detection: drying button disabled with tooltip when dry_sf_reason indicates insufficient power. Parses drying status bits and dry_sf_reason from AMS info hex string via MQTT. Backend: print_scheduler.py (+316 lines), bambu_mqtt.py, printer_manager, schemas, settings route. Frontend: PrintersPage drying presets prop, SettingsPage drying config UI, i18n (7 locales). Tests: 27 new tests in test_scheduler_auto_drying.py covering conservative params, presets, state sync, stop logic, minimum drying time, and auto-stop regressions. |