From c77486a7a8ee55bcb2c99ff77c087df1068b04e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilja=20Karta=C5=A1ov?= Date: Tue, 4 Jul 2023 13:28:39 +0200 Subject: [PATCH] Update SLA code to use API v.1 --- config.sl1.js | 1 + src/printer/common.js | 7 +- src/printer/components/cameras.js | 1 - src/printer/components/dataFormat.js | 70 +------ src/printer/components/files.js | 3 + src/printer/components/job.js | 225 +++++++++++----------- src/printer/components/question.js | 2 +- src/printer/components/toast.js | 4 +- src/printer/{fdm => }/context.js | 182 ++++++++++------- src/printer/fdm/index.js | 151 --------------- src/printer/index.js | 173 ++++++++++++++++- src/printer/sla/dashboard.js | 26 --- src/printer/sla/index.js | 219 --------------------- src/printer/sla/temperature.js | 13 -- src/printer/{fdm => views}/dashboard.js | 3 - src/printer/{sla => views}/exposure.js | 20 +- src/printer/{sla => views}/refill.js | 4 +- src/printer/{fdm => views}/temperature.js | 0 src/state.js | 10 +- templates/components/telemetry.html | 12 +- 20 files changed, 442 insertions(+), 684 deletions(-) rename src/printer/{fdm => }/context.js (65%) delete mode 100644 src/printer/fdm/index.js delete mode 100644 src/printer/sla/dashboard.js delete mode 100644 src/printer/sla/index.js delete mode 100644 src/printer/sla/temperature.js rename src/printer/{fdm => views}/dashboard.js (92%) rename src/printer/{sla => views}/exposure.js (91%) rename src/printer/{sla => views}/refill.js (89%) rename src/printer/{fdm => views}/temperature.js (100%) diff --git a/config.sl1.js b/config.sl1.js index a81518ab..0901ec7f 100644 --- a/config.sl1.js +++ b/config.sl1.js @@ -15,6 +15,7 @@ module.exports = (env, args) => { WITH_START_PRINT_AFTER_UPLOAD: true, WITH_LOGS: false, WITH_FONT: false, + WITH_V1_API: true, ...env, }; return webpackConfig(config, args); diff --git a/src/printer/common.js b/src/printer/common.js index efd67f26..2c008f54 100644 --- a/src/printer/common.js +++ b/src/printer/common.js @@ -2,9 +2,10 @@ import { LinkState, translateState } from "../state"; const SEPARATOR = " - "; -export const getPrinterLabel = (context) => { - return buildTitle([context.printer?.location, context.printer?.name]); -}; +export const getPrinterLabel = (context) => buildTitle([ + context.printer?.location || context.printer?.hostname, + context.printer?.name +]); export const buildTitle = (titleItems) => { return [...titleItems] diff --git a/src/printer/components/cameras.js b/src/printer/components/cameras.js index 9f47cd01..551dc7cb 100644 --- a/src/printer/components/cameras.js +++ b/src/printer/components/cameras.js @@ -411,7 +411,6 @@ const createCameraSettingsModal = (cameraId, resolve) => { inputTriggerScheme.value = translateTriggerScheme(data.trigger_scheme); setVisible(inputFocus.parentNode, hasFocus); - console.log(`DEBUG: has focus (${hasFocus})`, data) if (hasFocus) { inputFocus.value = Math.round(data.focus * 100); } diff --git a/src/printer/components/dataFormat.js b/src/printer/components/dataFormat.js index d0003579..94e08a7e 100644 --- a/src/printer/components/dataFormat.js +++ b/src/printer/components/dataFormat.js @@ -20,19 +20,6 @@ const str_GB = translate("unit.gb"); const str_true = translate("prop.true"); const str_false = translate("prop.false"); -/** - * Format the value data with format specificated. - * @param {string} format - one of ["int", "number", "layer", "temp", "fan", "resin", "cover", "date", "progress", "timeEst", "time", "expo", "boolean"] - * @param {any} value - */ -const formatData = (format, value) => { - if (process.env.PRINTER_TYPE === "sla") { - return slaFormatData(format, value); - } else { - return fdmFormatData(format, value); - } -}; - /** * It formats a number using fixed-point notation with one digit after the decimal point. * ex: 123.456 => 123.4 @@ -193,14 +180,15 @@ function formatBoolean(value) { } /** - * Format the value data with format specificated for sla type. - * @param {string} format - one of ["int", "number", "layer", "temp", "fan", "resin", "cover", "date", "progress", "timeEst", "time", "expo", "boolean"] + * Format the value data with format specificated. + * @param {string} format - one of ["number", "temp", "fan", "pos", "date", "progress", "timeEst", "time"] * @param {any} value */ -const slaFormatData = (format, value) => { +const formatData = (format, value) => { if (value === undefined || (value === null && format !== "progress")) { return translate("prop.na"); } + switch (format) { case "int": return parseInt(value); @@ -208,60 +196,22 @@ const slaFormatData = (format, value) => { return numberFormat(value); case "layer": return numberFormat(value, false) + " mm"; - case "temp": - return numberFormat(value) + " °C"; - case "fan": - return numberFormat(value) + ` ${str_rpm}`; - case "resin": - return numberFormat(value) + ` ${str_ml}`; - case "cover": - return value - ? translate("prop.cover-closed") - : translate("prop.cover-opened"); - case "date": - return dateFormat(value); - case "progress": - return numberFormat((value || 0) * 100, true, 0) + "%"; - case "timeEst": - return formatEstimatedTime(value); - case "time": - return formatTime(value); - case "est-time": - return "~ " + formatTime(value); - case "expo": - return formatExposure(value); case "totalLayer": return totalLayers(value); case "material": return value || translate("prop.na"); - case "size": - return formatSize(value); - case "boolean": - return formatBoolean(value); - default: - return value; - } -}; - -/** - * Format the value data with format specificated for fdm type. - * @param {string} format - one of ["number", "temp", "fan", "pos", "date", "progress", "timeEst", "time"] - * @param {any} value - */ -const fdmFormatData = (format, value) => { - if (value === undefined || (value === null && format !== "progress")) { - return translate("prop.na"); - } - - switch (format) { - case "number": - return numberFormat(value); case "temp": return numberFormat(value) + " °C"; case "temp_int": return numberFormat(value, 0) + "°C"; case "fan": return numberFormat(value) + ` ${str_rpm}`; + case "resin": + return numberFormat(value) + ` ${str_ml}`; + case "cover": + return value + ? translate("prop.cover-closed") + : translate("prop.cover-opened"); case "print": return numberFormat(value || 0, true, 0) + "%"; case "pos": diff --git a/src/printer/components/files.js b/src/printer/components/files.js index 8223fb54..7a2518a6 100644 --- a/src/printer/components/files.js +++ b/src/printer/components/files.js @@ -202,6 +202,9 @@ const updateFiles = (opts = {}) => { headers: { "If-None-Match": lastETag }, }) .then((result) => { + if (result.code === 304) { + return + } if (url !== getCurrentApiPath()) { // user navigated to other folder return; diff --git a/src/printer/components/job.js b/src/printer/components/job.js index 9d0e622d..b093d224 100644 --- a/src/printer/components/job.js +++ b/src/printer/components/job.js @@ -2,27 +2,34 @@ // Copyright (C) 2021 Prusa Research a.s. - www.prusa3d.com // SPDX-License-Identifier: GPL-3.0-or-later -import joinPaths from "../../helpers/join_paths"; import updateProperties from "./updateProperties"; -import { cancelJob, cancelPreview, pauseJob, resumeJob, startJob } from "./jobActions"; +import { + cancelJob, + cancelPreview, + pauseJob, + resumeJob, + startJob, +} from "./jobActions"; import { deleteFile, downloadFile } from "./fileActions"; -import { getImage, getJson } from "../../auth"; -import { handleError } from "./errors"; -import { renderProgressImg, updateProgressImg } from "./progressImage"; -import { setEnabled, setHidden, setVisible, showLoading, hideLoading } from "../../helpers/element"; +import { renderProgressImg } from "./progressImage"; +import { + setEnabled, + setHidden, + setVisible, + showLoading, + hideLoading, +} from "../../helpers/element"; import { updateProgressBar } from "./progressBar"; import { translate } from "../../locale_provider"; -import changeExposureTimesQuestion from "../sla/exposure"; -import { resinRefill } from "../sla/refill"; +import changeExposureTimesQuestion from "../views/exposure"; +import { resinRefill } from "../views/refill"; import { JobPendingStates, LinkState, OperationalStates } from "../../state"; import { setButtonLoading, unsetButtonLoading } from "../../helpers/button"; import printer from ".."; -import { context } from "../fdm"; let pendingCommand = null; let pendingDownload = null; - /** * Rerender component without api calls. * @param {object} context Printer context. @@ -35,8 +42,7 @@ export function render(context) { } const visible = setComponentVisibility(context); - if (visible) - updateComponent(context); + if (visible) updateComponent(context); } /** @@ -48,21 +54,18 @@ export function update(context, isFilePreview = false) { if (pendingCommand && pendingCommand.state !== context.state) { pendingCommand = null; - } + } if (visible) { updateComponent(context, isFilePreview); } -}; +} function setComponentVisibility(context, isFilePreview) { const element = document.getElementById("job"); - if (!element) - return false; + if (!element) return false; - const visible = isFilePreview - ? !!context.files.selected - : !!context.job?.id; + const visible = isFilePreview ? !!context.files.selected : !!context.job?.id; setVisible(element, visible); return visible; @@ -100,16 +103,15 @@ function updateComponent(context, isFilePreview) { } function setupRefill(stateText) { - const preview = document.getElementById("preview-wrapper") - const refill = document.getElementById("refill-wrapper") - if (stateText == "Feed me" || stateText == "Pour in resin") { - if (stateText == "Pour in resin") { + const preview = document.getElementById("preview-wrapper"); + const refill = document.getElementById("refill-wrapper"); + if ([LinkState.REFILL, LinkState.POUR_IN_RESIN].includes(stateText)) { + if (stateText == LinkState.POUR_IN_RESIN) { translate("msg.sla-pour-resin", { query: "#sla-refill-text" }); } setHidden(preview); setVisible(refill); - } - else { + } else { setHidden(refill); setVisible(preview); } @@ -135,57 +137,82 @@ function setupProperties(isPreview) { function hideNaProperties(state, isFilePreview) { const naValue = translate("prop.na"); - document.getElementById("job").querySelectorAll(".job-details .job-prop").forEach(section => { - const group = section.querySelector(".job-prop-grid").children; - let hidden = true; - - for (const prop of group) { - var isNa = prop.querySelector("[data-type]")?.innerHTML.trim() === naValue; - setHidden(prop, isNa); - if (!isNa) - hidden = false; - } - - if (process.env.PRINTER_TYPE === "sla") - setHidden(document.getElementById("pnt-time-est"), true) + document + .getElementById("job") + .querySelectorAll(".job-details .job-prop") + .forEach((section) => { + const group = section.querySelector(".job-prop-grid").children; + let hidden = true; + + for (const prop of group) { + var isNa = + prop.querySelector("[data-type]")?.innerHTML.trim() === naValue; + setHidden(prop, isNa); + if (!isNa) hidden = false; + } - if (process.env.PRINTER_TYPE === "sla" - && section.id === "file-last-mod" - && !isFilePreview - && ["Busy", "Printing"].includes(state.text) - ) { - hidden = true; - } + if (process.env.PRINTER_TYPE === "sla") + setHidden(document.getElementById("pnt-time-est"), true); + if ( + process.env.PRINTER_TYPE === "sla" && + section.id === "file-last-mod" && + !isFilePreview && + ["Busy", "Printing"].includes(state.text) + ) { + hidden = true; + } - setHidden(section, hidden); - }) + setHidden(section, hidden); + }); } /* ===================================== SETUP BUTTONS ======================================= */ function setupButtons(state, dataSource, jobId) { const file = dataSource.file; - + setupCancelButton(state, jobId); setupStartButton(state, file, jobId); setupDeleteButton(state, file, jobId); setupDownloadButton(state, file, jobId); if (!!jobId) { - if (process.env.PRINTER_TYPE === "fdm") { + if (process.env.PRINTER_TYPE === "sla") { + setupExposureButton(state, dataSource, changeExposureTimesQuestion); + // pause for refill + setupPauseButton(state, jobId, "#job #refill"); + setupSlaResumeWithRefillButton(state, jobId); + setupSlaResumeNoRefillButton(state, jobId); + } else if (process.env.PRINTER_TYPE === "fdm") { setupPauseButton(state, jobId, "#job #pause"); setupResumeButton(state, jobId); } + } +} - if (process.env.PRINTER_TYPE === "sla") { - const jobFile = jobResult?.job?.file; - if (jobFile) - setupExposureButton(state, jobFile, changeExposureTimesQuestion); - setupPauseButton(state, jobId, "#job #refill"); - setupSlaResumeButton(state, "#job #continue"); - setupSlaResumeButton(state, "#job #back"); - } +function setupSlaResumeWithRefillButton(state, jobId) { + const btn = document.querySelector("#job #continue"); + setVisible(btn, [LinkState.REFILL, LinkState.POUR_IN_RESIN].includes(state)); + + if (btn) { + btn.onclick = () => + state === LinkState.REFILL ? resinRefill(jobId) : resumeJob(jobId); + } +} + +function setupSlaResumeNoRefillButton(state, jobId) { + const btn = document.querySelector("#job #back"); + const isVisible = LinkState.REFILL === state; + setVisible(btn, isVisible); + setEnabled(btn, true); + + if (btn) { + btn.onclick = () => { + setEnabled(btn, false); + pendingCommand = { code: "resume", state: state }; + resumeJob(jobId).catch(() => (pendingCommand = null)); + }; } } @@ -194,22 +221,22 @@ function setupCancelButton(state, jobId) { const btnClose = document.querySelector("#job-close"); const linkState = LinkState.fromApi(state); const isJobPreview = OperationalStates.includes(linkState); - const enabled = !pendingCommand && JobPendingStates.includes(state) + const enabled = !pendingCommand && JobPendingStates.includes(state); const context = printer.getContext(); - + setEnabled(btnStop, enabled); if (btnStop) { if (jobId) { - const isVisible = jobId || (process.env.PRINTER_TYPE === "sla" && state.text != "Feed me"); + const isVisible = jobId && ![LinkState.REFILL, LinkState.POUR_IN_RESIN].includes(state); setVisible(btnStop, isVisible); btnStop.onclick = () => { cancelJob(jobId, { onConfirm: () => { - pendingCommand = {code: "stop", state: state}; + pendingCommand = { code: "stop", state: state }; setEnabled(btnStop, false); }, - onError: () => pendingCommand = null + onError: () => (pendingCommand = null), }); }; } @@ -217,9 +244,7 @@ function setupCancelButton(state, jobId) { if (btnClose) { setVisible(btnClose, isJobPreview || !jobId); - btnClose.onclick = !jobId - ? () => context.selectFile(null) - : cancelPreview; + btnClose.onclick = !jobId ? () => context.selectFile(null) : cancelPreview; } } @@ -228,7 +253,7 @@ function setupStartButton(state, file, jobId) { const actionAllowed = OperationalStates.includes(state); if (btn) { - setVisible(btn, actionAllowed) + setVisible(btn, actionAllowed); setEnabled(btn, actionAllowed); btn.onclick = () => startJob(state !== LinkState.READY, file.resource); } @@ -243,43 +268,24 @@ function setupPauseButton(state, jobId, selector) { if (btn) { btn.onclick = () => { setEnabled(btn, false); - pendingCommand = {code: "pause", state: state}; - pauseJob(jobId) - .catch(() => pendingCommand = null); + pendingCommand = { code: "pause", state: state }; + pauseJob(jobId).catch(() => (pendingCommand = null)); }; } } function setupResumeButton(state, jobId) { const btn = document.querySelector("#job #resume"); - const isPaused = state === LinkState.PAUSED; + const isPaused = [LinkState.PAUSED].includes(state); setVisible(btn, isPaused); setEnabled(btn, !pendingCommand && isPaused); if (btn) { btn.onclick = () => { setEnabled(btn, false); - pendingCommand = {code: "resume", state: state}; - resumeJob(jobId) - .catch(() => pendingCommand = null); - } - } -} - -function setupSlaResumeButton(state, selector) { - const btn = document.querySelector(selector); - if (selector.includes("#back")) - setVisible(btn, state.flags.paused && state.text === "Feed me"); - else - setVisible(btn, state.flags.paused); - - - if (btn) { - if (state.text == "Feed me" && !selector.includes("#back")) { - btn.onclick = resinRefill; - } else { - btn.onclick = resumeJob; - } + pendingCommand = { code: "resume", state: state }; + resumeJob(jobId).catch(() => (pendingCommand = null)); + }; } } @@ -295,17 +301,18 @@ function setupDeleteButton(state, file, jobId) { context.selectFile(null); } }); - } + }; } } function setupDownloadButton(state, file, jobId) { const btn = document.querySelector("#job #download"); if (btn) { - const isVisible = !jobId && file.refs?.download && ( - !pendingDownload || pendingDownload === file.refs.download - ); - + const isVisible = + !jobId && + file.refs?.download && + (!pendingDownload || pendingDownload === file.refs.download); + const fileDisplayName = file.display_name || file.name; setVisible(btn, isVisible); if (isVisible) { @@ -314,28 +321,24 @@ function setupDownloadButton(state, file, jobId) { setButtonLoading(btn); downloadFile(file.refs.download, fileDisplayName, () => { pendingDownload = null; - unsetButtonLoading(btn) + unsetButtonLoading(btn); }); - } + }; } } } -function setupExposureButton(state, jobFile, changeExposureTimesQuestion) { +function setupExposureButton(state, job, changeExposureTimesQuestion) { const btn = document.querySelector("#job #exposure"); if (btn) { - setVisible(btn, state.text === "Pour in resin" || state.text === "Printing"); - setEnabled(btn, state.flags.operational); - btn.onclick = () => changeExposureTimesQuestion(jobFile); - } -} - -function setupBackButton(state) { - const btn = document.querySelector("#job #back"); - - if (btn) { - setVisible(btn, state.flags.paused && state.text === "Feed me"); - btn.onclick = resumeJob; + const canSetupExposure = [ + ...OperationalStates, + LinkState.PRINTING, + LinkState.POUR_IN_RESIN, + ].includes(state); + setVisible(btn, canSetupExposure); + setEnabled(btn, canSetupExposure); + btn.onclick = () => changeExposureTimesQuestion(job); } } diff --git a/src/printer/components/question.js b/src/printer/components/question.js index cae3b3f2..b8390fd8 100644 --- a/src/printer/components/question.js +++ b/src/printer/components/question.js @@ -31,7 +31,7 @@ export const doQuestion = (data) => { no: (cb) => cb(), yesText: translate("btn.yes"), noText: translate("btn.no"), - next: "#files", + next: "#dashboard", }, data ); diff --git a/src/printer/components/toast.js b/src/printer/components/toast.js index 20792d0d..8674740d 100644 --- a/src/printer/components/toast.js +++ b/src/printer/components/toast.js @@ -38,7 +38,9 @@ export const createToast = (title, message, type) => { function show({ title, message, type, onClose }) { const article = createToast(title, message, type); const close = () => { - toast_context.removeChild(article); + if (toast_context.contains(article)) { + toast_context.removeChild(article); + } onClose?.(); }; diff --git a/src/printer/fdm/context.js b/src/printer/context.js similarity index 65% rename from src/printer/fdm/context.js rename to src/printer/context.js index 491e43d8..5e29d5c4 100644 --- a/src/printer/fdm/context.js +++ b/src/printer/context.js @@ -1,7 +1,7 @@ -import { getImage, getJson } from "../../auth"; -import { handleError } from "../components/errors"; -import { LinkState } from "../../state"; -import { getEstimatedEnd } from "../common"; +import { getImage, getJson } from "../auth"; +import { handleError } from "./components/errors"; +import { LinkState } from "../state"; +import { getEstimatedEnd } from "./common"; export class Context { constructor() { @@ -35,18 +35,18 @@ export class Context { ok: true, message: "OK", settings: { - hostname: 'connect.prusa3d.com', + hostname: "connect.prusa3d.com", tls: true, - port: 0 - } + port: 0, + }, }, printer: { ok: true, message: "OK", settings: { - port: '', + port: "", baudrate: 115200, - } + }, }, }; this.files = { @@ -61,19 +61,18 @@ export class Context { } updateConnection() { - return getJson("/api/connection", { method: "GET" }) - .then(res => { - this.link.connect.settings = { - hostname: res.data.connect.hostname, - port: res.data.connect.port, - tls: res.data.connect.tls, - }; - this.link.connect.registration = res.data.connect.registration; - this.link.printer.settings = { - port: res.data.current.port, - baudrate: res.data.current.baudrate, - }; - }); + return getJson("/api/connection", { method: "GET" }).then((res) => { + this.link.connect.settings = { + hostname: res.data.connect?.hostname, + port: res.data.connect?.port, + tls: res.data.connect?.tls, + }; + this.link.connect.registration = res.data.connect?.registration; + this.link.printer.settings = { + port: res.data.current?.port, + baudrate: res.data.current?.baudrate, + }; + }); } update({ status, printer }) { @@ -105,12 +104,15 @@ export class Context { hostname: printer.hostname, port: printer.port, }; + this.fileExtensions = + printer.project_extensions ?? process.env["FILE_EXTENSIONS"].split(","); } updateTelemetry(printer) { this.state = LinkState.fromApi(printer.state.toUpperCase()); this.telemetry = { temperature: { + // fdm nozzle: { current: printer.temp_nozzle, target: printer.target_nozzle, @@ -119,6 +121,16 @@ export class Context { current: printer.temp_bed, target: printer.target_bed, }, + // sla + ambient: { + current: printer.temp_ambient, + }, + cpu: { + current: printer.temp_cpu, + }, + uvLED: { + current: printer.temp_uv_led, + }, }, axis: { x: printer.axis_x, @@ -128,15 +140,21 @@ export class Context { flow: printer.flow, speed: printer.speed, fan: { + // fdm hotend: printer.fan_hotend, print: printer.fan_print, + // sla + blower: printer.fan_blower, + rear: printer.fan_rear, + uvLED: printer.fan_uv_led, }, + coverClosed: printer.cover_closed, }; // hide status if connect is not supported this.link.connect.message = printer.status_connect?.message ?? ""; this.link.connect.ok = printer.status_connect?.ok; // just suppress the status if unsupported by the printer - this.link.printer.message = printer.status_printer?.message ?? 'ok'; + this.link.printer.message = printer.status_printer?.message ?? "ok"; this.link.printer.ok = printer.status_printer?.ok ?? true; } @@ -149,42 +167,14 @@ export class Context { this.job = undefined; return; } - getJson("/api/v1/job") - .then((response) => { - const data = response.data; - if (data.id !== this.job.id) { - return; - } - - this.job = { - ...this.job, - file: mapFile(data.file), - thumbnail: { - source: !data.file.refs?.thumbnail, - ready: !data.file.refs?.thumbnail, - url: undefined, - }, - }; - - if (!this.job.thumbnail.ready) { - getImage(this.job.file.refs.thumbnail) - .then(({ url }) => { - if (this.job.id === newJobId) { - this.job.thumbnail.url = url; - } - }) - .catch((e) => console.error("Failed to fetch thumbnail", e)) - .finally(() => (this.job.thumbnail.ready = true)); - } - }) - .catch((err) => handleError(err)); + this.updateJobDetails(); } - if (newJobId) { + if (job && newJobId) { const lastTimeRemaining = this.job?.timeRemaining; - const thisTimeRemaning = job.time_remaining; + const thisTimeRemaining = job.time_remaining; const estimatedEnd = - lastTimeRemaining != thisTimeRemaning - ? getEstimatedEnd(thisTimeRemaning) + lastTimeRemaining != thisTimeRemaining + ? getEstimatedEnd(thisTimeRemaining) : this.job?.estimatedEnd; this.job = { @@ -199,6 +189,46 @@ export class Context { } } + updateJobDetails() { + return getJson("/api/v1/job") + .then((response) => { + const data = response.data; + if (data.id !== this.job.id) { + return; + } + + this.job = { + ...this.job, + file: mapFile(data.file), + thumbnail: { + source: !data.file.refs?.thumbnail, + ready: !data.file.refs?.thumbnail, + url: undefined, + }, + ...(process.env.PRINTER_TYPE === "sla" + ? { + exposureTime: data.exposure_time, + exposureTimeCalibration: data.exposure_time_calibration, + exposureTimeFirst: data.exposure_time_first, + exposureUserProfile: data.exposure_user_profile, + } + : {}), + }; + + if (!this.job.thumbnail.ready) { + getImage(this.job.file.refs.thumbnail) + .then(({ url }) => { + if (this.job.id === newJobId) { + this.job.thumbnail.url = url; + } + }) + .catch((e) => console.error("Failed to fetch thumbnail", e)) + .finally(() => (this.job.thumbnail.ready = true)); + } + }) + .catch((err) => handleError(err)); + } + updateStorage(storage) { Object.keys(storage).forEach((entry) => { const data = { @@ -250,14 +280,14 @@ export class Context { const now = Math.round(Date.now() / 1000); const fileSize = this.transfer?.file?.size || 0; const timeTransferring = transfer.time_transferring; - const timeStarted = timeTransferring !== undefined - ? now - timeTransferring - : undefined; + const timeStarted = + timeTransferring !== undefined ? now - timeTransferring : undefined; const dataTransferred = transfer.data_transferred; const dataRemaining = fileSize - dataTransferred; - const timeRemaining = (timeTransferring > 0 && dataRemaining >= 0) - ? (dataRemaining / (dataTransferred / timeTransferring)) - : undefined; + const timeRemaining = + timeTransferring > 0 && dataRemaining >= 0 + ? dataRemaining / (dataTransferred / timeTransferring) + : undefined; this.transfer = { ...this.transfer, @@ -266,7 +296,7 @@ export class Context { timeRemaining, id: newId, progress: transfer.progress, - dataTransferred + dataTransferred, }; } } @@ -282,7 +312,7 @@ export class Context { this.files.selected = null; return; } - + const thumbnailSource = file.refs?.thumbnail; this.files.selected = { @@ -297,16 +327,16 @@ export class Context { if (!file.meta) { const resource = this.files.selected.file.resource; - getJson(resource) - .then(response => { - const fullFileInfo = mapFile({...response.data, resource}); - if (this.files.selected.file.resource === resource) { - this.files.selected.file.meta = fullFileInfo.meta; - this.files.selected.timeRemaining = fullFileInfo.meta?.estimatedPrintTime; - } - }); + getJson(resource).then((response) => { + const fullFileInfo = mapFile({ ...response.data, resource }); + if (this.files.selected.file.resource === resource) { + this.files.selected.file.meta = fullFileInfo.meta; + this.files.selected.timeRemaining = + fullFileInfo.meta?.estimatedPrintTime; + } + }); } - + if (thumbnailSource) { getImage(thumbnailSource) .then(({ url }) => { @@ -344,6 +374,10 @@ const mapFile = (data) => ({ filamentType: data.meta?.filament_type, layerHeight: data.meta?.layer_height, estimatedPrintTime: data.meta?.estimated_print_time, + exposureTime: data.meta?.exposure_time, + exposureTimeCalibration: data.meta?.exposure_time_calibration, + exposureTimeFirst: data.meta?.exposure_time_first, + exposureUserProfile: data.meta?.exposure_user_profile, }, - readOnly: data.read_only || data.ro + readOnly: data.read_only || data.ro, }); diff --git a/src/printer/fdm/index.js b/src/printer/fdm/index.js deleted file mode 100644 index 67db4ed7..00000000 --- a/src/printer/fdm/index.js +++ /dev/null @@ -1,151 +0,0 @@ -// This file is part of the Prusa Link Web -// Copyright (C) 2021 Prusa Research a.s. - www.prusa3d.com -// SPDX-License-Identifier: GPL-3.0-or-later - -import * as graph from "../components/temperature_graph"; -import dashboard from "./dashboard.js"; -import files from "../components/files"; -import question from "../components/question.js"; -import { buildTitle, getPrinterLabel, getStatusForTitle } from "../common.js"; -import { updateProperties } from "../components/updateProperties.js"; -import { translate } from "../../locale_provider"; -import { LinkState, translateState } from "../../state"; -import updateConnectionStatus from "../components/updateConnectionStatus"; -import { currentRoute } from "../../router"; -import { Context } from "./context"; - -export const context = new Context(); - -const updatePrinterTitle = (obj) => { - const newTitle = () => { - const label = document.getElementById("title-printer"); - if (label) { - label.innerHTML = getPrinterName(); - } - }; - const load = obj.load; - obj.load = () => { - newTitle(); - load(context); - }; - return obj; -}; - -const getPrinterName = () => getPrinterLabel(context); - -const updatePrinterStatus = (state) => { - const linkState = state; - const elem = document.getElementById("printer-status"); - if (elem) { - elem.innerHTML = translateState(linkState); - } -}; - -const buildRouteTitle = (titleItems) => buildTitle([ - ...titleItems, - getPrinterName(), - process.env["APP_NAME"] -]); - -let currentModule = dashboard; -const fdm = { - routes: [ - { - path: "dashboard", - html: require("../../views/dashboard.html"), - module: updatePrinterTitle(dashboard), - getTitle: () => translate("home.link"), - }, - { - path: "question", - html: require("../../views/question.html"), - module: updatePrinterTitle(question), - }, - process.env.WITH_FILES ? - { - path: "files", - html: require("../../views/files.html"), - module: updatePrinterTitle(files), - getTitle: () => translate("proj.storage"), - } - : null, - process.env.WITH_SETTINGS ? - { - path: "settings", - html: require("../../views/settings.html"), - module: updatePrinterTitle(require("../components/settings.js").default), - getTitle: () => translate("settings.title"), - } - : null, - process.env.WITH_CONTROLS ? - { - path: "control", - html: require("../../views/control.html"), - module: updatePrinterTitle(require("../components/control.js").default), - getTitle: () => translate("control.link"), - } : null, - process.env.WITH_CAMERAS ? - { - path: "cameras", - html: require("../../views/cameras.html"), - module: updatePrinterTitle(require("../components/cameras.js").default), - getTitle: () => translate("cameras.link"), - } : null, - ].filter(route => route != null), - init: (apiResult) => { - context.update(apiResult); - initTemperatureGraph(); - }, - update: (apiResult) => { - context.update(apiResult); - - const page = currentRoute(); - const stateText = getStatusForTitle(context); - document.title = buildRouteTitle([ - stateText, - fdm.routes.find(route => route.path === page).getTitle() - ]); - - updateProperties("telemetry", context); - updatePrinterStatus(context.state); - updateTemperatureGraph(context.telemetry); - updateModule(); - }, - setConnected: (isConnected) => { - updateConnectionStatus({ - link: context.link, - isConnected, - }); - }, - setModule: (module) => { - currentModule = module; - }, - getContext: () => { - return context; - }, -}; - -const initTemperatureGraph = () => { - const maxTemp = 300; - - let map = new Map([ - ["temp-line-blue", []], - ["temp-line-orange", []], - ]); - - graph.init(map, maxTemp); - graph.render(); -}; - -const updateTemperatureGraph = (telemetry) => { - const now = new Date().getTime(); - graph.update("temp-line-blue", [now, telemetry.temperature.bed.current]); - graph.update("temp-line-orange", [now, telemetry.temperature.nozzle.current]); - graph.render(); -}; - -const updateModule = () => { - if (currentModule && currentModule.update) currentModule.update(context); -}; - -export default fdm; diff --git a/src/printer/index.js b/src/printer/index.js index 7464d4c3..330ab678 100644 --- a/src/printer/index.js +++ b/src/printer/index.js @@ -2,9 +2,174 @@ // Copyright (C) 2021 Prusa Research a.s. - www.prusa3d.com // SPDX-License-Identifier: GPL-3.0-or-later -const printer = (() => { - if (process.env.PRINTER_TYPE === "sla") return require("./sla"); - if (process.env.PRINTER_TYPE === "fdm") return require("./fdm"); -})().default; +import * as graph from "./components/temperature_graph"; +import dashboard from "./views/dashboard.js"; +import files from "./components/files"; +import question from "./components/question.js"; +import refill from "./views/refill.js"; +import { buildTitle, getPrinterLabel, getStatusForTitle } from "./common.js"; +import { updateProperties } from "./components/updateProperties.js"; +import { translate } from "../locale_provider"; +import { translateState } from "../state"; +import updateConnectionStatus from "./components/updateConnectionStatus"; +import { currentRoute } from "../router"; +import { Context } from "./context"; + +const context = new Context(); + +const updatePrinterTitle = (obj) => { + const newTitle = () => { + const label = document.getElementById("title-printer"); + if (label) { + label.innerHTML = getPrinterName(); + } + }; + const load = obj.load; + obj.load = () => { + newTitle(); + load(context); + }; + return obj; +}; + +const getPrinterName = () => getPrinterLabel(context); + +const updatePrinterStatus = (state) => { + const linkState = state; + const elem = document.getElementById("printer-status"); + if (elem) { + elem.innerHTML = translateState(linkState); + } +}; + +const buildRouteTitle = (titleItems) => + buildTitle([...titleItems, getPrinterName(), process.env["APP_NAME"]]); + +let currentModule = dashboard; +const printer = { + routes: [ + { + path: "dashboard", + html: require("../views/dashboard.html"), + module: updatePrinterTitle(dashboard), + getTitle: () => translate("home.link"), + }, + { + path: "question", + html: require("../views/question.html"), + module: updatePrinterTitle(question), + }, + process.env.PRINTER_TYPE === "sla" + ? { + path: "refill", + html: require("../views/refill.html"), + module: updatePrinterTitle(refill), + } + : null, + process.env.WITH_FILES + ? { + path: "files", + html: require("../views/files.html"), + module: updatePrinterTitle(files), + getTitle: () => translate("proj.storage"), + } + : null, + process.env.WITH_SETTINGS + ? { + path: "settings", + html: require("../views/settings.html"), + module: updatePrinterTitle( + require("./components/settings.js").default + ), + getTitle: () => translate("settings.title"), + } + : null, + process.env.WITH_CONTROLS + ? { + path: "control", + html: require("../views/control.html"), + module: updatePrinterTitle( + require("./components/control.js").default + ), + getTitle: () => translate("control.link"), + } + : null, + process.env.WITH_CAMERAS + ? { + path: "cameras", + html: require("../views/cameras.html"), + module: updatePrinterTitle( + require("./components/cameras.js").default + ), + getTitle: () => translate("cameras.link"), + } + : null, + ].filter((route) => route != null), + init: (apiResult) => { + context.update(apiResult); + initTemperatureGraph(); + }, + update: (apiResult) => { + context.update(apiResult); + + const page = currentRoute(); + const stateText = getStatusForTitle(context); + document.title = buildRouteTitle([ + stateText, + printer.routes.find((route) => route.path === page).getTitle(), + ]); + + updateProperties("telemetry", context); + updatePrinterStatus(context.state); + updateTemperatureGraph(context.telemetry); + updateModule(); + }, + setConnected: (isConnected) => { + updateConnectionStatus({ + link: context.link, + isConnected, + }); + }, + setModule: (module) => { + currentModule = module; + }, + getContext: () => { + return context; + }, +}; + +const initTemperatureGraph = () => { + let maxTemp = 300; + + const map = new Map([ + ["temp-line-blue", []], + ["temp-line-orange", []], + ]); + + if (process.env.PRINTER_TYPE === "sla") { + map.set("temp-line-yellow", []) + } + + graph.init(map, maxTemp); + graph.render(); +}; + +const updateTemperatureGraph = (telemetry) => { + const now = new Date().getTime(); + if (process.env.PRINTER_TYPE === "fdm") { + graph.update("temp-line-blue", [now, telemetry.temperature.bed.current]); + graph.update("temp-line-orange", [now, telemetry.temperature.nozzle.current]); + } + if (process.env.PRINTER_TYPE === "sla") { + graph.update("temp-line-blue", [now, telemetry.temperature.ambient.current]); + graph.update("temp-line-orange", [now, telemetry.temperature.cpu.current]); + graph.update("temp-line-yellow", [now, telemetry.temperature.uvLED.current]); + } + graph.render(); +}; + +const updateModule = () => { + if (currentModule && currentModule.update) currentModule.update(context); +}; export default printer; diff --git a/src/printer/sla/dashboard.js b/src/printer/sla/dashboard.js deleted file mode 100644 index b4cc7f91..00000000 --- a/src/printer/sla/dashboard.js +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of the Prusa Link Web -// Copyright (C) 2021 Prusa Research a.s. - www.prusa3d.com -// SPDX-License-Identifier: GPL-3.0-or-later - -import * as graph from "../components/temperature_graph"; -import upload from "../components/upload"; -import { translate } from "../../locale_provider"; -import * as job from "../components/job"; -import { LinkState } from "../../state"; -import sla from "."; -import { getStatusForTitle } from "../common"; - -const load = (context) => { - translate("home.link", { query: "#title-status-label" }); - upload.init("local", "", context.fileExtensions); - graph.render(); - update(context); -}; - -const update = (context) => { - const linkState = context.state; - job.update(context); - upload.update(linkState); -}; - -export default { load, update }; diff --git a/src/printer/sla/index.js b/src/printer/sla/index.js deleted file mode 100644 index 73fbf861..00000000 --- a/src/printer/sla/index.js +++ /dev/null @@ -1,219 +0,0 @@ -// This file is part of the Prusa Link Web -// Copyright (C) 2021 Prusa Research a.s. - www.prusa3d.com -// SPDX-License-Identifier: GPL-3.0-or-later - -import * as graph from "../components/temperature_graph"; -import dashboard from "./dashboard.js"; -import files from "../components/files"; -import question from "../components/question.js"; -import refill from "./refill.js"; -import { updateProperties } from "../components/updateProperties.js"; -import { translate } from "../../locale_provider"; -import { showLoading, hideLoading } from "../../helpers/element"; -import { getPrinterLabel, getStatusForTitle } from "../common.js"; -import updateConnectionStatus from "../components/updateConnectionStatus"; - -import { currentRoute } from "../../router"; - -const context = { - /** Result of `api/v1/status */ - status: undefined, - - /** Result of `api/version`. */ - version: undefined, - /** Result of `api/printer`. */ - printer: undefined, - /** Result of `api/job`.job */ - current: undefined, - /** Result of `api/connection`. */ - connection: undefined, - /** Supported file extensions. */ - fileExtensions: [], -}; - -const updatePrinterTitle = (obj) => { - const newHostname = () => { - const hostnameLabel = document.getElementById("title-printer"); - if (hostnameLabel) { - hostnameLabel.innerHTML = getPrinterName(); - } - }; - const load = obj.load; - obj.load = () => { - newHostname(); - load(context); - }; - return obj; -}; - -const getPrinterName = () => getPrinterLabel(context); - - -const updatePrinterStatus = (state) => { - if (state) { - const query = { query: "#printer-status" }; - if (state.flags.error || state.flags.closedOrError) - translate("ntf.error", query); - else if (!state.flags.operational) - translate("prop.st-busy", query); - else if (state.flags.paused) { - if (state.text === "Pour in resin") - translate("prop.st-pour-resin", query); - else if (state.text === "Feed me") - translate("prop.st-feedme", query); - else - translate("prop.st-paused", query); - } - else if (state.flags.printing) - translate("prop.st-printing", query); - else - translate("prop.st-idle", query); - } -}; - -const buildRouteTitle = (titleItems) => buildTitle([ - ...titleItems, - getPrinterName(), - process.env["APP_NAME"] -]); - -let currentModule = dashboard; -const sla = { - routes: [ - { - path: "dashboard", - html: require("../../views/dashboard.html"), - module: updatePrinterTitle(dashboard), - getTitle: () => translate("home.link"), - }, - { - path: "question", - html: require("../../views/question.html"), - module: updatePrinterTitle(question), - }, - { - path: "refill", - html: require("../../views/refill.html"), - module: updatePrinterTitle(refill), - }, - process.env.WITH_FILES ? - { - path: "files", - html: require("../../views/files.html"), - module: updatePrinterTitle(files), - getTitle: () => translate("proj.storage"), - } - : null, - process.env.WITH_SETTINGS ? - { - path: "settings", - html: require("../../views/settings.html"), - module: updatePrinterTitle(require("../components/settings.js").default), - getTitle: () => translate("settings.title"), - } - : null, - process.env.WITH_CONTROLS ? - { - path: "control", - html: require("../../views/control.html"), - module: updatePrinterTitle(require("../components/control.js").default), - getTitle: () => translate("control.link"), - } : null, - ].filter(route => route != null), - init: (apiResult) => { - updateContext(apiResult); - const exts = apiResult.profiles?.payload?.data?.profiles[0]?.projectExtensions; - context.fileExtensions = exts || process.env.FILE_EXTENSIONS; - initTemperatureGraph(); - }, - update: (apiResult) => { - const page = currentRoute(); - const stateText = getStatusForTitle(context); - document.title = buildRouteTitle([ - stateText, - fdm.routes.find(route => route.path === page).getTitle() - ]); - - updateContext(apiResult); - if (context.printer.state.flags.operational) - hideLoading(); - else - showLoading(); - updateProperties("telemetry", context.printer); - updatePrinterStatus(context.printer.state); - updateTemperatureGraph(context.printer); - updateModule(); - }, - setConnected: (isConnected) => { - updateConnectionStatus({ - connection: context.connection, - isConnected, - }); - }, - setModule: (module) => { - currentModule = module; - }, - getContext: () => { - return context; - }, -}; - -const updateContext = ({ status, connection, job, printer, version }) => { - if (status?.ok && status.payload) { - context.status = status.payload.data; - } - - /* - if (connection?.ok && connection.payload) { - context.connection = connection.payload.data; - } - if (job?.ok && job.payload) { - context.current = job.payload.data; - } - if (printer?.ok && printer.payload) { - context.printer = printer.payload.data; - } - */ - - if (version?.ok && version.payload) { - context.version = version.payload; - } -} - -const initTemperatureGraph = () => { - const maxTemp = 100; - - let map = new Map([ - ["temp-line-blue", []], - ["temp-line-orange", []], - ["temp-line-yellow", []], - ]); - - graph.init(map, maxTemp); - graph.render(); -}; - -const updateTemperatureGraph = (data) => { - const now = new Date().getTime(); - graph.update("temp-line-blue", [ - now, - data.temperature.chamber.actual, // Original Prusa SL1 uses Chamber for ambient temp - ]); - graph.update("temp-line-orange", [ - now, - data.temperature.tool0 - .actual /* TODO: API collision - Original Prusa SL1 uses - Extruderfor UV LED temp - current API provides only tool0 */, - ]); - graph.update("temp-line-yellow", [ - now, - data.temperature.bed.actual, // Original Prusa SL1 uses Bed for CPU temperature - ]); - graph.render(); -}; - -const updateModule = () => { - if (currentModule && currentModule.update) currentModule.update(context); -}; - -export default sla; diff --git a/src/printer/sla/temperature.js b/src/printer/sla/temperature.js deleted file mode 100644 index fcc8620c..00000000 --- a/src/printer/sla/temperature.js +++ /dev/null @@ -1,13 +0,0 @@ -// This file is part of the Prusa Link Web -// Copyright (C) 2021 Prusa Research a.s. - www.prusa3d.com -// SPDX-License-Identifier: GPL-3.0-or-later - -import * as graph from "../components/temperature_graph"; -import { translate } from "../../locale_provider"; - -const load = () => { - translate("temps.title", { query: "#title-status-label" }); - graph.render(); -}; - -export default { load }; diff --git a/src/printer/fdm/dashboard.js b/src/printer/views/dashboard.js similarity index 92% rename from src/printer/fdm/dashboard.js rename to src/printer/views/dashboard.js index babb5add..ede75f67 100644 --- a/src/printer/fdm/dashboard.js +++ b/src/printer/views/dashboard.js @@ -7,10 +7,7 @@ import upload from "../components/upload"; import cameras from "../components/cameras"; import { translate } from "../../locale_provider"; import * as job from "../components/job"; -import { LinkState } from "../../state"; import { getJson } from "../../auth"; -import fdm from "."; -import { getStatusForTitle } from "../common"; const load = (context) => { translate("home.link", { query: "#title-status-label" }); diff --git a/src/printer/sla/exposure.js b/src/printer/views/exposure.js similarity index 91% rename from src/printer/sla/exposure.js rename to src/printer/views/exposure.js index 86857368..7a447763 100644 --- a/src/printer/sla/exposure.js +++ b/src/printer/views/exposure.js @@ -6,6 +6,7 @@ import { getJson } from "../../auth"; import { handleError } from "../components/errors"; import { doQuestion } from "../components/question"; import { translate } from "../../locale_provider"; +import printer from ".."; // import { setBusy } from "../components/busy"; const repeatInterval = 250; // milliseconds, how often should the value be updated when holding the button @@ -78,19 +79,20 @@ const setValue = (item_name, value, min, max, step) => { * @param {object} elements - {id: HTMLElement} * @param {HTMLDivElement} div html element to insert in modal */ -const setUpElements = (file, elements, div) => { +const setUpElements = (job, elements, div) => { const template = document.getElementById("exposure-item").content; + const file = job.file; div.className = "modal-exposure"; for (let expo in config) { - if (expo in file) { + if (expo in job && job[expo] !== undefined) { const elm = document.importNode(template, true); var minus = elm.getElementById("minus"); var plus = elm.getElementById("plus"); elm.getElementById("desc").innerHTML = config[expo].text; const value = elm.getElementById("value"); - value.dataset.value = file[expo].toFixed(0); + value.dataset.value = job[expo].toFixed(0); if (expo == "exposureUserProfile") { - switch(parseInt(file[expo])) { + switch(parseInt(job[expo])) { case 0: value.innerHTML = translate("exp-times.faster"); break; @@ -109,7 +111,7 @@ const setUpElements = (file, elements, div) => { plus = elm.getElementById("next"); minus.style.display = "block"; plus.style.display = "block"; - } else value.innerHTML = (file[expo] / 1000).toFixed(1); + } else value.innerHTML = (job[expo] / 1000).toFixed(1); const [min, max] = config[expo].limit; const setMinus = setValue(expo, value, min, max, -config[expo].step); minus.onclick = setMinus; @@ -141,12 +143,13 @@ const setUpElements = (file, elements, div) => { * Create a question for set up the exposure times * @param {object} file - job file information */ -const changeExposureTimesQuestion = (jobFile) => { +const changeExposureTimesQuestion = (job) => { + const context = printer.getContext(); const page = window.location.hash; history.pushState(null, document.title, page); const elements = {}; const div = document.createElement("div"); - setUpElements(jobFile, elements, div); + setUpElements(job, elements, div); doQuestion({ title: translate("btn.chg-print-set"), questionChildren: [div], @@ -164,8 +167,9 @@ const changeExposureTimesQuestion = (jobFile) => { }, body: JSON.stringify(result), }) + .then(() => context.updateJobDetails()) .catch((result) => handleError(result)) - .finally((result) => close()); + .finally(() => close()); }, yesText: translate("btn.save-chgs"), noText: translate("btn.cancel"), diff --git a/src/printer/sla/refill.js b/src/printer/views/refill.js similarity index 89% rename from src/printer/sla/refill.js rename to src/printer/views/refill.js index 6ce541a5..38af0c23 100644 --- a/src/printer/sla/refill.js +++ b/src/printer/views/refill.js @@ -6,14 +6,14 @@ import { getJson } from "../../auth"; import { handleError } from "../components/errors"; import { resumeJob } from "../components/jobActions"; -export const resinRefill = () => { +export const resinRefill = (jobId) => { getJson("/api/system/commands/custom/resinrefill", { method: "POST", headers: { "Content-Type": "application/json", } }).then(() => { - resumeJob(); + resumeJob(jobId); }).catch((result) => handleError(result)); }; diff --git a/src/printer/fdm/temperature.js b/src/printer/views/temperature.js similarity index 100% rename from src/printer/fdm/temperature.js rename to src/printer/views/temperature.js diff --git a/src/state.js b/src/state.js index a080293f..84745ebb 100644 --- a/src/state.js +++ b/src/state.js @@ -6,6 +6,8 @@ export const LinkState = { IDLE: "IDLE", READY: "READY", BUSY: "BUSY", + POUR_IN_RESIN: "POUR IN RESIN", + REFILL: "FEED ME", PRINTING: "PRINTING", PAUSED: "PAUSED", FINISHED: "FINISHED", @@ -23,6 +25,9 @@ export const LinkState = { case "STOPPED": return LinkState.STOPPED; case "ERROR": return LinkState.ERROR; case "ATTENTION": return LinkState.ATTENTION; + // sla specific + case "POUR IN RESIN": return LinkState.POUR_IN_RESIN; + case "FEED ME": return LinkState.REFILL; default: console.error(`Unsupported state: ${linkState}`); return LinkState.UNKNOWN; @@ -33,12 +38,13 @@ export const LinkState = { export const OperationalStates = [ LinkState.IDLE, LinkState.READY, - LinkState.FINISHED + LinkState.FINISHED, ]; export const JobPendingStates = [ LinkState.PRINTING, LinkState.PAUSED, + LinkState.POUR_IN_RESIN, ]; export const translateState = (state) => { @@ -52,6 +58,8 @@ export const translateState = (state) => { case LinkState.STOPPED: return translate("prop.st-stopped"); case LinkState.ERROR: return translate("prop.st-error"); case LinkState.ATTENTION: return translate("prop.st-attention"); + case LinkState.POUR_IN_RESIN: return translate("prop.st-pour-resin"); + case LinkState.REFILL: return translate("prop.st-feedme"); default: console.error(`Unsupported state: ${state}`); return translate("prop.st-unknown"); diff --git a/templates/components/telemetry.html b/templates/components/telemetry.html index 422b8fc6..fd494d3a 100644 --- a/templates/components/telemetry.html +++ b/templates/components/telemetry.html @@ -9,12 +9,12 @@ {% if env.PRINTER_TYPE == "sla" %} {% set telemetry_list = [ - {'text': 'CPU temperature', label: 'prop.temp-cpu', 'icon': 'temperature_color.svg', 'format': 'temp', "locations": ["temperature.bed.actual"], enabled: true }, - {'text': 'UV LED temperature', label: 'prop.temp-led', 'icon': 'temperature_color.svg', 'format': 'temp', "locations": ["temperature.tool0.actual"], enabled: true }, - {'text': 'ambient temperature', label: 'prop.temp-amb', 'icon': 'temperature_color.svg', 'format': 'temp', "locations": ["temperature.chamber.actual"], enabled: true }, - {'text': 'UV LED fan', label: 'prop.fan-led', 'icon': 'fan_color.svg', 'format': 'fan', "location": "telemetry.fanUvLed", enabled: true }, - {'text': 'blower fan', label: 'prop.fan-blower', 'icon': 'fan_color.svg', 'format': 'fan', "location": "telemetry.fanBlower", enabled: true }, - {'text': 'rear fan', label: 'prop.fan-rear', 'icon': 'fan_color.svg', 'format': 'fan', "location": "telemetry.fanRear", enabled: true }, + {'text': 'CPU temperature', label: 'prop.temp-cpu', 'icon': 'temperature_color.svg', 'format': 'temp', "locations": ["telemetry.temperature.cpu.current"], enabled: true }, + {'text': 'UV LED temperature', label: 'prop.temp-led', 'icon': 'temperature_color.svg', 'format': 'temp', "locations": ["telemetry.temperature.uvLED.current"], enabled: true }, + {'text': 'ambient temperature', label: 'prop.temp-amb', 'icon': 'temperature_color.svg', 'format': 'temp', "locations": ["telemetry.temperature.ambient.current"], enabled: true }, + {'text': 'UV LED fan', label: 'prop.fan-led', 'icon': 'fan_color.svg', 'format': 'fan', "location": "telemetry.fan.uvLED", enabled: true }, + {'text': 'blower fan', label: 'prop.fan-blower', 'icon': 'fan_color.svg', 'format': 'fan', "location": "telemetry.fan.blower", enabled: true }, + {'text': 'rear fan', label: 'prop.fan-rear', 'icon': 'fan_color.svg', 'format': 'fan', "location": "telemetry.fan.rear", enabled: true }, {'text': 'cover state', label: 'prop.cover', 'icon': 'cover_color.svg', 'format': 'cover', "location": "telemetry.coverClosed", enabled: true } ] %}