Update dependencies, improve document printer management, and add workspace configuration
Some checks failed
farmcontrol/farmcontrol-server/pipeline/head There was a failure building this commit
Some checks failed
farmcontrol/farmcontrol-server/pipeline/head There was a failure building this commit
This commit is contained in:
parent
3cc2cbe020
commit
ffa6d84251
@ -5,7 +5,7 @@
|
||||
"apiUrl": "https://dev.tombutcher.work/api",
|
||||
"host": {
|
||||
"id": "691a1db49ce913faf0e51284",
|
||||
"authCode": "FvD3qnNh8FP_xJShlECfYshqQawfD5oPP4xlGOFV2vQIDPRxkAjH4rO6sIgpLucX"
|
||||
"authCode": "9uu3DC0si__-F9FnGWTKudle5z6yZasFMlKohnShElPekRYteh-LlZaksHOXFfOO"
|
||||
}
|
||||
},
|
||||
"production": {
|
||||
|
||||
53
package.json
53
package.json
@ -20,45 +20,46 @@
|
||||
"author": "Tom Butcher",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.13.2",
|
||||
"canvas": "^3.2.0",
|
||||
"axios": "^1.16.1",
|
||||
"canvas": "^3.2.3",
|
||||
"etcd3": "^1.1.2",
|
||||
"express": "^5.1.0",
|
||||
"express": "^5.2.1",
|
||||
"form-data": "^4.0.5",
|
||||
"ipp": "^2.0.1",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"jsonwebtoken": "^9.0.3",
|
||||
"keycloak-connect": "^26.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash": "^4.18.1",
|
||||
"log4js": "^6.9.1",
|
||||
"mongoose": "^9.0.0",
|
||||
"mongoose": "^9.6.2",
|
||||
"node-cache": "^5.1.2",
|
||||
"node-thermal-printer": "^4.5.0",
|
||||
"pdf-to-img": "^5.0.0",
|
||||
"node-thermal-printer": "^4.6.0",
|
||||
"pdf-to-img": "^6.1.0",
|
||||
"sharp": "^0.34.5",
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"ws": "^8.18.3"
|
||||
"socket.io": "^4.8.3",
|
||||
"socket.io-client": "^4.8.3",
|
||||
"ws": "^8.20.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/icons": "^6.1.0",
|
||||
"antd": "^5.28.0",
|
||||
"@electron/rebuild": "^4.0.1",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"@ant-design/icons": "^6.2.3",
|
||||
"@electron/rebuild": "^4.0.4",
|
||||
"@vitejs/plugin-react": "^6.0.2",
|
||||
"antd": "^5.29.2",
|
||||
"concurrently": "^9.2.1",
|
||||
"cross-env": "^10.1.0",
|
||||
"electron": "^38.7.1",
|
||||
"electron-builder": "^26.0.12",
|
||||
"jest": "^30.2.0",
|
||||
"nodemon": "^3.1.11",
|
||||
"electron": "^42.1.0",
|
||||
"electron-builder": "^26.8.1",
|
||||
"jest": "^30.4.2",
|
||||
"nodemon": "^3.1.14",
|
||||
"pkg": "^5.8.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"rimraf": "^6.1.2",
|
||||
"shx": "^0.3.4",
|
||||
"supertest": "^7.1.4",
|
||||
"vite": "^7.2.4",
|
||||
"react": "^19.2.6",
|
||||
"react-dom": "^19.2.6",
|
||||
"rimraf": "^6.1.3",
|
||||
"shx": "^0.4.0",
|
||||
"supertest": "^7.2.2",
|
||||
"vite": "^8.0.13",
|
||||
"vite-plugin-svgo": "^2.0.0",
|
||||
"vite-plugin-svgr": "^4.5.0"
|
||||
"vite-plugin-svgr": "^5.2.0"
|
||||
},
|
||||
"pkg": {
|
||||
"assets": [
|
||||
|
||||
2922
pnpm-lock.yaml
generated
2922
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
9
pnpm-workspace.yaml
Normal file
9
pnpm-workspace.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
allowBuilds:
|
||||
canvas: true
|
||||
chromedriver: true
|
||||
electron-winstaller: true
|
||||
electron: true
|
||||
esbuild: true
|
||||
protobufjs: true
|
||||
sharp: true
|
||||
unrs-resolver: true
|
||||
@ -15,7 +15,7 @@ export class DocumentPrinterClient {
|
||||
documentPrinter = {
|
||||
connection: { interface: "cups", host: "localhost", port: 9100 },
|
||||
},
|
||||
documentPrinterManager
|
||||
documentPrinterManager,
|
||||
) {
|
||||
this.id = documentPrinter._id;
|
||||
this.documentPrinter = documentPrinter;
|
||||
@ -23,9 +23,10 @@ export class DocumentPrinterClient {
|
||||
this.queue = [];
|
||||
this.documentPrinterManager = documentPrinterManager;
|
||||
this.currentJob = null;
|
||||
this.active = documentPrinter.active == true;
|
||||
this.socketClient = documentPrinterManager.socketClient;
|
||||
this.interface = documentPrinter.connection.interface || "cups"; // cups, receipt, or os
|
||||
this.state = { type: "offline" };
|
||||
this.state = { type: this.active == true ? "offline" : "inactive" };
|
||||
this.isOnline = documentPrinter.online || false;
|
||||
this.shouldReconnect = true;
|
||||
this.isProcessingQueue = false;
|
||||
@ -38,7 +39,7 @@ export class DocumentPrinterClient {
|
||||
|
||||
initializeInterface() {
|
||||
logger.info(
|
||||
`Initializing ${this.interface} interface for document printer ${this.id}`
|
||||
`Initializing ${this.interface} interface for document printer ${this.id}`,
|
||||
);
|
||||
switch (this.interface) {
|
||||
case "cups":
|
||||
@ -104,6 +105,16 @@ export class DocumentPrinterClient {
|
||||
await this.reconnect();
|
||||
}
|
||||
}
|
||||
|
||||
this.documentPrinter = { ...this.documentPrinter, ...data };
|
||||
|
||||
if (Object.hasOwn(data || {}, "active") && data.active != this.active) {
|
||||
if (data.active == true) {
|
||||
await this.setActive();
|
||||
} else {
|
||||
await this.setInactive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerEventHandlers() {
|
||||
@ -126,8 +137,18 @@ export class DocumentPrinterClient {
|
||||
}
|
||||
|
||||
async connect() {
|
||||
if (this.active == false) {
|
||||
logger.info(
|
||||
`Document printer ${this.id} is not active, skipping connection`,
|
||||
);
|
||||
this.shouldReconnect = false;
|
||||
this.isOnline = false;
|
||||
this.state = { type: "inactive" };
|
||||
await this.updateDocumentPrinterState();
|
||||
return false;
|
||||
}
|
||||
logger.info(
|
||||
`Connecting to document printer ${this.id} (${this.interface})`
|
||||
`Connecting to document printer ${this.id} (${this.interface})`,
|
||||
);
|
||||
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
@ -140,7 +161,7 @@ export class DocumentPrinterClient {
|
||||
|
||||
if (!this.printerInterface) {
|
||||
logger.error(
|
||||
`Cannot connect: No interface initialized for ${this.interface}`
|
||||
`Cannot connect: No interface initialized for ${this.interface}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -150,7 +171,7 @@ export class DocumentPrinterClient {
|
||||
if (result.error) {
|
||||
logger.error(
|
||||
`Error connecting to document printer ${this.documentPrinter.name}:`,
|
||||
result.error
|
||||
result.error,
|
||||
);
|
||||
this.isOnline = false;
|
||||
this.state = { type: "offline", message: result.error };
|
||||
@ -158,27 +179,37 @@ export class DocumentPrinterClient {
|
||||
return false;
|
||||
}
|
||||
logger.info(
|
||||
`Connected to document printer ${this.documentPrinter.name} (${this.interface})`
|
||||
`Connected to document printer ${this.documentPrinter.name} (${this.interface})`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
async reconnect() {
|
||||
if (this.active == false) {
|
||||
logger.info(
|
||||
`Document printer ${this.documentPrinter.name} is inactive, skipping reconnect`,
|
||||
);
|
||||
this.shouldReconnect = false;
|
||||
this.isOnline = false;
|
||||
this.state = { type: "inactive" };
|
||||
await this.updateDocumentPrinterState();
|
||||
return false;
|
||||
}
|
||||
if (this.isOnline == true) {
|
||||
logger.info(
|
||||
`Disconnecting from document printer ${this.documentPrinter.name} before reconnecting...`
|
||||
`Disconnecting from document printer ${this.documentPrinter.name} before reconnecting...`,
|
||||
);
|
||||
await this.disconnect();
|
||||
}
|
||||
logger.info(
|
||||
`Reconnecting to document printer ${this.documentPrinter.name}`
|
||||
`Reconnecting to document printer ${this.documentPrinter.name}`,
|
||||
);
|
||||
this.shouldReconnect = true;
|
||||
const connectResult = await this.connect();
|
||||
if (connectResult == false) {
|
||||
logger.error(
|
||||
`Error reconnecting to document printer ${this.documentPrinter.name}:`,
|
||||
connectResult.error
|
||||
connectResult.error,
|
||||
);
|
||||
if (this.shouldReconnect) {
|
||||
// Attempt to reconnect after delay
|
||||
@ -190,7 +221,7 @@ export class DocumentPrinterClient {
|
||||
if (initializeResult == false) {
|
||||
logger.error(
|
||||
`Error initializing document printer ${this.documentPrinter.name}:`,
|
||||
initializeResult.error
|
||||
initializeResult.error,
|
||||
);
|
||||
if (this.shouldReconnect) {
|
||||
// Attempt to reconnect after delay
|
||||
@ -213,7 +244,7 @@ export class DocumentPrinterClient {
|
||||
if (result.error) {
|
||||
logger.error(
|
||||
`Error initializing document printer ${this.documentPrinter.name}:`,
|
||||
result.error
|
||||
result.error,
|
||||
);
|
||||
this.state = { type: "offline", message: result.error };
|
||||
await this.updateDocumentPrinterState();
|
||||
@ -223,7 +254,7 @@ export class DocumentPrinterClient {
|
||||
await this.updateDocumentPrinterState();
|
||||
this.eventUpdateInterval = setInterval(
|
||||
this.handleEventUpdate.bind(this),
|
||||
3000
|
||||
3000,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
@ -236,7 +267,7 @@ export class DocumentPrinterClient {
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error retrieving status for document printer ${this.documentPrinter.name}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -272,19 +303,19 @@ export class DocumentPrinterClient {
|
||||
|
||||
async deployDocumentJob(documentJob) {
|
||||
logger.info(
|
||||
`Deploying document job ${documentJob._id} to ${this.documentPrinter.name}`
|
||||
`Deploying document job ${documentJob._id} to ${this.documentPrinter.name}`,
|
||||
);
|
||||
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot deploy job: Document printer not connected (${this.documentPrinter.name})`
|
||||
`Cannot deploy job: Document printer not connected (${this.documentPrinter.name})`,
|
||||
);
|
||||
return { error: "Document printer not connected" };
|
||||
}
|
||||
|
||||
if (!this.printerInterface) {
|
||||
logger.error(
|
||||
`Cannot deploy job: No interface initialized (${this.documentPrinter.name})`
|
||||
`Cannot deploy job: No interface initialized (${this.documentPrinter.name})`,
|
||||
);
|
||||
return { error: "No interface initialized" };
|
||||
}
|
||||
@ -310,7 +341,7 @@ export class DocumentPrinterClient {
|
||||
});
|
||||
if (!documentTemplate) {
|
||||
logger.error(
|
||||
`Document template not found for job ${documentJob._id}`
|
||||
`Document template not found for job ${documentJob._id}`,
|
||||
);
|
||||
return { error: "Document template not found" };
|
||||
}
|
||||
@ -325,20 +356,20 @@ export class DocumentPrinterClient {
|
||||
});
|
||||
if (!pdfObj) {
|
||||
logger.error(
|
||||
`Failed to render document template for job ${documentJob._id}`
|
||||
`Failed to render document template for job ${documentJob._id}`,
|
||||
);
|
||||
return { error: "Failed to render document template" };
|
||||
}
|
||||
const result = await this.printerInterface.deploy(
|
||||
documentJob,
|
||||
pdfObj.pdf
|
||||
pdfObj.pdf,
|
||||
);
|
||||
await this.updateJobState(documentJob._id, {
|
||||
type: "deploying",
|
||||
progress: 1.0,
|
||||
});
|
||||
logger.info(
|
||||
`Deployed document job ${documentJob._id} to ${this.documentPrinter.name}`
|
||||
`Deployed document job ${documentJob._id} to ${this.documentPrinter.name}`,
|
||||
);
|
||||
await this.updateJobState(documentJob._id, {
|
||||
type: "queued",
|
||||
@ -349,21 +380,21 @@ export class DocumentPrinterClient {
|
||||
this.queue.push(documentJob._id);
|
||||
} else {
|
||||
logger.warn(
|
||||
`Job ${documentJob._id} is already in the queue for ${this.documentPrinter.name}`
|
||||
`Job ${documentJob._id} is already in the queue for ${this.documentPrinter.name}`,
|
||||
);
|
||||
}
|
||||
this.startQueue();
|
||||
return result;
|
||||
} else {
|
||||
logger.error(
|
||||
`Interface ${this.interface} does not support deployDocumentJob`
|
||||
`Interface ${this.interface} does not support deployDocumentJob`,
|
||||
);
|
||||
return { error: "Interface does not support this operation" };
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error deploying document job to ${this.documentPrinter.name}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
await this.updateJobState(documentJob._id, {
|
||||
type: "error",
|
||||
@ -377,20 +408,20 @@ export class DocumentPrinterClient {
|
||||
async startQueue() {
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot start queue: Document printer not connected (${this.documentPrinter.name})`
|
||||
`Cannot start queue: Document printer not connected (${this.documentPrinter.name})`,
|
||||
);
|
||||
return { error: "Document printer not connected" };
|
||||
}
|
||||
if (!this.printerInterface) {
|
||||
logger.error(
|
||||
`Cannot start queue: No interface initialized (${this.documentPrinter.name})`
|
||||
`Cannot start queue: No interface initialized (${this.documentPrinter.name})`,
|
||||
);
|
||||
return { error: "No interface initialized" };
|
||||
}
|
||||
// Prevent concurrent queue processing
|
||||
if (this.isProcessingQueue) {
|
||||
logger.debug(
|
||||
`Queue is already being processed for ${this.documentPrinter.name}`
|
||||
`Queue is already being processed for ${this.documentPrinter.name}`,
|
||||
);
|
||||
return { info: "Queue is already being processed" };
|
||||
}
|
||||
@ -404,19 +435,19 @@ export class DocumentPrinterClient {
|
||||
async runQueue() {
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot print next job: Document printer not connected (${this.documentPrinter.name})`
|
||||
`Cannot print next job: Document printer not connected (${this.documentPrinter.name})`,
|
||||
);
|
||||
return { error: "Document printer not connected" };
|
||||
}
|
||||
if (!this.printerInterface) {
|
||||
logger.error(
|
||||
`Cannot print next job: No interface initialized (${this.documentPrinter.name})`
|
||||
`Cannot print next job: No interface initialized (${this.documentPrinter.name})`,
|
||||
);
|
||||
return { error: "No interface initialized" };
|
||||
}
|
||||
if (this.state.type != "standby") {
|
||||
logger.error(
|
||||
`Cannot print next job: Document printer not in standby mode (${this.documentPrinter.name})`
|
||||
`Cannot print next job: Document printer not in standby mode (${this.documentPrinter.name})`,
|
||||
);
|
||||
return { error: "Document printer not in standby mode" };
|
||||
}
|
||||
@ -424,7 +455,7 @@ export class DocumentPrinterClient {
|
||||
// Prevent concurrent queue processing
|
||||
if (this.isProcessingQueue) {
|
||||
logger.debug(
|
||||
`Queue is already being processed for ${this.documentPrinter.name}`
|
||||
`Queue is already being processed for ${this.documentPrinter.name}`,
|
||||
);
|
||||
return { info: "Queue is already being processed" };
|
||||
}
|
||||
@ -439,7 +470,7 @@ export class DocumentPrinterClient {
|
||||
// Re-check connection status before each job
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Printer went offline while printing (${this.documentPrinter.name})`
|
||||
`Printer went offline while printing (${this.documentPrinter.name})`,
|
||||
);
|
||||
this.state = {
|
||||
type: "offline",
|
||||
@ -450,7 +481,7 @@ export class DocumentPrinterClient {
|
||||
}
|
||||
if (!this.printerInterface) {
|
||||
logger.error(
|
||||
`Printer interface lost while printing (${this.documentPrinter.name})`
|
||||
`Printer interface lost while printing (${this.documentPrinter.name})`,
|
||||
);
|
||||
this.state = {
|
||||
type: "offline",
|
||||
@ -472,7 +503,7 @@ export class DocumentPrinterClient {
|
||||
|
||||
await this.printerInterface.print(jobId);
|
||||
logger.info(
|
||||
`Successfully printed job ${jobId} for ${this.documentPrinter.name}`
|
||||
`Successfully printed job ${jobId} for ${this.documentPrinter.name}`,
|
||||
);
|
||||
// Only remove job from queue after successful printing
|
||||
this.queue.shift();
|
||||
@ -480,7 +511,7 @@ export class DocumentPrinterClient {
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error printing job ${jobId} for ${this.documentPrinter.name}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
|
||||
// Remove failed job from queue to prevent infinite retry loop
|
||||
@ -492,7 +523,7 @@ export class DocumentPrinterClient {
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Finished printing all jobs for ${this.documentPrinter.name}`
|
||||
`Finished printing all jobs for ${this.documentPrinter.name}`,
|
||||
);
|
||||
this.state = { type: "standby", message: null };
|
||||
await this.updateDocumentPrinterState();
|
||||
@ -513,7 +544,7 @@ export class DocumentPrinterClient {
|
||||
await this.printerInterface.disconnect();
|
||||
}
|
||||
this.isOnline = false;
|
||||
this.state = { type: "offline" };
|
||||
this.state = { type: this.active == false ? "inactive" : "offline" };
|
||||
this.isProcessingQueue = false;
|
||||
this.queue = []; // Clear queue on disconnect
|
||||
await this.updateDocumentPrinterState();
|
||||
@ -521,4 +552,21 @@ export class DocumentPrinterClient {
|
||||
logger.info(`Successfully disconnected from ${this.documentPrinter.name}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
async setInactive() {
|
||||
this.active = false;
|
||||
this.documentPrinter.active = false;
|
||||
this.isOnline = false;
|
||||
await this.disconnect();
|
||||
this.state = { type: "inactive" };
|
||||
await this.updateDocumentPrinterState();
|
||||
}
|
||||
|
||||
async setActive() {
|
||||
this.active = true;
|
||||
this.documentPrinter.active = true;
|
||||
this.shouldReconnect = true;
|
||||
this.isOnline = false;
|
||||
await this.reconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ export class DocumentPrinterManager {
|
||||
logger.debug("Handling document printer update for id:", id);
|
||||
const documentPrinter = this.getDocumentPrinterClient(id);
|
||||
if (documentPrinter) {
|
||||
documentPrinter.updateDocumentPrinter(data.object);
|
||||
await documentPrinter.updateDocumentPrinter(data.object);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -64,8 +64,8 @@ const App = () => {
|
||||
prev.map((printer) =>
|
||||
printer._id === newPrinter._id
|
||||
? _.merge(printer, newPrinter)
|
||||
: printer
|
||||
)
|
||||
: printer,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@ -73,7 +73,7 @@ const App = () => {
|
||||
"setDocumentPrinters",
|
||||
(newDocumentPrinters) => {
|
||||
setDocumentPrinters(newDocumentPrinters);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
window.electronAPI.onIPCData("setDocumentPrinter", (newDocumentPrinter) => {
|
||||
@ -81,8 +81,8 @@ const App = () => {
|
||||
prev.map((documentPrinter) =>
|
||||
documentPrinter._id === newDocumentPrinter._id
|
||||
? _.merge(documentPrinter, newDocumentPrinter)
|
||||
: documentPrinter
|
||||
)
|
||||
: documentPrinter,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@ -229,7 +229,7 @@ const App = () => {
|
||||
className="ant-menu-horizontal ant-menu-light electron-drag-area"
|
||||
style={{
|
||||
lineHeight: "40px",
|
||||
padding: "0 8px 0 75px",
|
||||
padding: "0 8px 0 83px",
|
||||
}}
|
||||
justify="space-between"
|
||||
>
|
||||
@ -246,6 +246,7 @@ const App = () => {
|
||||
flexWrap: "wrap",
|
||||
border: 0,
|
||||
lineHeight: "38px",
|
||||
marginTop: "1px",
|
||||
}}
|
||||
overflowedIndicator={
|
||||
<Button type="text" icon={<MenuOutlined />} />
|
||||
|
||||
@ -60,6 +60,14 @@ const StateTag = ({ state, showBadge = true, style = {} }) => {
|
||||
status = "success";
|
||||
text = "Unconsumed";
|
||||
break;
|
||||
case "inactive":
|
||||
status = "default";
|
||||
text = "Inactive";
|
||||
break;
|
||||
case "connecting":
|
||||
status = "warning";
|
||||
text = "Connecting";
|
||||
break;
|
||||
case "error":
|
||||
status = "error";
|
||||
text = "Error";
|
||||
|
||||
@ -23,7 +23,11 @@ export class PrinterClient {
|
||||
this.socketClient = printerManager.socketClient;
|
||||
this.database = new PrinterDatabase(this.socketClient, this.printer);
|
||||
this.printerFileManager = new PrinterFileManager(this);
|
||||
this.state = { type: "offline", message: "Moonraker disconnected." };
|
||||
this.active = printer.active !== false;
|
||||
this.state =
|
||||
this.active == true
|
||||
? { type: "offline", message: "Moonraker disconnected." }
|
||||
: { type: "inactive" };
|
||||
this.klippyState = { type: "offline", message: "Klippy disconnected." };
|
||||
this.config = printer.moonraker;
|
||||
this.version = printer.version;
|
||||
@ -37,10 +41,11 @@ export class PrinterClient {
|
||||
this.motionObject = {};
|
||||
this.miscObject = {};
|
||||
this.currentFilamentStock = printer.currentFilamentStock;
|
||||
this.currentFilament = null;
|
||||
this.currentFilamentSku = null;
|
||||
this.currentFilamentUsed = 0;
|
||||
this.registerEventHandlers();
|
||||
this.subscribeToActions();
|
||||
this.subscribeToObjectUpdates();
|
||||
this.baseSubscription = {
|
||||
print_stats: null,
|
||||
display_status: null,
|
||||
@ -74,32 +79,32 @@ export class PrinterClient {
|
||||
registerEventHandlers() {
|
||||
// Register event handlers for Moonraker notifications
|
||||
this.jsonRpc.registerMethod(
|
||||
"notify_gcode_response"
|
||||
"notify_gcode_response",
|
||||
//this.handleGcodeResponse.bind(this),
|
||||
);
|
||||
this.jsonRpc.registerMethod(
|
||||
"notify_status_update",
|
||||
this.handleStatusUpdate.bind(this)
|
||||
this.handleStatusUpdate.bind(this),
|
||||
);
|
||||
this.jsonRpc.registerMethod(
|
||||
"notify_klippy_disconnected",
|
||||
this.handleKlippyDisconnected.bind(this)
|
||||
this.handleKlippyDisconnected.bind(this),
|
||||
);
|
||||
this.jsonRpc.registerMethod(
|
||||
"notify_klippy_ready",
|
||||
this.handleKlippyReady.bind(this)
|
||||
this.handleKlippyReady.bind(this),
|
||||
);
|
||||
this.jsonRpc.registerMethod(
|
||||
"notify_filelist_changed",
|
||||
this.handleFileListChanged.bind(this)
|
||||
this.handleFileListChanged.bind(this),
|
||||
);
|
||||
this.jsonRpc.registerMethod(
|
||||
"notify_metadata_update",
|
||||
this.handleMetadataUpdate.bind(this)
|
||||
this.handleMetadataUpdate.bind(this),
|
||||
);
|
||||
this.jsonRpc.registerMethod(
|
||||
"notify_power_changed",
|
||||
this.handlePowerChanged.bind(this)
|
||||
this.handlePowerChanged.bind(this),
|
||||
);
|
||||
}
|
||||
|
||||
@ -110,6 +115,31 @@ export class PrinterClient {
|
||||
});
|
||||
}
|
||||
|
||||
subscribeToObjectUpdates() {
|
||||
this.socketClient.subscribeToObjectUpdates({
|
||||
objectType: "printer",
|
||||
_id: this.id,
|
||||
});
|
||||
}
|
||||
|
||||
async updatePrinter(data) {
|
||||
logger.debug(`Updating printer ${this.id} with data...`);
|
||||
this.printer = { ...this.printer, ...data };
|
||||
this.database.printer = this.printer;
|
||||
|
||||
if (data?.moonraker) {
|
||||
this.config = data.moonraker;
|
||||
}
|
||||
|
||||
if (Object.hasOwn(data || {}, "active") && data.active != this.active) {
|
||||
if (data.active == true) {
|
||||
await this.setActive();
|
||||
} else {
|
||||
await this.setInactive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _runQueueMutation(task) {
|
||||
const executeTask = async () => task();
|
||||
this.queueMutationChain = this.queueMutationChain
|
||||
@ -119,6 +149,15 @@ export class PrinterClient {
|
||||
}
|
||||
|
||||
async connect() {
|
||||
if (this.active == false) {
|
||||
logger.info(`Printer ${this.id} is not active, skipping connection`);
|
||||
this.shouldReconnect = false;
|
||||
this.isOnline = false;
|
||||
this.state = { type: "inactive" };
|
||||
await this.updatePrinterState();
|
||||
return false;
|
||||
}
|
||||
|
||||
const { protocol, host, port } = this.config;
|
||||
const wsUrl = `${protocol}://${host}:${port}/websocket`;
|
||||
|
||||
@ -143,7 +182,10 @@ export class PrinterClient {
|
||||
this.socket.addEventListener("close", () => {
|
||||
logger.info(`Disconnected from Moonraker (${this.printer.name})`);
|
||||
this.isOnline = false;
|
||||
this.state = { type: "offline", message: "Moonraker disconnected." };
|
||||
this.state =
|
||||
this.active == true
|
||||
? { type: "offline", message: "Moonraker disconnected." }
|
||||
: { type: "inactive" };
|
||||
this.connectedAt = null;
|
||||
this.updatePrinterState();
|
||||
this.connectionId = null;
|
||||
@ -182,14 +224,14 @@ export class PrinterClient {
|
||||
.then(async (result) => {
|
||||
this.connectionId = result.connection_id;
|
||||
logger.info(
|
||||
`Connection identified with ID: ${this.connectionId} (${this.printer.name})`
|
||||
`Connection identified with ID: ${this.connectionId} (${this.printer.name})`,
|
||||
);
|
||||
await this.initialize();
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error(
|
||||
`Error identifying connection (${this.printer.name}):`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -207,7 +249,7 @@ export class PrinterClient {
|
||||
await this.syncSubJobs();
|
||||
this.eventUpdateInterval = setInterval(
|
||||
this.handleEventUpdate.bind(this),
|
||||
500
|
||||
500,
|
||||
);
|
||||
}
|
||||
|
||||
@ -221,20 +263,20 @@ export class PrinterClient {
|
||||
logger.info(
|
||||
"Server:",
|
||||
`Moonraker ${serverResult.moonraker_version} (${this.printer.name})`,
|
||||
`State: ${this.klippyState.type}`
|
||||
`State: ${this.klippyState.type}`,
|
||||
);
|
||||
|
||||
try {
|
||||
const klippyResult = await this.jsonRpc.callMethod("printer.info");
|
||||
logger.info(
|
||||
`Klippy info for ${this.printer.name}: ${klippyResult.hostname}, ${klippyResult.software_version}`
|
||||
`Klippy info for ${this.printer.name}: ${klippyResult.hostname}, ${klippyResult.software_version}`,
|
||||
);
|
||||
// Update firmware version in database
|
||||
await this.database.updatePrinterFirmware(
|
||||
klippyResult.software_version
|
||||
klippyResult.software_version,
|
||||
);
|
||||
logger.info(
|
||||
`Updated firmware version for ${this.printer.name} to ${klippyResult.software_version}`
|
||||
`Updated firmware version for ${this.printer.name} to ${klippyResult.software_version}`,
|
||||
);
|
||||
|
||||
if (klippyResult.state === "error" && klippyResult.state_message) {
|
||||
@ -245,7 +287,7 @@ export class PrinterClient {
|
||||
type: "error",
|
||||
message: klippyResult.state_message,
|
||||
actions: ["restartPrinter"],
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@ -257,7 +299,7 @@ export class PrinterClient {
|
||||
type: "error",
|
||||
message: klippyResult.state_message,
|
||||
actions: ["restartPrinter"],
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@ -269,19 +311,19 @@ export class PrinterClient {
|
||||
message: klippyResult.state_message,
|
||||
priority: 8,
|
||||
timestamp: new Date(),
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error getting Klippy info for ${this.printer.name}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error getting server info for ${this.printer.name}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -294,7 +336,7 @@ export class PrinterClient {
|
||||
for (const file of result) {
|
||||
if (file.path.startsWith("farmcontrol/")) {
|
||||
this.printrFileIds.push(
|
||||
file.path.replace("farmcontrol/", "").replace(".gcode", "")
|
||||
file.path.replace("farmcontrol/", "").replace(".gcode", ""),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -305,17 +347,17 @@ export class PrinterClient {
|
||||
logger.info(`Getting current filament for printer: ${this.printer.name}`);
|
||||
if (!this.currentFilamentStock || !this.currentFilamentStock?._id) {
|
||||
logger.warn(
|
||||
`No current filament stock found for printer: ${this.printer.name}`
|
||||
`No current filament stock found for printer: ${this.printer.name}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
const result = await this.socketClient.getObject({
|
||||
objectType: "filamentStock",
|
||||
_id: this.currentFilamentStock._id,
|
||||
populate: ["filament"],
|
||||
populate: ["filamentSku"],
|
||||
});
|
||||
this.currentFilament = result.filament;
|
||||
return this.currentFilament;
|
||||
this.currentFilamentSku = result.filamentSku;
|
||||
return this.currentFilamentSku;
|
||||
}
|
||||
|
||||
async getQueuedJobIds() {
|
||||
@ -332,7 +374,7 @@ export class PrinterClient {
|
||||
logger.info(`Getting state of (${this.printer.name})`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot send command: Not connected to Moonraker. (${this.printer.name})`
|
||||
`Cannot send command: Not connected to Moonraker. (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -354,7 +396,7 @@ export class PrinterClient {
|
||||
try {
|
||||
const result = await this.jsonRpc.callMethodWithKwargs(
|
||||
"printer.objects.query",
|
||||
{ objects: this.baseSubscription }
|
||||
{ objects: this.baseSubscription },
|
||||
);
|
||||
logger.debug(`Command sent to ${this.printer.name}`);
|
||||
if (result.status != undefined) {
|
||||
@ -380,12 +422,12 @@ export class PrinterClient {
|
||||
|
||||
logger.debug(
|
||||
"Combined subscriptions:",
|
||||
Object.keys(allSubscriptions).join(", ")
|
||||
Object.keys(allSubscriptions).join(", "),
|
||||
);
|
||||
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot send command: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot send command: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -406,7 +448,7 @@ export class PrinterClient {
|
||||
logger.info(`Sending ${command.method} command to (${this.printer.name})`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot send command: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot send command: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -414,7 +456,7 @@ export class PrinterClient {
|
||||
try {
|
||||
const result = await this.jsonRpc.callMethodWithKwargs(
|
||||
command.method,
|
||||
command.params
|
||||
command.params,
|
||||
);
|
||||
logger.debug(`Command sent to ${this.printer.name}`);
|
||||
if (result.status != undefined) {
|
||||
@ -443,7 +485,7 @@ export class PrinterClient {
|
||||
const oldState = this.state.type;
|
||||
if (newState !== oldState) {
|
||||
logger.info(
|
||||
`Printer ${this.printer.name} state changed from ${this.state.type} to ${newState}`
|
||||
`Printer ${this.printer.name} state changed from ${this.state.type} to ${newState}`,
|
||||
);
|
||||
if (oldState == "printing" && newState == "complete") {
|
||||
printerFinished = true;
|
||||
@ -476,7 +518,7 @@ export class PrinterClient {
|
||||
const newProgress = status.display_status.progress;
|
||||
if (newProgress !== this.state.progress) {
|
||||
logger.info(
|
||||
`Printer ${this.printer.name} progress changed from ${this.state.progress} to ${newProgress}`
|
||||
`Printer ${this.printer.name} progress changed from ${this.state.progress} to ${newProgress}`,
|
||||
);
|
||||
this.state.progress = newProgress;
|
||||
progressChanged = true;
|
||||
@ -639,7 +681,7 @@ export class PrinterClient {
|
||||
if (newFilamentDetected !== this.filamentDetected) {
|
||||
console.log(status["filament_switch_sensor fsensor"]);
|
||||
logger.info(
|
||||
`Printer ${this.printer.name} filament detection changed from ${this.filamentDetected} to ${newFilamentDetected}.`
|
||||
`Printer ${this.printer.name} filament detection changed from ${this.filamentDetected} to ${newFilamentDetected}.`,
|
||||
);
|
||||
this.filamentDetected = newFilamentDetected;
|
||||
|
||||
@ -701,11 +743,11 @@ export class PrinterClient {
|
||||
if (stateChanged == true) {
|
||||
if (printerFinished == true && isCurrentJobSubJob == true) {
|
||||
logger.info(
|
||||
`Subjob ${this.currentSubJob._id} completed, posting part stock items for printer ${this.id}`
|
||||
`Subjob ${this.currentSubJob._id} completed, posting part stock items for printer ${this.id}`,
|
||||
);
|
||||
await this.database.setSubJobFinishedAt(
|
||||
this.currentSubJob._id,
|
||||
new Date()
|
||||
new Date(),
|
||||
);
|
||||
await this.database.postSubJobPartStockItems(this.currentSubJob._id);
|
||||
}
|
||||
@ -720,7 +762,7 @@ export class PrinterClient {
|
||||
this.currentSubJob.startedAt = new Date();
|
||||
await this.database.setSubJobStartedAt(
|
||||
this.currentSubJob._id,
|
||||
new Date()
|
||||
new Date(),
|
||||
);
|
||||
}
|
||||
if (this.currentJob.startedAt == null) {
|
||||
@ -738,7 +780,7 @@ export class PrinterClient {
|
||||
};
|
||||
await this.database.updateSubJobState(
|
||||
this.currentSubJob._id,
|
||||
subJobState
|
||||
subJobState,
|
||||
);
|
||||
await this.database.updateJobState(this.currentJob._id);
|
||||
}
|
||||
@ -780,13 +822,13 @@ export class PrinterClient {
|
||||
) {
|
||||
logger.debug(
|
||||
"Updating stock event value:",
|
||||
this.currentFilamentUsed.toFixed(2)
|
||||
this.currentFilamentUsed.toFixed(2),
|
||||
);
|
||||
this.database.updateFilamentStockWeight(
|
||||
this.currentFilamentStock,
|
||||
this.currentFilamentUsed,
|
||||
this.currentSubJob,
|
||||
this.currentJob
|
||||
this.currentJob,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -794,11 +836,15 @@ export class PrinterClient {
|
||||
async updatePrinterState() {
|
||||
try {
|
||||
const state =
|
||||
this.klippyState.type !== "ready" ? this.klippyState : this.state;
|
||||
this.active == false
|
||||
? { type: "inactive" }
|
||||
: this.klippyState.type !== "ready"
|
||||
? this.klippyState
|
||||
: this.state;
|
||||
await this.database.updatePrinterState(
|
||||
state,
|
||||
this.isOnline,
|
||||
this.connectedAt
|
||||
this.connectedAt,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to update printer state:`, error);
|
||||
@ -822,11 +868,11 @@ export class PrinterClient {
|
||||
const serverSubJobs = await this.database.getQueuedSubJobs();
|
||||
|
||||
const queuedSubJobs = serverSubJobs.filter((subJob) =>
|
||||
this.queuedJobIds.includes(subJob.moonrakerJobId)
|
||||
this.queuedJobIds.includes(subJob.moonrakerJobId),
|
||||
);
|
||||
|
||||
const unqueuedSubJobs = serverSubJobs.filter(
|
||||
(subJob) => !this.queuedJobIds.includes(subJob.moonrakerJobId)
|
||||
(subJob) => !this.queuedJobIds.includes(subJob.moonrakerJobId),
|
||||
);
|
||||
|
||||
this.queue = queuedSubJobs;
|
||||
@ -850,7 +896,7 @@ export class PrinterClient {
|
||||
printingTypes.includes(stateType)
|
||||
) {
|
||||
logger.info(
|
||||
`No current subjob or job, setting first unqueued subjob as current...`
|
||||
`No current subjob or job, setting first unqueued subjob as current...`,
|
||||
);
|
||||
const targetSubJob = unqueuedSubJobs[0];
|
||||
const targetJob = await this.database.getJobById(targetSubJob.job);
|
||||
@ -869,7 +915,7 @@ export class PrinterClient {
|
||||
});
|
||||
this.currentSubJob.state.type = stateType;
|
||||
this.currentJob.state = await this.database.updateJobState(
|
||||
this.currentJob._id
|
||||
this.currentJob._id,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -941,7 +987,7 @@ export class PrinterClient {
|
||||
handleMetadataUpdate(metadata) {
|
||||
logger.info(
|
||||
`Metadata updated for ${this.printer.name}:`,
|
||||
metadata.filename
|
||||
metadata.filename,
|
||||
);
|
||||
}
|
||||
|
||||
@ -953,7 +999,7 @@ export class PrinterClient {
|
||||
logger.info(`Uploading G-code file ${fileName} to ${this.printer.name}`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot upload file: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot upload file: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -986,14 +1032,14 @@ export class PrinterClient {
|
||||
headers,
|
||||
onUploadProgress: (progressEvent) => {
|
||||
const percentCompleted = Math.round(
|
||||
(progressEvent.loaded * 100) / progressEvent.total
|
||||
(progressEvent.loaded * 100) / progressEvent.total,
|
||||
);
|
||||
logger.debug(
|
||||
`Uploading file to ${this.printer.name}: ` +
|
||||
fileName +
|
||||
" " +
|
||||
percentCompleted +
|
||||
"%"
|
||||
"%",
|
||||
);
|
||||
this.socketManager.broadcast("notify_printer_update", {
|
||||
printerId: this.id,
|
||||
@ -1011,7 +1057,7 @@ export class PrinterClient {
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Successfully uploaded file ${fileName} to ${this.printer.name}`
|
||||
`Successfully uploaded file ${fileName} to ${this.printer.name}`,
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
@ -1024,7 +1070,7 @@ export class PrinterClient {
|
||||
// Add subJob to queue
|
||||
this.deploySubJobQueue.push(subJob);
|
||||
logger.debug(
|
||||
`Queued sub job ${subJob._id} for deployment. Queue size: ${this.deploySubJobQueue.length}`
|
||||
`Queued sub job ${subJob._id} for deployment. Queue size: ${this.deploySubJobQueue.length}`,
|
||||
);
|
||||
|
||||
const now = Date.now();
|
||||
@ -1065,7 +1111,7 @@ export class PrinterClient {
|
||||
this.deploySubJobQueue = [];
|
||||
|
||||
logger.info(
|
||||
`Processing ${subJobsToDeploy.length} queued sub job(s) for printer ${this.id}`
|
||||
`Processing ${subJobsToDeploy.length} queued sub job(s) for printer ${this.id}`,
|
||||
);
|
||||
|
||||
// Process sub jobs in parallel with a 250ms stagger between starts
|
||||
@ -1082,10 +1128,10 @@ export class PrinterClient {
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error deploying sub job ${subJob._id} to printer ${this.id}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
}
|
||||
})()
|
||||
})(),
|
||||
);
|
||||
|
||||
await Promise.all(deployPromises);
|
||||
@ -1098,7 +1144,7 @@ export class PrinterClient {
|
||||
"to printer:",
|
||||
this.id,
|
||||
"with gcode file:",
|
||||
`${subJob.gcodeFile.name}`
|
||||
`${subJob.gcodeFile.name}`,
|
||||
);
|
||||
const gcodeFile = await this.socketClient.getObject({
|
||||
objectType: "gcodeFile",
|
||||
@ -1117,7 +1163,7 @@ export class PrinterClient {
|
||||
progress: (progress / 100 / 2).toFixed(2),
|
||||
});
|
||||
await this.database.updateJobState(subJob.job._id);
|
||||
}
|
||||
},
|
||||
);
|
||||
if (!file) {
|
||||
throw new Error("Error getting file");
|
||||
@ -1134,7 +1180,7 @@ export class PrinterClient {
|
||||
progress: (progress / 100 / 2 + 0.5).toFixed(2),
|
||||
});
|
||||
await this.database.updateJobState(subJob.job._id);
|
||||
}
|
||||
},
|
||||
);
|
||||
this.printrFileIds.push(gcodeFile.file.toString());
|
||||
if (!uploadResult) {
|
||||
@ -1161,7 +1207,7 @@ export class PrinterClient {
|
||||
const mostRecentQueuedJob = queuedJobs[queuedJobs.length - 1];
|
||||
const updatedSubJob = await this.database.setSubJobMoonrakerJobId(
|
||||
subJob._id,
|
||||
mostRecentQueuedJob.job_id
|
||||
mostRecentQueuedJob.job_id,
|
||||
);
|
||||
await this.database.updateSubJobState(subJob._id, {
|
||||
type: "queued",
|
||||
@ -1206,7 +1252,7 @@ export class PrinterClient {
|
||||
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot set temperature: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot set temperature: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1217,20 +1263,20 @@ export class PrinterClient {
|
||||
// Handle extruder temperature
|
||||
if (temperature.extruder?.target !== undefined) {
|
||||
gcodeCommands.push(
|
||||
`SET_HEATER_TEMPERATURE HEATER=extruder TARGET=${temperature.extruder.target}`
|
||||
`SET_HEATER_TEMPERATURE HEATER=extruder TARGET=${temperature.extruder.target}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Handle bed temperature
|
||||
if (temperature.bed?.target !== undefined) {
|
||||
gcodeCommands.push(
|
||||
`SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET=${temperature.bed.target}`
|
||||
`SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET=${temperature.bed.target}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (gcodeCommands.length === 0) {
|
||||
logger.warn(
|
||||
`No valid temperature targets provided for ${this.printer.name}`
|
||||
`No valid temperature targets provided for ${this.printer.name}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1245,7 +1291,7 @@ export class PrinterClient {
|
||||
|
||||
if (!result) {
|
||||
logger.error(
|
||||
`Failed to set temperature with command: ${gcodeCommand}`
|
||||
`Failed to set temperature with command: ${gcodeCommand}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1258,7 +1304,7 @@ export class PrinterClient {
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error setting temperature for ${this.printer.name}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1268,7 +1314,7 @@ export class PrinterClient {
|
||||
logger.info(`Restarting printer firmware for ${this.printer.name}`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot restart printer firmware: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot restart printer firmware: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1281,13 +1327,13 @@ export class PrinterClient {
|
||||
throw new Error("Failed to restart printer firmware");
|
||||
}
|
||||
logger.info(
|
||||
`Successfully restarted printer firmware for ${this.printer.name}`
|
||||
`Successfully restarted printer firmware for ${this.printer.name}`,
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error restarting printer firmware for ${this.printer.name}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1297,7 +1343,7 @@ export class PrinterClient {
|
||||
logger.info(`Restarting printer for ${this.printer.name}`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot restart printer: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot restart printer: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1320,7 +1366,7 @@ export class PrinterClient {
|
||||
logger.info(`Restarting moonraker server for ${this.printer.name}`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot restart moonraker server: Not connected to moonraker server (${this.printer.name})`
|
||||
`Cannot restart moonraker server: Not connected to moonraker server (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1333,13 +1379,13 @@ export class PrinterClient {
|
||||
throw new Error("Failed to restart moonraker server");
|
||||
}
|
||||
logger.info(
|
||||
`Successfully restarted moonraker server for ${this.printer.name}`
|
||||
`Successfully restarted moonraker server for ${this.printer.name}`,
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Error restarting moonraker server for ${this.printer.name}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1349,7 +1395,7 @@ export class PrinterClient {
|
||||
logger.info(`Starting queue for ${this.printer.name}`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot start queue: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot start queue: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1372,7 +1418,7 @@ export class PrinterClient {
|
||||
logger.info(`Pausing job for ${this.printer.name}`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot pause job: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot pause job: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1395,7 +1441,7 @@ export class PrinterClient {
|
||||
logger.info(`Resuming job for ${this.printer.name}`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot resume job: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot resume job: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1418,7 +1464,7 @@ export class PrinterClient {
|
||||
logger.info(`Cancelling job for ${this.printer.name}`);
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
`Cannot cancel job: Not connected to Moonraker (${this.printer.name})`
|
||||
`Cannot cancel job: Not connected to Moonraker (${this.printer.name})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1477,4 +1523,26 @@ export class PrinterClient {
|
||||
logger.info(`Successfully disconnected from ${this.printer.name}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
async setInactive() {
|
||||
this.active = false;
|
||||
this.printer.active = false;
|
||||
this.database.printer = this.printer;
|
||||
this.isOnline = false;
|
||||
await this.disconnect();
|
||||
this.state = { type: "inactive" };
|
||||
this.klippyState = { type: "inactive" };
|
||||
this.connectedAt = null;
|
||||
await this.updatePrinterState();
|
||||
}
|
||||
|
||||
async setActive() {
|
||||
this.active = true;
|
||||
this.printer.active = true;
|
||||
this.database.printer = this.printer;
|
||||
this.klippyState = { type: "offline", message: "Klippy disconnected." };
|
||||
this.shouldReconnect = true;
|
||||
this.isOnline = false;
|
||||
await this.connect();
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ export class PrinterManager {
|
||||
return;
|
||||
case "loadFilamentStock":
|
||||
const loadFilamentStockResult = await printer.loadFilamentStock(
|
||||
action.data.filamentStock
|
||||
action.data.filamentStock,
|
||||
);
|
||||
callback(loadFilamentStockResult);
|
||||
return;
|
||||
@ -127,6 +127,14 @@ export class PrinterManager {
|
||||
callback({ error: "Unknown command." });
|
||||
}
|
||||
|
||||
async handlePrinterUpdate(id, data) {
|
||||
logger.debug("Handling printer update for id:", id);
|
||||
const printer = this.getPrinterClient(id);
|
||||
if (printer) {
|
||||
await printer.updatePrinter(data.object);
|
||||
}
|
||||
}
|
||||
|
||||
getPrinterClient(printerId) {
|
||||
return this.printerClients.get(printerId);
|
||||
}
|
||||
@ -138,7 +146,7 @@ export class PrinterManager {
|
||||
// Close all printer connections
|
||||
async closeAllConnections() {
|
||||
logger.info(
|
||||
`Closing all printer connections... current count: ${this.printerClients.size}`
|
||||
`Closing all printer connections... current count: ${this.printerClients.size}`,
|
||||
);
|
||||
|
||||
// Take a snapshot so any mutations during disconnects don't affect iteration
|
||||
@ -150,14 +158,14 @@ export class PrinterManager {
|
||||
printerClient.shouldReconnect = false;
|
||||
await printerClient.disconnect();
|
||||
logger.info(
|
||||
`Disconnected printer client ${printerClient?.id || "unknown"}`
|
||||
`Disconnected printer client ${printerClient?.id || "unknown"}`,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Failed to disconnect printer client ${
|
||||
printerClient?.id || "unknown"
|
||||
}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -169,7 +177,7 @@ export class PrinterManager {
|
||||
this.printers = [];
|
||||
|
||||
logger.info(
|
||||
`All printer connections closed. Remaining clients: ${this.printerClients.size}`
|
||||
`All printer connections closed. Remaining clients: ${this.printerClients.size}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,6 +216,9 @@ export class SocketClient {
|
||||
callback
|
||||
);
|
||||
}
|
||||
if (data.objectType == "printer") {
|
||||
this.printerManager.handlePrinterUpdate(data._id, data, callback);
|
||||
}
|
||||
}
|
||||
|
||||
handleConnect() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user