190 lines
5.6 KiB
JavaScript
190 lines
5.6 KiB
JavaScript
// printer-manager.js - Manages multiple printer connections through MongoDB
|
|
import { PrinterClient } from "./printerclient.js";
|
|
import { printerModel } from "../database/printer.schema.js"; // Import your printer model
|
|
import { printSubJobModel } from "../database/printsubjob.schema.js"; // Import your subjob model
|
|
import { loadConfig } from "../config.js";
|
|
import log4js from "log4js";
|
|
import { printJobModel } from "../database/printjob.schema.js";
|
|
// Load configuration
|
|
const config = loadConfig();
|
|
|
|
const logger = log4js.getLogger("Printer Manager");
|
|
logger.level = config.server.logLevel;
|
|
|
|
export class PrinterManager {
|
|
constructor(config) {
|
|
this.config = config;
|
|
this.printerClientConnections = new Map();
|
|
this.statusCheckInterval = null;
|
|
this.initializePrinterConnections();
|
|
}
|
|
|
|
async initializePrinterConnections() {
|
|
try {
|
|
// Get all printers from the database
|
|
const printers = await printerModel.find({}).populate({ path: "currentFilamentStock",
|
|
populate: {
|
|
path: "filament",
|
|
},});
|
|
|
|
for (const printer of printers) {
|
|
await this.connectToPrinter(printer);
|
|
}
|
|
|
|
logger.info(`Initialized connections to ${printers.length} printers`);
|
|
} catch (error) {
|
|
logger.error(`Error initializing printer connections: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
async connectToPrinter(printer) {
|
|
// Create and store the connection
|
|
const printerClientConnection = new PrinterClient(
|
|
printer,
|
|
this,
|
|
this.socketManager,
|
|
);
|
|
this.printerClientConnections.set(printer.id, printerClientConnection);
|
|
|
|
// Connect to the printer
|
|
await printerClientConnection.connect();
|
|
|
|
logger.info(`Connected to printer: ${printer.name} (${printer.id})`);
|
|
return true;
|
|
}
|
|
|
|
getPrinterClient(printerId) {
|
|
return this.printerClientConnections.get(printerId);
|
|
}
|
|
|
|
getAllPrinterClients() {
|
|
return this.printerClientConnections.values();
|
|
}
|
|
|
|
// Process command for a specific printer
|
|
async processPrinterCommand(command) {
|
|
const printerId = command.params.printerId;
|
|
const printerClientConnection =
|
|
this.printerClientConnections.get(printerId);
|
|
if (!printerClientConnection) {
|
|
return {
|
|
success: false,
|
|
error: `Printer with ID ${printerId} not found`,
|
|
};
|
|
}
|
|
|
|
return await printerClientConnection.sendPrinterCommand(command);
|
|
}
|
|
|
|
async updateSubscription(printerId, socketId, mergedSubscription) {
|
|
const printerClientConnection =
|
|
this.printerClientConnections.get(printerId);
|
|
if (!printerClientConnection) {
|
|
return {
|
|
success: false,
|
|
error: `Printer with ID ${printerId} not found`,
|
|
};
|
|
}
|
|
printerClientConnection.subscriptions.set(socketId, mergedSubscription);
|
|
return await printerClientConnection.updateSubscriptions();
|
|
}
|
|
|
|
// Close all printer connections
|
|
closeAllConnections() {
|
|
for (const printerClientConnection of this.printerClientConnections.values()) {
|
|
if (printerClientConnection.socket) {
|
|
printerClientConnection.socket.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
setSocketManager(socketManager) {
|
|
this.socketManager = socketManager;
|
|
}
|
|
|
|
async downloadGCODE(gcodeFileId) {
|
|
logger.info(`Downloading G-code file ${gcodeFileId}`);
|
|
try {
|
|
// Download the G-code file with authentication
|
|
const url = `http://localhost:8080/gcodefiles/${gcodeFileId}/content/`;
|
|
const response = await fetch(url, {
|
|
headers: {
|
|
Authorization: `Bearer ${this.socketManager.socketClientConnections.values().next().value.socket.handshake.auth.token}`,
|
|
},
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error(
|
|
`Failed to download G-code file: ${response.statusText}`,
|
|
);
|
|
}
|
|
const gcodeContent = await response.blob();
|
|
|
|
logger.info(`G-code file ${gcodeFileId} downloaded!`);
|
|
|
|
return gcodeContent;
|
|
} catch (error) {
|
|
logger.error("Error in deployGcodeToAllPrinters:", error);
|
|
return {
|
|
success: false,
|
|
error: error.message,
|
|
};
|
|
}
|
|
}
|
|
|
|
async deployPrintJob(printJobId) {
|
|
logger.info(`Deploying print job ${printJobId}`);
|
|
const printJob = await printJobModel
|
|
.findById(printJobId)
|
|
.populate("printers")
|
|
.populate("subJobs");
|
|
if (!printJob) {
|
|
throw new Error("Print job not found");
|
|
}
|
|
|
|
if (!printJob.gcodeFile) {
|
|
throw new Error("No G-code file associated with this print job");
|
|
}
|
|
|
|
const gcodeFileId = printJob.gcodeFile.toString();
|
|
const fileName = `${printJob.id}.gcode`;
|
|
|
|
const gcodeFile = await this.downloadGCODE(gcodeFileId);
|
|
|
|
for (const printer of printJob.printers) {
|
|
const printerClient = this.getPrinterClient(printer.id);
|
|
if (!printerClient) {
|
|
throw new Error(`Printer with ID ${printer.id} not found`);
|
|
return false;
|
|
}
|
|
await printerClient.uploadGcodeFile(gcodeFile, fileName);
|
|
await printerClient.deploySubJobs(printJob.id);
|
|
}
|
|
|
|
printJob.state = { type: "queued" };
|
|
printJob.updatedAt = new Date();
|
|
await printJob.save();
|
|
|
|
this.socketManager.broadcast("notify_job_update", {
|
|
id: printJob.id,
|
|
state: { type: "queued" },
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
async cancelSubJob(subJobId) {
|
|
logger.info(`Canceling sub job ${subJobId}`);
|
|
const subJob = await printSubJobModel.findById(subJobId);
|
|
if (!subJob) {
|
|
throw new Error("Sub job not found");
|
|
}
|
|
const printerClient = this.getPrinterClient(subJob.printer.toString());
|
|
if (!printerClient) {
|
|
throw new Error(`Printer with ID ${printer.id} not found`);
|
|
return false;
|
|
}
|
|
await printerClient.cancelSubJob(subJob.subJobId);
|
|
return true;
|
|
}
|
|
}
|