feat: level-based control now reaches machine groups + manual Qd forwarding
Two additions to pumpingStation: 1. _controlLevelBased now calls _applyMachineGroupLevelControl in addition to _applyMachineLevelControl when the basin is filling above startLevel. Previously only direct-child machines received the level-based percent-control signal; in a hierarchical topology (PS → MGC → pumps) the machines sit under MGC and PS.machines is empty, so the level control never reached them. 2. New 'Qd' input topic + forwardDemandToChildren() method. When PS is in 'manual' mode (matching the pattern from rotatingMachine's virtualControl), operator demand from a dashboard slider is forwarded to all child machine groups and direct machines. When PS is in any other mode (levelbased, flowbased, etc.), the Qd msg is silently dropped with a debug log so the automatic control isn't overridden. No breaking changes — existing flows that don't send 'Qd' are unaffected, and _controlLevelBased's additional call to machineGroupLevelControl is a no-op when no machine groups are registered. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -221,6 +221,27 @@ class nodeClass {
|
||||
this.source.setManualInflow(val, ts, unit);
|
||||
break;
|
||||
}
|
||||
case 'Qd': {
|
||||
// Manual demand: operator sets the target output via a
|
||||
// dashboard slider. Only accepted when PS is in 'manual'
|
||||
// mode — mirrors how rotatingMachine gates commands by
|
||||
// mode (virtualControl vs auto).
|
||||
const demand = Number(msg.payload);
|
||||
if (!Number.isFinite(demand)) {
|
||||
this.source.logger.warn(`Invalid Qd value: ${msg.payload}`);
|
||||
break;
|
||||
}
|
||||
if (this.source.mode === 'manual') {
|
||||
this.source.forwardDemandToChildren(demand).catch((err) =>
|
||||
this.source.logger.error(`Failed to forward demand: ${err.message}`)
|
||||
);
|
||||
} else {
|
||||
this.source.logger.debug(
|
||||
`Qd ignored in ${this.source.mode} mode. Switch to manual to use the demand slider.`
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -254,6 +254,11 @@ class PumpingStation {
|
||||
const percControl = this._scaleLevelToFlowPercent(level);
|
||||
this.logger.debug(`Controllevel based => Level ${level} control applying to pump : ${percControl}`);
|
||||
await this._applyMachineLevelControl(percControl);
|
||||
// Also forward to machine groups (e.g. MGC) — the level-based
|
||||
// control originally only addressed direct-child machines, but in
|
||||
// a hierarchical topology (PS → MGC → pumps) the machines sit
|
||||
// under MGC and PS.machines is empty.
|
||||
await this._applyMachineGroupLevelControl(percControl);
|
||||
}
|
||||
|
||||
if (level < stopLevel && direction === 'draining') {
|
||||
@@ -272,6 +277,38 @@ class PumpingStation {
|
||||
// placeholder for flow-based logic
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward a manual demand value to all child machine groups + direct
|
||||
* machines. Called from the 'Qd' topic handler when PS is in manual
|
||||
* mode — mirrors how rotatingMachine gates commands by mode.
|
||||
* @param {number} demand - the operator-set demand (interpretation
|
||||
* depends on MGC scaling: 'absolute' = m³/h, 'normalized' = 0-100%)
|
||||
*/
|
||||
async forwardDemandToChildren(demand) {
|
||||
this.logger.info(`Manual demand forwarded: ${demand}`);
|
||||
// Forward to machine groups (MGC)
|
||||
if (this.machineGroups && Object.keys(this.machineGroups).length > 0) {
|
||||
await Promise.all(
|
||||
Object.values(this.machineGroups).map((group) =>
|
||||
group.handleInput('parent', demand).catch((err) => {
|
||||
this.logger.error(`Failed to forward demand to group: ${err.message}`);
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
// Forward to direct machines (if any)
|
||||
if (this.machines && Object.keys(this.machines).length > 0) {
|
||||
const perMachine = demand / Object.keys(this.machines).length;
|
||||
for (const machine of Object.values(this.machines)) {
|
||||
try {
|
||||
await machine.handleInput('parent', 'execMovement', perMachine);
|
||||
} catch (err) {
|
||||
this.logger.error(`Failed to forward demand to machine: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _applyMachineGroupLevelControl(percentControl) {
|
||||
if (!this.machineGroups || Object.keys(this.machineGroups).length === 0) return;
|
||||
await Promise.all(
|
||||
|
||||
Reference in New Issue
Block a user