Printers move out of Settings into their own table and page: each has an optional nickname (the model is shown when blank), a model from the Bambu lineup with a line drawing that follows the selection, an AMS type suggested from the model, and its address, serial and access code. Access codes are never returned to the browser. The printer set up in Settings is migrated automatically and its settings rows removed. Background sync covers every printer. Grams left are filled in only from an AMS that measures (AMS, AMS 2 Pro, AMS HT), never from an AMS lite. Spools now show their RFID tag ID, product code and filament code, and say which printer they're loaded in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
119 lines
4.8 KiB
JavaScript
119 lines
4.8 KiB
JavaScript
// Printer models, and simple line drawings of their shapes, drawn for
|
|
// Printhive. The drawings suggest a model's form — open frame, enclosed, large
|
|
// format — rather than depict any product exactly.
|
|
(function () {
|
|
const svg = (inner, width = 150) =>
|
|
`<svg viewBox="0 0 ${width} 120" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
|
stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" role="img">${inner}</svg>`;
|
|
|
|
// An AMS lite: a stand with four spools around a hub.
|
|
const amsLite = (x) => `
|
|
<line x1="${x}" y1="104" x2="${x}" y2="52"/>
|
|
<line x1="${x - 10}" y1="104" x2="${x + 10}" y2="104"/>
|
|
<circle cx="${x - 9}" cy="40" r="7"/><circle cx="${x + 9}" cy="40" r="7"/>
|
|
<circle cx="${x - 9}" cy="58" r="7"/><circle cx="${x + 9}" cy="58" r="7"/>`;
|
|
|
|
// An AMS on top of an enclosed printer: a box showing four spools.
|
|
const amsTop = (x, width) => {
|
|
const step = width / 4;
|
|
let spools = '';
|
|
for (let i = 0; i < 4; i += 1) spools += `<circle cx="${x + step / 2 + i * step}" cy="23" r="5"/>`;
|
|
return `<rect x="${x}" y="14" width="${width}" height="18" rx="3"/>${spools}`;
|
|
};
|
|
|
|
const toolhead = (x, y) => `<rect x="${x}" y="${y}" width="14" height="15" rx="2"/>
|
|
<line x1="${x + 7}" y1="${y + 15}" x2="${x + 7}" y2="${y + 20}"/>`;
|
|
|
|
const shapes = {
|
|
// A1: a bed on a base, an upright gantry, an AMS lite alongside.
|
|
open: svg(`
|
|
<rect x="12" y="94" width="92" height="10" rx="3"/>
|
|
<rect x="24" y="84" width="68" height="6" rx="2"/>
|
|
<line x1="20" y1="94" x2="20" y2="26"/><line x1="96" y1="94" x2="96" y2="26"/>
|
|
<line x1="16" y1="26" x2="100" y2="26"/><line x1="20" y1="56" x2="96" y2="56"/>
|
|
${toolhead(50, 49)}
|
|
${amsLite(126)}`),
|
|
|
|
// A1 mini: a single column holding the gantry out over the bed.
|
|
openMini: svg(`
|
|
<rect x="22" y="94" width="72" height="10" rx="3"/>
|
|
<rect x="36" y="84" width="50" height="6" rx="2"/>
|
|
<rect x="24" y="30" width="10" height="64" rx="2"/>
|
|
<line x1="34" y1="54" x2="90" y2="54"/>
|
|
${toolhead(58, 47)}
|
|
${amsLite(122)}`),
|
|
|
|
// A2L: the A1's form, stretched to a larger bed.
|
|
openLarge: svg(`
|
|
<rect x="6" y="94" width="104" height="10" rx="3"/>
|
|
<rect x="14" y="84" width="88" height="6" rx="2"/>
|
|
<line x1="10" y1="94" x2="10" y2="22"/><line x1="106" y1="94" x2="106" y2="22"/>
|
|
<line x1="6" y1="22" x2="110" y2="22"/><line x1="10" y1="54" x2="106" y2="54"/>
|
|
${toolhead(52, 47)}
|
|
${amsLite(132)}`),
|
|
|
|
// P1P: a bare cube frame.
|
|
frame: svg(`
|
|
<rect x="30" y="38" width="66" height="66" rx="3"/>
|
|
<path d="M30 38 L44 28 L110 28 L96 38 M110 28 L110 94 L96 104"/>
|
|
<line x1="30" y1="60" x2="96" y2="60"/>
|
|
${toolhead(56, 53)}
|
|
<rect x="40" y="90" width="46" height="5" rx="2"/>`, 140),
|
|
|
|
// P1S, P2S, X1C, X1E, X2D: an enclosed box with an AMS on top.
|
|
box: svg(`
|
|
${amsTop(30, 66)}
|
|
<rect x="28" y="36" width="70" height="70" rx="5"/>
|
|
<rect x="36" y="44" width="54" height="46" rx="3"/>
|
|
<line x1="36" y1="98" x2="90" y2="98"/>
|
|
${toolhead(56, 52)}`, 126),
|
|
|
|
// H2S, H2D, H2C: a wide enclosed box with an AMS on top.
|
|
large: svg(`
|
|
${amsTop(28, 94)}
|
|
<rect x="18" y="36" width="114" height="70" rx="5"/>
|
|
<rect x="26" y="44" width="98" height="46" rx="3"/>
|
|
<line x1="26" y1="98" x2="124" y2="98"/>
|
|
${toolhead(58, 52)}${toolhead(78, 52)}`),
|
|
|
|
// Anything else: a plain box with a nozzle.
|
|
generic: svg(`
|
|
<rect x="34" y="30" width="72" height="72" rx="8"/>
|
|
${toolhead(63, 50)}
|
|
<line x1="44" y1="92" x2="96" y2="92"/>`, 140),
|
|
};
|
|
|
|
// ams is only a suggestion — a P1S might have an AMS, an AMS 2 Pro or an AMS HT.
|
|
const models = [
|
|
{ id: 'A1 mini', shape: 'openMini', ams: 'ams_lite' },
|
|
{ id: 'A1', shape: 'open', ams: 'ams_lite' },
|
|
{ id: 'A2L', shape: 'openLarge', ams: 'ams_lite' },
|
|
{ id: 'P1P', shape: 'frame', ams: 'ams' },
|
|
{ id: 'P1S', shape: 'box', ams: 'ams' },
|
|
{ id: 'P2S', shape: 'box', ams: 'ams_2_pro' },
|
|
{ id: 'X1C', shape: 'box', ams: 'ams' },
|
|
{ id: 'X1E', shape: 'box', ams: 'ams' },
|
|
{ id: 'X2D', shape: 'box', ams: 'ams_2_pro' },
|
|
{ id: 'H2S', shape: 'large', ams: 'ams_2_pro' },
|
|
{ id: 'H2D', shape: 'large', ams: 'ams_2_pro' },
|
|
{ id: 'H2C', shape: 'large', ams: 'ams_2_pro' },
|
|
{ id: 'Other', shape: 'generic', ams: 'none' },
|
|
];
|
|
|
|
const amsTypes = [
|
|
{ id: 'none', label: 'No AMS (external spool)' },
|
|
{ id: 'ams_lite', label: 'AMS lite (full or empty only)' },
|
|
{ id: 'ams', label: 'AMS' },
|
|
{ id: 'ams_2_pro', label: 'AMS 2 Pro' },
|
|
{ id: 'ams_ht', label: 'AMS HT' },
|
|
];
|
|
|
|
const find = (id) => models.find((m) => m.id === id) || null;
|
|
|
|
window.PRINTER_MODELS = {
|
|
models,
|
|
amsTypes,
|
|
find,
|
|
art: (id) => shapes[(find(id) || {}).shape] || shapes.generic,
|
|
};
|
|
}());
|