Gå til hovedinnhold

Plugin-system

3DPrintForge støtter et plugin-system som lar deg utvide funksjonaliteten uten å endre kildekoden.

Eksperimentelt

Plugin-systemet er under aktiv utvikling. API-et kan endre seg mellom versjoner.

Hva kan plugins gjøre?

  • Legge til nye API-endepunkter via registerRoute()
  • Registrere egne frontend-paneler via registerPanel()
  • Kjøre periodiske oppgaver med setInterval()
  • Tilgang til SQLite-databasen via db-konteksten
  • Lytte på printer-hendelser og reagere på dem
  • Integrere med tredjeparts tjenester
  • Utvide varslingskanaler

Plugin-struktur

Et plugin er en Node.js-modul i plugins/-mappen:

plugins/
└── mitt-plugin/
├── plugin.json # Metadata
├── index.js # Inngangspunkt
└── README.md # Dokumentasjon (valgfritt)

plugin.json

{
"name": "mitt-plugin",
"version": "1.0.0",
"description": "Beskrivelse av pluginen",
"author": "Ditt navn",
"main": "index.js",
"hooks": ["onPrintStart", "onPrintEnd", "onPrinterConnect"]
}

index.js

module.exports = {
// Kalles når pluginen lastes
async onLoad(context) {
const { api, db, logger, events, registerRoute, registerPanel } = context;
logger.info('Mitt plugin er lastet');

// Registrer en ny API-rute med registerRoute()
registerRoute('GET', '/plugins/mitt-plugin/status', (req, res) => {
res.json({ status: 'aktiv' });
});

registerRoute('POST', '/plugins/mitt-plugin/action', (req, res) => {
// Håndter POST-forespørsler
res.json({ result: 'ok' });
});

// Registrer et frontend-panel
registerPanel({
id: 'mitt-plugin-panel',
title: 'Mitt Plugin',
position: 'sidebar', // 'sidebar', 'dashboard', 'settings'
icon: 'fas fa-puzzle-piece',
html: '<div id="mitt-plugin-content">Loading...</div>',
js: '/plugins/mitt-plugin/public/panel.js'
});

// Kjør periodisk oppgave med setInterval
this.intervalId = setInterval(async () => {
const printers = context.printers;
for (const [id, printer] of printers) {
logger.debug(`Printer ${id}: ${printer.status}`);
}
}, 60000); // Hvert minutt

// Direkte databasetilgang
const rows = db.prepare('SELECT COUNT(*) as count FROM print_history').all();
logger.info(`Totalt ${rows[0].count} prints i historikken`);
},

// Kalles når pluginen lastes ut
async onUnload(context) {
if (this.intervalId) {
clearInterval(this.intervalId);
}
},

// Kalles når en print starter
async onPrintStart(context, printJob) {
const { logger } = context;
logger.info(`Print startet: ${printJob.name}`);
},

// Kalles når en print er ferdig
async onPrintEnd(context, printJob) {
const { logger, db } = context;
logger.info(`Print ferdig: ${printJob.name}`);
// Lagre data i databasen
db.prepare(
'INSERT INTO plugin_data (plugin, key, value) VALUES (?, ?, ?)'
).run('mitt-plugin', 'siste-print', printJob.name);
}
};

Tilgjengelige hooks

HookUtløser
onLoadPlugin lastes inn
onUnloadPlugin lastes ut
onPrinterConnectPrinter kobler til
onPrinterDisconnectPrinter kobler fra
onPrintStartPrint starter
onPrintEndPrint fullføres
onPrintFailPrint feiler
onFilamentChangeFilamentbytte
onAmsUpdateAMS-status oppdateres

Plugin context

Alle hooks mottar et context-objekt:

EgenskapTypeBeskrivelse
registerRouteFunctionRegistrer nye API-ruter: registerRoute(method, path, handler)
registerPanelFunctionRegistrer frontend-paneler: registerPanel({ id, title, position, html, js })
dbDatabaseSyncDirekte tilgang til SQLite-databasen (Node.js 22 innebygd)
loggerLoggerLogging med nivåer (debug, info, warn, error)
eventsEventEmitterLytt på og emit hendelser
configObjectDashboardets konfigurasjon (les-only)
printersMapAlle tilkoblede printere med status
apiRouterBakoverkompatibel API-registrering (bruk registerRoute i stedet)

Installere en plugin

# Kopier plugin-mappen
cp -r mitt-plugin/ plugins/

# Restart dashboardet
npm start

Plugins aktiveres automatisk ved oppstart hvis de finnes i plugins/-mappen.

Deaktivere en plugin

Legg til "disabled": true i plugin.json, eller fjern mappen.

Eksempel-plugin: Slack-varsler

const { IncomingWebhook } = require('@slack/webhook');

module.exports = {
async onLoad(context) {
this.webhook = new IncomingWebhook(process.env.SLACK_WEBHOOK_URL);
},

async onPrintEnd(context, job) {
await this.webhook.send({
text: `Print ferdig! *${job.name}* tok ${job.duration}`
});
}
};