UNPKG

@fdm-monster/server

Version:

FDM Monster is a bulk OctoPrint manager to set up, configure and monitor 3D printers. Our aim is to provide extremely optimized websocket performance and reliability.

235 lines (234 loc) 8.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "PrusaLinkApi", { enumerable: true, get: function() { return PrusaLinkApi; } }); const _printerapiinterface = require("../printer-api.interface"); const _prusalinkhttpclientbuilder = require("./utils/prusa-link-http-client.builder"); const _fs = require("fs"); const _eventconstants = require("../../constants/event.constants"); const _runtimeexceptions = require("../../exceptions/runtime.exceptions"); const defaultLog = { adapter: "prusa-link" }; class PrusaLinkApi { eventEmitter2; httpClientFactory; settingsStore; printerLogin; logger; authHeader; constructor(loggerFactory, eventEmitter2, httpClientFactory, settingsStore, printerLogin){ this.eventEmitter2 = eventEmitter2; this.httpClientFactory = httpClientFactory; this.settingsStore = settingsStore; this.printerLogin = printerLogin; this.authHeader = null; this.logger = loggerFactory(PrusaLinkApi.name); this.logger.debug("Constructed api client", this.logMeta()); } get type() { return _printerapiinterface.PrusaLinkType; } set login(login) { this.printerLogin = login; } get client() { return this.createClient(); } async getVersion() { const response = await this.client.get("/api/version"); return response.data.server; } async getFiles() { const response = await this.client.get("/api/files"); return response.data.files.filter((dir)=>dir.path === "/usb")[0].children.map((f)=>({ path: f.display, date: null, size: -1 })); } async getFile(path) { const response = await this.getFileRaw(path); return { path: response.data.name, size: response.data.size, date: null }; } async getStatus() { const response = await this.client.get("/api/v1/status"); return response.data; } async getPrinterState() { const response = await this.client.get("/api/printer"); return response.data; } async getJobState() { const response = await this.client.get("/api/job"); return response.data; } connect() { throw new Error("Method not implemented."); } disconnect() { throw new Error("Method not implemented."); } restartServer() { throw new Error("Method not implemented."); } restartHost() { throw new Error("Method not implemented."); } restartPrinterFirmware() { throw new Error("Method not implemented."); } async startPrint(path) { await this.client.post(`/api/v1/files/usb/${path}`); } async pausePrint() { const jobId = await this.getCurrentJobId(); if (!jobId) { this.logger.warn("Job pause command did not complete, job or job id not set"); return; } await this.client.put(`/api/v1/job/${jobId}/pause`); } async resumePrint() { const jobId = await this.getCurrentJobId(); if (!jobId) { this.logger.warn("Job resume command did not complete, job or job id not set"); return; } await this.client.put(`/api/v1/job/${jobId}/resume`); } async cancelPrint() { const jobId = await this.getCurrentJobId(); if (!jobId) { this.logger.warn("Job cancel command did not complete, job or job id not set"); return; } await this.client.delete(`/api/v1/job/${jobId}`); } quickStop() { throw new Error("Method not implemented."); } sendGcode(script) { throw new Error("Method not implemented."); } movePrintHead(amounts) { throw new Error("Method not implemented."); } homeAxes(axes) { throw new Error("Method not implemented."); } async downloadFile(path) { const fileReference = await this.getFileRaw(path); const pathUrl = fileReference.data.refs.download; return await this.client.get(pathUrl, { responseType: "stream" }); } async getFileChunk(path, startBytes, endBytes) { const fileReference = await this.getFileRaw(path); const pathUrl = fileReference.data.refs.download; return await this.createClient((o)=>o.withHeaders({ Range: `bytes=${startBytes}-${endBytes}` })).get(pathUrl); } async uploadFile(multerFileOrBuffer, startPrint, progressToken) { try { let fileBuffer; const filename = multerFileOrBuffer.originalname; if (Buffer.isBuffer(multerFileOrBuffer)) { this.logger.log("Using file directly from memory buffer for upload"); fileBuffer = multerFileOrBuffer; } else { const filePath = multerFileOrBuffer.path; this.logger.log(`Reading file from disk for upload: ${filePath}`); fileBuffer = (0, _fs.readFileSync)(filePath); } const contentLength = fileBuffer.length; const response = await this.createClient((b)=>{ b.withHeaders({ "Content-Length": contentLength.toString(), "Overwrite": "?1", "Print-After-Upload": startPrint ? "?1" : "?0" }).withTimeout(this.settingsStore.getTimeoutSettings().apiUploadTimeout).withOnUploadProgress((p)=>{ if (progressToken) { this.eventEmitter2.emit(`${(0, _eventconstants.uploadProgressEvent)(progressToken)}`, progressToken, p); } }); }).put(`/api/v1/files/usb/${encodeURIComponent(filename)}`, fileBuffer); if (progressToken) { this.eventEmitter2.emit(`${(0, _eventconstants.uploadDoneEvent)(progressToken)}`, progressToken); } return response.data; } catch (e) { if (progressToken) { this.eventEmitter2.emit(`${(0, _eventconstants.uploadFailedEvent)(progressToken)}`, progressToken, e?.message); } let data; try { data = JSON.parse(e.response?.body); } catch { data = e.response?.body; } throw new _runtimeexceptions.ExternalServiceError({ error: e.message, statusCode: e.response?.statusCode, data, success: false, stack: e.stack }, "Prusa-Link"); } } async deleteFile(path) { await this.client.delete(`/api/v1/files/usb/${path}`); } async deleteFolder(path) { await this.client.delete(`/api/v1/files/usb/${path}`); } getSettings() { throw new Error("Method not implemented."); } getReprintState() { throw new Error("Method not implemented."); } getFileRaw(path) { return this.client.get(`/api/v1/files/usb/${path}`); } async getCurrentJobId() { const status = await this.getStatus(); return status.job?.id; } createClient(buildFluentOptions) { const builder = new _prusalinkhttpclientbuilder.PrusaLinkHttpClientBuilder(); return this.httpClientFactory.createClientWithBaseUrl(builder, this.printerLogin.printerURL, (b)=>{ this.logger.debug("Building API client", this.logMeta()); b.withDigestAuth(this.printerLogin.username, this.printerLogin.password, (error)=>{ this.logger.error("Authentication error occurred", error); }, (error, attemptCount)=>{ this.logger.log(`Authentication attempt count ${attemptCount} for method ${error.config?.method?.toUpperCase()} path ${error.config?.url}`, this.logMeta()); }, (authHeader)=>{ this.logger.debug("Authentication successful, saving auth header for later reuse", this.logMeta()); this.authHeader = authHeader; }); if (this.authHeader) { b.withAuthHeader(this.authHeader); } if (buildFluentOptions && typeof buildFluentOptions === "function") { buildFluentOptions(b); } }); } logMeta() { return defaultLog; } } //# sourceMappingURL=prusa-link.api.js.map