P5 wave 1: extract rotatingMachine concerns into focused modules
src/curves/ loader + normalizer (with cross-pressure anomaly
detection) + reverseCurve helper
src/prediction/ predictors (predictFlow/Power/Ctrl) +
groupPredictors (lazy group-scope views) +
OperatingPoint (pressure-driven prediction setpoints)
src/drift/ DriftAssessor (per-metric drift) + PredictionHealth
(composes flow/power/pressure into HealthStatus +
confidence sibling — see OPEN_QUESTIONS 2026-05-10)
src/pressure/ VirtualPressureChildren (dashboard-sim) +
PressureInitialization (real-vs-virtual tracking) +
PressureRouter (dispatches by position)
src/state/ stateBindings (state.emitter listener helper) +
isOperationalState
src/measurement/ measurementHandlers (dispatcher for flow/power/temp/pressure)
src/flow/ flowController (handleInput body — execSequence,
execMovement, flowMovement, emergencystop)
src/display/ workingCurves (showWorkingCurves + showCoG admin)
src/commands/ canonical names: set.mode, cmd.startup/shutdown/estop,
set.setpoint, set.flow-setpoint,
data.simulate-measurement, query.curves, query.cog,
child.register. execSequence demuxes by payload.action
to canonical cmd.* handlers.
CONTRACT.md inputs/outputs/events/children surface
110 basic tests pass (100 new + 10 pre-existing).
specificClass.js / nodeClass.js untouched — integration in P5 wave 2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
85
src/flow/flowController.js
Normal file
85
src/flow/flowController.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Dispatches inbound control actions (execSequence / execMovement /
|
||||
* flowMovement / emergencyStop / enter|exitMaintenance / statusCheck)
|
||||
* to the state machine and motion helpers on the host.
|
||||
*
|
||||
* Behaviour mirrors the original specificClass.handleInput exactly:
|
||||
* - actions are lower-cased
|
||||
* - mode/source gating runs first
|
||||
* - flow-setpoints are unit-converted (output -> canonical) before
|
||||
* calcCtrl + setpoint
|
||||
* - thrown errors are caught + logged (no re-throw) so a misbehaving
|
||||
* parent never crashes the FSM
|
||||
*/
|
||||
|
||||
class FlowController {
|
||||
constructor(ctx) {
|
||||
if (!ctx || !ctx.host) {
|
||||
throw new Error('FlowController: ctx.host is required');
|
||||
}
|
||||
this.host = ctx.host;
|
||||
this.logger = ctx.logger || ctx.host.logger;
|
||||
}
|
||||
|
||||
async handle(source, action, parameter) {
|
||||
const host = this.host;
|
||||
|
||||
if (typeof action !== 'string') {
|
||||
this.logger.error('Action must be string');
|
||||
return;
|
||||
}
|
||||
action = action.toLowerCase();
|
||||
|
||||
if (!host.isValidActionForMode(action, host.currentMode)) return;
|
||||
if (!host.isValidSourceForMode(source, host.currentMode)) return;
|
||||
|
||||
this.logger.info(
|
||||
`Handling input from source '${source}' with action '${action}' in mode '${host.currentMode}'.`,
|
||||
);
|
||||
|
||||
try {
|
||||
switch (action) {
|
||||
case 'execsequence':
|
||||
return await host.executeSequence(parameter);
|
||||
|
||||
case 'execmovement':
|
||||
return await host.setpoint(parameter);
|
||||
|
||||
case 'entermaintenance':
|
||||
case 'exitmaintenance':
|
||||
return await host.executeSequence(parameter);
|
||||
|
||||
case 'flowmovement': {
|
||||
const canonicalFlowSetpoint = host._convertUnitValue(
|
||||
parameter,
|
||||
host.unitPolicy.output.flow,
|
||||
host.unitPolicy.canonical.flow,
|
||||
'flowmovement setpoint',
|
||||
);
|
||||
const pos = host.calcCtrl(canonicalFlowSetpoint);
|
||||
return await host.setpoint(pos);
|
||||
}
|
||||
|
||||
case 'emergencystop':
|
||||
this.logger.warn(`Emergency stop activated by '${source}'.`);
|
||||
return await host.executeSequence('emergencystop');
|
||||
|
||||
case 'statuscheck':
|
||||
this.logger.info(
|
||||
`Status Check: Mode = '${host.currentMode}', Source = '${source}'.`,
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
this.logger.warn(`Action '${action}' is not implemented.`);
|
||||
break;
|
||||
}
|
||||
this.logger.debug(`Action '${action}' successfully executed`);
|
||||
return { status: true, feedback: `Action '${action}' successfully executed.` };
|
||||
} catch (error) {
|
||||
this.logger.error(`Error handling input: ${error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FlowController;
|
||||
Reference in New Issue
Block a user