mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-09 07:25:44 +02:00
Every field that takes a chamber target stopped at 60: the per-filament chamber map and per-print override in Preheat & Heat Soak, the chamber quick-select presets, and the printer-card chamber control. 60 is the X1E's ceiling and the X1E was the only heated-chamber model when that limit was written; the H2 series and X2D heat to 65, so the top of their range was unreachable. The ceiling now lives in one constant per side (MAX_CHAMBER_TEMP_C in backend/app/utils/printer_models.py and frontend/src/utils/printer.ts) rather than as a literal at each call site. X1E firmware clamps a higher request to its own maximum, so a shared ceiling is safe. Also fixes a live bug at PrintersPage.tsx:7985: parsePresetTriple was bounded to 60 there, and it rejects the whole triple on any out-of-range entry, so a saved 65 preset would have silently reverted the printer card to the defaults while Settings still showed 65.
74 lines
2.5 KiB
TypeScript
74 lines
2.5 KiB
TypeScript
/**
|
|
* Helpers for the user-configurable temperature / fan-speed presets shown in
|
|
* the printer-card popovers and edited under Settings -> Workflow.
|
|
*
|
|
* Storage shape: JSON string of exactly 3 integers per category. Empty string
|
|
* means "use built-in defaults". Validators on the backend (AppSettingsUpdate)
|
|
* enforce the same shape on writes; helpers here are defensive parsers.
|
|
*
|
|
* The "Off" (value 0) button is rendered separately by buildPresetOptions and
|
|
* is not part of the configurable triple.
|
|
*/
|
|
|
|
import { MAX_CHAMBER_TEMP_C } from './printer';
|
|
|
|
export type PresetTriple = readonly [number, number, number];
|
|
|
|
export const NOZZLE_TEMP_DEFAULTS: PresetTriple = [120, 220, 260];
|
|
export const BED_TEMP_DEFAULTS: PresetTriple = [55, 75, 90];
|
|
export const CHAMBER_TEMP_DEFAULTS: PresetTriple = [35, 45, 60];
|
|
export const FAN_SPEED_DEFAULTS: PresetTriple = [50, 75, 100];
|
|
|
|
export interface PresetCategory {
|
|
key: 'nozzle_temp_presets' | 'bed_temp_presets' | 'chamber_temp_presets' | 'fan_speed_presets';
|
|
defaults: PresetTriple;
|
|
lo: number;
|
|
hi: number;
|
|
unit: 'C' | '%';
|
|
}
|
|
|
|
export const PRESET_CATEGORIES: readonly PresetCategory[] = [
|
|
{ key: 'nozzle_temp_presets', defaults: NOZZLE_TEMP_DEFAULTS, lo: 0, hi: 320, unit: 'C' },
|
|
{ key: 'bed_temp_presets', defaults: BED_TEMP_DEFAULTS, lo: 0, hi: 140, unit: 'C' },
|
|
{ key: 'chamber_temp_presets', defaults: CHAMBER_TEMP_DEFAULTS, lo: 0, hi: MAX_CHAMBER_TEMP_C, unit: 'C' },
|
|
{ key: 'fan_speed_presets', defaults: FAN_SPEED_DEFAULTS, lo: 0, hi: 100, unit: '%' },
|
|
];
|
|
|
|
/**
|
|
* Parse a JSON triple from settings, falling back to defaults if empty / malformed
|
|
* / wrong shape. Forward-compat for any storage drift; backend validators are
|
|
* the source of truth.
|
|
*/
|
|
export function parsePresetTriple(
|
|
raw: string | undefined | null,
|
|
fallback: PresetTriple,
|
|
lo: number,
|
|
hi: number,
|
|
): [number, number, number] {
|
|
if (!raw) return [...fallback];
|
|
try {
|
|
const parsed = JSON.parse(raw);
|
|
if (
|
|
Array.isArray(parsed) &&
|
|
parsed.length === 3 &&
|
|
parsed.every((n) => Number.isInteger(n) && n >= lo && n <= hi)
|
|
) {
|
|
return parsed as [number, number, number];
|
|
}
|
|
} catch {
|
|
// fall through to defaults
|
|
}
|
|
return [...fallback];
|
|
}
|
|
|
|
/** Build the popover options: fixed "Off" button + 3 user-configured presets. */
|
|
export function buildPresetOptions(
|
|
values: PresetTriple,
|
|
unit: 'C' | '%',
|
|
): Array<{ label: string; value: number }> {
|
|
return [
|
|
{ label: 'Off', value: 0 },
|
|
...values.map((v) => ({ label: `${v} ${unit}`, value: v })),
|
|
];
|
|
}
|