Compare commits
3 Commits
7acd6c2ce0
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b40b2c736f | ||
|
|
74951e7a23 | ||
|
|
167b1026f1 |
12
CONTRACT.md
12
CONTRACT.md
@@ -68,6 +68,18 @@ from the measurement container (e.g. `delta_predicted_pressure`,
|
|||||||
(`idle → starting → warmingup → operational → accelerating →
|
(`idle → starting → warmingup → operational → accelerating →
|
||||||
decelerating → stopping → coolingdown → idle`, plus `off`).
|
decelerating → stopping → coolingdown → idle`, plus `off`).
|
||||||
|
|
||||||
|
## Limitations vs `rotatingMachine`
|
||||||
|
|
||||||
|
- **No `maintenance` state machine.** The schema's `mode.current` enum
|
||||||
|
accepts `maintenance` (gates sources via `isValidSourceForMode`), but
|
||||||
|
the FSM has no `entermaintenance` / `exitmaintenance` states and the
|
||||||
|
`sequences` schema declares only `startup`, `shutdown`, `emergencystop`,
|
||||||
|
and `boot`. Configuring `maintenance` mode therefore disables external
|
||||||
|
command sources but does not put the valve through a maintenance
|
||||||
|
sequence. Aligns with valve's role as a passive flow-controlled
|
||||||
|
actuator; lift to RM-style FSM if/when site maintenance procedures
|
||||||
|
require explicit state transitions.
|
||||||
|
|
||||||
## Events emitted by `source.measurements.emitter`
|
## Events emitted by `source.measurements.emitter`
|
||||||
|
|
||||||
The `MeasurementContainer` fires `<type>.<variant>.<position>` whenever
|
The `MeasurementContainer` fires `<type>.<variant>.<position>` whenever
|
||||||
|
|||||||
@@ -7,23 +7,33 @@
|
|||||||
function _logger(source, ctx) { return ctx?.logger || source?.logger || null; }
|
function _logger(source, ctx) { return ctx?.logger || source?.logger || null; }
|
||||||
function _send(ctx, ports) { if (typeof ctx?.send === 'function') ctx.send(ports); }
|
function _send(ctx, ports) { if (typeof ctx?.send === 'function') ctx.send(ports); }
|
||||||
|
|
||||||
|
// Resolve the command origin (control authority: parent | GUI | fysical).
|
||||||
|
// The shared commandRegistry stamps msg.origin (default 'parent'); legacy flows
|
||||||
|
// carried it as payload.source. Prefer the legacy field when present so existing
|
||||||
|
// flows keep working, otherwise use the registry-stamped msg.origin.
|
||||||
|
function _origin(msg) {
|
||||||
|
const p = msg && msg.payload;
|
||||||
|
if (p && typeof p === 'object' && typeof p.source === 'string' && p.source) return p.source;
|
||||||
|
return (typeof msg?.origin === 'string' && msg.origin) ? msg.origin : 'parent';
|
||||||
|
}
|
||||||
|
|
||||||
exports.setMode = (source, msg) => {
|
exports.setMode = (source, msg) => {
|
||||||
source.setMode(msg.payload);
|
source.setMode(msg.payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.startup = async (source, msg) => {
|
exports.startup = async (source, msg) => {
|
||||||
const p = msg.payload || {};
|
const p = msg.payload || {};
|
||||||
await source.handleInput(p.source ?? 'parent', 'execSequence', 'startup');
|
await source.handleInput(_origin(msg), 'execSequence', 'startup');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.shutdown = async (source, msg) => {
|
exports.shutdown = async (source, msg) => {
|
||||||
const p = msg.payload || {};
|
const p = msg.payload || {};
|
||||||
await source.handleInput(p.source ?? 'parent', 'execSequence', 'shutdown');
|
await source.handleInput(_origin(msg), 'execSequence', 'shutdown');
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.estop = async (source, msg) => {
|
exports.estop = async (source, msg) => {
|
||||||
const p = msg.payload || {};
|
const p = msg.payload || {};
|
||||||
await source.handleInput(p.source ?? 'parent', p.action ?? 'emergencystop');
|
await source.handleInput(_origin(msg), p.action ?? 'emergencystop');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Legacy umbrella: payload.action selects the canonical verb.
|
// Legacy umbrella: payload.action selects the canonical verb.
|
||||||
@@ -41,7 +51,7 @@ exports.execSequenceAlias = async (source, msg, ctx) => {
|
|||||||
exports.setPosition = async (source, msg) => {
|
exports.setPosition = async (source, msg) => {
|
||||||
const p = msg.payload || {};
|
const p = msg.payload || {};
|
||||||
const action = p.action ?? 'execMovement';
|
const action = p.action ?? 'execMovement';
|
||||||
await source.handleInput(p.source ?? 'parent', action, Number(p.setpoint));
|
await source.handleInput(_origin(msg), action, Number(p.setpoint));
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.dataFlow = (source, msg) => {
|
exports.dataFlow = (source, msg) => {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<script>
|
<script>
|
||||||
RED.nodes.registerType("valve", {
|
RED.nodes.registerType("valve", {
|
||||||
category: "EVOLV",
|
category: "EVOLV",
|
||||||
color: "#86bbdd", // color for the node based on the S88 schema
|
color: "#3CAEA3",
|
||||||
defaults: {
|
defaults: {
|
||||||
|
|
||||||
// Define default properties
|
// Define default properties
|
||||||
@@ -131,6 +131,7 @@
|
|||||||
<label for="node-input-dbaseOutputFormat"><i class="fa fa-database"></i> Database Output</label>
|
<label for="node-input-dbaseOutputFormat"><i class="fa fa-database"></i> Database Output</label>
|
||||||
<select id="node-input-dbaseOutputFormat" style="width:60%;">
|
<select id="node-input-dbaseOutputFormat" style="width:60%;">
|
||||||
<option value="influxdb">influxdb</option>
|
<option value="influxdb">influxdb</option>
|
||||||
|
<option value="frost">frost</option>
|
||||||
<option value="json">json</option>
|
<option value="json">json</option>
|
||||||
<option value="csv">csv</option>
|
<option value="csv">csv</option>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
Reference in New Issue
Block a user