Files
valve/src/io/output.js
znetsixe e27135bdc4 P6: convert valve to BaseDomain + BaseNodeAdapter + concern split
Refactor of valve to use the platform infrastructure (BaseDomain, BaseNodeAdapter,
ChildRouter, commandRegistry, statusBadge). Extracts concerns into
focused modules per .claude/refactor/MODULE_SPLIT.md generic template.
Tests stay green; CONTRACT.md generated; legacy aliases preserved.

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

74 lines
2.9 KiB
JavaScript

'use strict';
const { statusBadge } = require('generalFunctions');
const STATE_SYMBOLS = {
off: '⬛', idle: '⏸️', operational: '⏵️',
starting: '⏯️', warmingup: '🔄', accelerating: '⏩',
stopping: '⏹️', coolingdown: '❄️', decelerating: '⏪',
};
const STATE_FILL = {
off: 'red', idle: 'blue',
operational: 'green', warmingup: 'green',
starting: 'yellow', accelerating: 'yellow',
stopping: 'yellow', coolingdown: 'yellow', decelerating: 'yellow',
};
const SHOW_METRICS = new Set(['operational', 'warmingup', 'accelerating', 'decelerating']);
function buildOutput(host) {
const output = {};
Object.entries(host.measurements.measurements || {}).forEach(([type, variants]) => {
Object.entries(variants || {}).forEach(([variant, positions]) => {
Object.keys(positions || {}).forEach((position) => {
const unit = host._outputUnitForType(type);
const value = host._readMeasurement(type, variant, position, unit);
if (value != null) output[`${position}_${variant}_${type}`] = value;
});
});
});
output.state = host.state.getCurrentState();
output.percentageOpen = host.state.getCurrentPosition();
output.moveTimeleft = host.state.getMoveTimeLeft();
output.mode = host.currentMode;
return output;
}
function buildStatusBadge(host) {
try {
const mode = host.currentMode;
const stateName = host.state.getCurrentState();
const flowUnit = host.unitPolicyView.output.flow || 'm3/h';
const pressureUnit = host.unitPolicyView.output.pressure || 'mbar';
const flow = Math.round(host.measurements.type('flow').variant('predicted').position('downstream').getCurrentValue(flowUnit));
let deltaP = host.measurements.type('pressure').variant('predicted').position('delta').getCurrentValue(pressureUnit);
if (deltaP !== null && deltaP !== undefined) deltaP = parseFloat(deltaP.toFixed(0));
if (Number.isNaN(deltaP)) deltaP = '∞';
const pos = Math.round(host.state.getCurrentPosition() * 100) / 100;
const symbol = STATE_SYMBOLS[stateName] || '❔';
const fill = STATE_FILL[stateName] || 'grey';
let badge;
if (SHOW_METRICS.has(stateName)) {
badge = statusBadge.compose(
[`${mode}: ${symbol}`, `${pos}%`, `💨${flow}${flowUnit}`, `ΔP${deltaP} ${pressureUnit}`],
{ fill, shape: 'dot' }
);
} else {
badge = statusBadge.compose([`${mode}: ${symbol}`], { fill, shape: 'dot' });
}
const fc = typeof host.getFluidCompatibility === 'function' ? host.getFluidCompatibility() : null;
if (fc && (fc.status === 'mismatch' || fc.status === 'conflict')) {
return { fill: 'yellow', shape: 'ring', text: `${badge.text} | ⚠ ${fc.message}` };
}
return badge;
} catch (err) {
host.logger?.error?.(`getStatusBadge: ${err.message}`);
return statusBadge.error('Status Error');
}
}
module.exports = { buildOutput, buildStatusBadge };