Files
pumpingStation/pumpingStation.js
znetsixe 7afcd6e54a P2 wave 1: extract concerns from pumpingStation specificClass
Splits pumpingStation/src/ into focused concern modules. specificClass.js
will be slimmed to an orchestrator in P2.9 (integration); for now both
the inlined logic AND the new modules coexist so tests stay green
throughout.

  src/basin/         BasinGeometry + thresholdValidator (pure)
  src/measurement/   flowAggregator + measurementRouter + calibration
  src/control/       levelBased + flowBased(stub) + manual + index dispatcher
  src/safety/        safetyController split into dryRun + overfill rules
  src/commands/      registry array + handlers (canonical names from start)
  src/editor.js      260 lines of SVG basin-diagram redraw, was inline in .html
  examples/standalone-demo.js  was if(require.main===module) at bottom of specificClass.js
  CONTRACT.md        canonical inputs + outputs + emitted events

Modified:
  src/specificClass.js  removed the 170-line standalone demo block
  pumpingStation.html   oneditprepare/oneditsave delegate to editor.{init,save}
  pumpingStation.js     added admin endpoint serving src/editor.js

102 basic tests pass (60 new + 42 existing).
specificClass.js itself is unchanged in behaviour — integration is P2.9.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 20:18:49 +02:00

52 lines
2.2 KiB
JavaScript

const nameOfNode = 'pumpingStation'; // this is the name of the node, it should match the file name and the node type in Node-RED
const nodeClass = require('./src/nodeClass.js'); // this is the specific node class
const { MenuManager, configManager } = require('generalFunctions');
// This is the main entry point for the Node-RED node, it will register the node and setup the endpoints
module.exports = function(RED) {
// Register the node type
RED.nodes.registerType(nameOfNode, function(config) {
// Initialize the Node-RED node first
RED.nodes.createNode(this, config);
// Then create your custom class and attach it
this.nodeClass = new nodeClass(config, RED, this, nameOfNode);
});
// Setup admin UIs
const menuMgr = new MenuManager(); //this will handle the menu endpoints so we can load them dynamically
const cfgMgr = new configManager(); // this will handle the config endpoints so we can load them dynamically
// Register the different menu's for the measurement node (in the future we could automate this further by refering to the config)
RED.httpAdmin.get(`/${nameOfNode}/menu.js`, (req, res) => {
try {
const script = menuMgr.createEndpoint(nameOfNode, ['logger','position']);
res.type('application/javascript').send(script);
} catch (err) {
res.status(500).send(`// Error generating menu: ${err.message}`);
}
});
// Endpoint to get the configuration data for the specific node
RED.httpAdmin.get(`/${nameOfNode}/configData.js`, (req, res) => {
try {
const script = cfgMgr.createEndpoint(nameOfNode);
// Send the configuration data as JSON response
res.type('application/javascript').send(script);
} catch (err) {
res.status(500).send(`// Error generating configData: ${err.message}`);
}
});
// Editor.js — extracted SVG basin-diagram + oneditprepare/oneditsave logic.
RED.httpAdmin.get(`/${nameOfNode}/editor.js`, (req, res) => {
try {
const fs = require('fs');
const path = require('path');
const script = fs.readFileSync(path.join(__dirname, 'src/editor.js'), 'utf8');
res.type('application/javascript').send(script);
} catch (err) {
res.status(500).send(`// Error loading editor.js: ${err.message}`);
}
});
};