mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-21 18:47:13 +02:00
fix(ams): stop showing the humidity drop index as a percentage (issue #3140)
Bambu sends two humidity fields that are not the same quantity. humidity_raw is relative humidity in percent; humidity is a 1-5 drop index, and it runs the other way -- OpenBambuAPI's push_info sample pairs "humidity:30%" with "humidity_idx:4", so a high index means dry where a high percentage means wet. Four call sites used the index whenever no percentage arrived. A unit sending only the index therefore rendered as "2%" in the green band while being the second-wettest of the five steps, charted an average of index values as a percentage, and sat under every humidity threshold forever, since no index can reach one -- the alarm and auto-drying could not fire for such a unit at all. - utils/ams_humidity: one leaf helper, a percentage or None. The index is never converted; None is what every caller already handles. - routes/printers, printer_manager, print_scheduler, main, bambu_mqtt: all five readings go through it, so the card, the websocket, the chart, the alarm and auto-drying cannot answer differently. - main: a unit that reports the index and no usable percentage says so once per unit in the log, with its firmware versions requested. No supported printer is known to do this, and "known" is doing work there -- the alternative is a card that goes blank with no trace. Three faults found while checking what else those paths touched: - main: humidity_raw=float(x) if x else None stored NULL for a numeric 0% while writing 0.0 to humidity on the same row. - main: that same expression was unguarded, unlike the parse above it, so a non-numeric humidity_raw raised inside record_ams_history and aborted the pass for every printer, not just the one that sent it. - routes/ams_history: the averages were tested for truthiness, so a window averaging exactly 0 reported no average while the min and max beside it reported 0.0. An affected unit now reports no humidity rather than a number that means the opposite: the indicator is hidden, the chart leaves a gap, the alarm and auto-drying skip the unit. Temperature is untouched. Auto-drying's outcome is unchanged either way -- an index could never cross the threshold -- so only the intent moves. No supported printer is known to be affected; the report came from an install running X1Plus, which Bambuddy does not support. Verified against 7927 recorded samples from seven AMS units including an AMS-HT: not one used the fallback. Two percentages that did fall through to the index no longer do -- a reading with a decimal point, and "38.0", which int() rejected.
This commit is contained in:
@@ -93,10 +93,14 @@ async def get_ams_history(
|
||||
],
|
||||
min_humidity=stats.min_humidity,
|
||||
max_humidity=stats.max_humidity,
|
||||
avg_humidity=round(stats.avg_humidity, 1) if stats.avg_humidity else None,
|
||||
# ``is not None``, not truthiness: an average of exactly 0 is a
|
||||
# reading, and the min/max beside it would report it while the average
|
||||
# showed an em dash. AVG over an empty or all-NULL window is the only
|
||||
# case that has no answer (#3140).
|
||||
avg_humidity=round(stats.avg_humidity, 1) if stats.avg_humidity is not None else None,
|
||||
min_temperature=stats.min_temp,
|
||||
max_temperature=stats.max_temp,
|
||||
avg_temperature=round(stats.avg_temp, 1) if stats.avg_temp else None,
|
||||
avg_temperature=round(stats.avg_temp, 1) if stats.avg_temp is not None else None,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ from backend.app.services.printer_media import (
|
||||
)
|
||||
from backend.app.services.slicer_filament_resolver import _ORCA_PROFILE_ID
|
||||
from backend.app.services.slot_nozzle import resolve_slot_nozzle
|
||||
from backend.app.utils.ams_humidity import ams_humidity_percent
|
||||
from backend.app.utils.filament_ids import filament_id_to_setting_id
|
||||
from backend.app.utils.filament_types import is_material_name, printer_filament_type
|
||||
from backend.app.utils.fts_routing import slot_extruder
|
||||
@@ -586,22 +587,11 @@ async def get_printer_status(
|
||||
exists=tray_data.get("exists"),
|
||||
)
|
||||
)
|
||||
# Prefer humidity_raw (percentage) over humidity (index 1-5)
|
||||
# humidity_raw is the actual percentage value from the sensor
|
||||
humidity_raw = ams_data.get("humidity_raw")
|
||||
humidity_idx = ams_data.get("humidity")
|
||||
humidity_value = None
|
||||
|
||||
if humidity_raw is not None:
|
||||
try:
|
||||
humidity_value = int(humidity_raw)
|
||||
except (ValueError, TypeError):
|
||||
pass # Skip unparseable humidity; will try index fallback
|
||||
if humidity_value is None and humidity_idx is not None:
|
||||
try:
|
||||
humidity_value = int(humidity_idx)
|
||||
except (ValueError, TypeError):
|
||||
pass # Skip unparseable humidity index; humidity remains None
|
||||
# Percentage only. The 1-5 ``humidity`` index is never substituted
|
||||
# for one -- it is inverted, so it would read as the opposite of
|
||||
# what it means (#3140). See utils/ams_humidity.
|
||||
humidity_pct = ams_humidity_percent(ams_data)
|
||||
humidity_value = int(round(humidity_pct)) if humidity_pct is not None else None
|
||||
# AMS-HT has 1 tray, regular AMS has 4 trays
|
||||
is_ams_ht = len(trays) == 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user