Files
rotatingMachine/src/nodeClass.js
znetsixe e058fe9245 P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules
specificClass.js: 1760 → 400 lines.
  Machine extends BaseDomain. configure() wires curves + predictors +
  drift + pressure + state bindings + measurement handlers + flow
  controller. ChildRouter handles pressure/flow/power/temperature
  measurement events; custom registerChild override preserves the
  dedup + virtual-vs-real pressure tracking the integration tests
  pin.

  Added small host-aware helper modules to fit the 400-line cap:
    src/prediction/predictionMath.js   (calcFlow/Power/Ctrl)
    src/prediction/efficiencyMath.js   (calcCog/EfficiencyCurve/etc.)
    src/pressure/pressureSelector.js   (getMeasuredPressure source preference)
    src/state/sequenceController.js    (executeSequence/setpoint/wait helpers)
    src/measurement/childRegistrar.js  (custom registerChild path)
    src/drift/healthRefresh.js         (drift status update wrappers)
    src/io/output.js                   (buildOutput + buildStatusBadge)

  unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve()
  bridged to legacy property-path readers via a frozen view object —
  same pattern as MGC. See OPEN_QUESTIONS.md.

nodeClass.js: 433 → 61 lines.
  Extends BaseNodeAdapter. tickInterval=null (event-driven on state +
  measurement events). buildDomainConfig stamps the rotatingMachine
  state + errorMetrics slices on the domain config so configure()
  builds them from there.

5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor
they pinned private methods (_loadConfig, _setupSpecificClass,
_attachInputHandler, _updateNodeStatus) that no longer exist. New
versions drive the public BaseNodeAdapter surface or call extracted
io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10
"private nodeClass tests" for the deferred rewrite plan.

196 / 196 tests pass (basic 110 + integration ~80 + edge ~6).

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

62 lines
2.3 KiB
JavaScript

'use strict';
const { BaseNodeAdapter, convert } = require('generalFunctions');
const Machine = require('./specificClass');
const commands = require('./commands');
// Event-driven: state + measurement events drive recomputes via the
// domain emitter. No tick loop. Status badge polled every second.
class nodeClass extends BaseNodeAdapter {
static DomainClass = Machine;
static commands = commands;
static tickInterval = null;
static statusInterval = 1000;
buildDomainConfig(uiConfig) {
const flowUnit = _resolveUnit(uiConfig.unit, 'volumeFlowRate', 'm3/h');
// Stash extras on the Machine class so its constructor (called by
// BaseNodeAdapter via DomainClass) picks them up alongside the
// machineConfig. Single-threaded JS makes the hand-off race-free.
Machine._pendingExtras = {
stateConfig: {
general: { logging: { enabled: uiConfig.enableLog, logLevel: uiConfig.logLevel } },
movement: { speed: Number(uiConfig.speed), mode: uiConfig.movementMode },
time: {
starting: Number(uiConfig.startup), warmingup: Number(uiConfig.warmup),
stopping: Number(uiConfig.shutdown), coolingdown: Number(uiConfig.cooldown),
},
},
errorMetricsConfig: {},
};
return {
asset: {
uuid: uiConfig.assetUuid || uiConfig.uuid || null,
tagCode: uiConfig.assetTagCode || uiConfig.assetTagNumber || null,
tagNumber: uiConfig.assetTagNumber || null,
unit: flowUnit,
curveUnits: {
pressure: _resolveUnit(uiConfig.curvePressureUnit, 'pressure', 'mbar'),
flow: _resolveUnit(uiConfig.curveFlowUnit || flowUnit, 'volumeFlowRate', flowUnit),
power: _resolveUnit(uiConfig.curvePowerUnit, 'power', 'kW'),
control: (typeof uiConfig.curveControlUnit === 'string' && uiConfig.curveControlUnit.trim()) || '%',
},
},
general: { unit: flowUnit },
flowNumber: uiConfig.flowNumber,
};
}
}
function _resolveUnit(candidate, expectedMeasure, fallback) {
const raw = typeof candidate === 'string' ? candidate.trim() : '';
const fb = String(fallback || '').trim();
if (!raw) return fb;
try {
const desc = convert().describe(raw);
if (expectedMeasure && desc.measure !== expectedMeasure) return fb;
return raw;
} catch (_) { return fb; }
}
module.exports = nodeClass;