Compare commits
2 Commits
e69825a48e
...
d56f8a382c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d56f8a382c | ||
|
|
46adc1ee9b |
8
examples/README.md
Normal file
8
examples/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# valve Example Flows
|
||||
|
||||
Import-ready Node-RED examples for valve.
|
||||
|
||||
## Files
|
||||
- basic.flow.json
|
||||
- integration.flow.json
|
||||
- edge.flow.json
|
||||
6
examples/basic.flow.json
Normal file
6
examples/basic.flow.json
Normal file
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{"id":"valve_basic_tab","type":"tab","label":"valve basic","disabled":false,"info":"valve basic example"},
|
||||
{"id":"valve_basic_node","type":"valve","z":"valve_basic_tab","name":"valve basic","x":420,"y":180,"wires":[["valve_basic_dbg"]]},
|
||||
{"id":"valve_basic_inj","type":"inject","z":"valve_basic_tab","name":"basic trigger","props":[{"p":"topic","vt":"str"},{"p":"payload","vt":"str"}],"topic":"ping","payload":"1","payloadType":"str","x":160,"y":180,"wires":[["valve_basic_node"]]},
|
||||
{"id":"valve_basic_dbg","type":"debug","z":"valve_basic_tab","name":"valve basic debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":660,"y":180,"wires":[]}
|
||||
]
|
||||
6
examples/edge.flow.json
Normal file
6
examples/edge.flow.json
Normal file
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{"id":"valve_edge_tab","type":"tab","label":"valve edge","disabled":false,"info":"valve edge example"},
|
||||
{"id":"valve_edge_node","type":"valve","z":"valve_edge_tab","name":"valve edge","x":420,"y":180,"wires":[["valve_edge_dbg"]]},
|
||||
{"id":"valve_edge_inj","type":"inject","z":"valve_edge_tab","name":"unknown topic","props":[{"p":"topic","vt":"str"},{"p":"payload","vt":"str"}],"topic":"doesNotExist","payload":"x","payloadType":"str","x":170,"y":180,"wires":[["valve_edge_node"]]},
|
||||
{"id":"valve_edge_dbg","type":"debug","z":"valve_edge_tab","name":"valve edge debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":660,"y":180,"wires":[]}
|
||||
]
|
||||
6
examples/integration.flow.json
Normal file
6
examples/integration.flow.json
Normal file
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{"id":"valve_int_tab","type":"tab","label":"valve integration","disabled":false,"info":"valve integration example"},
|
||||
{"id":"valve_int_node","type":"valve","z":"valve_int_tab","name":"valve integration","x":420,"y":180,"wires":[["valve_int_dbg"]]},
|
||||
{"id":"valve_int_inj","type":"inject","z":"valve_int_tab","name":"registerChild","props":[{"p":"topic","vt":"str"},{"p":"payload","vt":"str"}],"topic":"registerChild","payload":"example-child-id","payloadType":"str","x":170,"y":180,"wires":[["valve_int_node"]]},
|
||||
{"id":"valve_int_dbg","type":"debug","z":"valve_int_tab","name":"valve integration debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":680,"y":180,"wires":[]}
|
||||
]
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "Control module valve",
|
||||
"main": "valve.js",
|
||||
"scripts": {
|
||||
"test": "node valve.js"
|
||||
"test": "node --test test/basic/*.test.js test/integration/*.test.js test/edge/*.test.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -249,35 +249,50 @@ class nodeClass {
|
||||
_attachInputHandler() {
|
||||
this.node.on('input', (msg, send, done) => {
|
||||
const v = this.source;
|
||||
try {
|
||||
switch(msg.topic) {
|
||||
case 'registerChild':
|
||||
case 'registerChild': {
|
||||
const childId = msg.payload;
|
||||
const childObj = this.RED.nodes.getNode(childId);
|
||||
if (!childObj || !childObj.source) {
|
||||
v.logger.warn(`registerChild skipped: missing child/source for id=${childId}`);
|
||||
break;
|
||||
}
|
||||
v.childRegistrationUtils.registerChild(childObj.source, msg.positionVsParent);
|
||||
break;
|
||||
}
|
||||
case 'setMode':
|
||||
v.setMode(msg.payload);
|
||||
break;
|
||||
case 'execSequence':
|
||||
case 'execSequence': {
|
||||
const { source: seqSource, action: seqAction, parameter } = msg.payload;
|
||||
v.handleInput(seqSource, seqAction, parameter);
|
||||
break;
|
||||
case 'execMovement':
|
||||
}
|
||||
case 'execMovement': {
|
||||
const { source: mvSource, action: mvAction, setpoint } = msg.payload;
|
||||
v.handleInput(mvSource, mvAction, Number(setpoint));
|
||||
break;
|
||||
case 'emergencystop':
|
||||
}
|
||||
case 'emergencystop': {
|
||||
const { source: esSource, action: esAction } = msg.payload;
|
||||
v.handleInput(esSource, esAction);
|
||||
break;
|
||||
case 'showcurve':
|
||||
v.showCurve();
|
||||
send({ topic : "Showing curve" , payload: v.showCurve() });
|
||||
break;
|
||||
case 'updateFlow': //Als nieuwe flow van header node dan moet deltaP weer opnieuw worden berekend en doorgegeven aan header node
|
||||
v.updateFlow(msg.payload.variant, msg.payload.value, msg.payload.position);
|
||||
}
|
||||
done();
|
||||
case 'showcurve':
|
||||
send({ topic: 'Showing curve', payload: v.showCurve() });
|
||||
break;
|
||||
case 'updateFlow':
|
||||
v.updateFlow(msg.payload.variant, msg.payload.value, msg.payload.position);
|
||||
break;
|
||||
default:
|
||||
v.logger.warn(`Unknown topic: ${msg.topic}`);
|
||||
}
|
||||
} catch (error) {
|
||||
v.logger.error(`Input handler failure: ${error.message}`);
|
||||
}
|
||||
|
||||
if (typeof done === 'function') done();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -288,7 +303,7 @@ class nodeClass {
|
||||
this.node.on('close', (done) => {
|
||||
clearInterval(this._tickInterval);
|
||||
clearInterval(this._statusInterval);
|
||||
done();
|
||||
if (typeof done === 'function') done();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,9 @@ class Valve {
|
||||
}
|
||||
|
||||
setMode(newMode) {
|
||||
const availableModes = defaultConfig.mode.current.rules.values.map(v => v.value);
|
||||
const availableModes = Array.isArray(this.defaultConfig?.mode?.current?.rules?.values)
|
||||
? this.defaultConfig.mode.current.rules.values.map(v => v.value)
|
||||
: Object.keys(this.config?.mode?.allowedSources || {});
|
||||
if (!availableModes.includes(newMode)) {
|
||||
this.logger.warn(`Invalid mode '${newMode}'. Allowed modes are: ${availableModes.join(', ')}`);
|
||||
return;
|
||||
@@ -190,7 +192,7 @@ class Valve {
|
||||
await this.state.moveTo(setpoint);
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error setting setpoint: ${error}`);
|
||||
this.logger.error(`Error setting setpoint: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +206,6 @@ class Valve {
|
||||
switch (variant) {
|
||||
case ("measured"):
|
||||
// put value in measurements container
|
||||
console.log( 'wtf ... ' + value);
|
||||
this.measurements.type("pressure").variant("measured").position(position).value(value);
|
||||
// get latest downstream pressure measurement
|
||||
const measuredDownStreamP = this.measurements.type("pressure").variant("measured").position("downstream").getCurrentValue(); //update downstream pressure measurement
|
||||
|
||||
12
test/README.md
Normal file
12
test/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# valve Test Suite Layout
|
||||
|
||||
Required EVOLV layout:
|
||||
- basic/
|
||||
- integration/
|
||||
- edge/
|
||||
- helpers/
|
||||
|
||||
Baseline structure tests:
|
||||
- basic/structure-module-load.basic.test.js
|
||||
- integration/structure-examples.integration.test.js
|
||||
- edge/structure-examples-node-type.edge.test.js
|
||||
0
test/basic/.gitkeep
Normal file
0
test/basic/.gitkeep
Normal file
8
test/basic/structure-module-load.basic.test.js
Normal file
8
test/basic/structure-module-load.basic.test.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
test('valve module load smoke', () => {
|
||||
assert.doesNotThrow(() => {
|
||||
require('../../valve.js');
|
||||
});
|
||||
});
|
||||
0
test/edge/.gitkeep
Normal file
0
test/edge/.gitkeep
Normal file
11
test/edge/structure-examples-node-type.edge.test.js
Normal file
11
test/edge/structure-examples-node-type.edge.test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const flow = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../../examples/basic.flow.json'), 'utf8'));
|
||||
|
||||
test('basic example includes node type valve', () => {
|
||||
const count = flow.filter((n) => n && n.type === 'valve').length;
|
||||
assert.equal(count >= 1, true);
|
||||
});
|
||||
0
test/helpers/.gitkeep
Normal file
0
test/helpers/.gitkeep
Normal file
0
test/integration/.gitkeep
Normal file
0
test/integration/.gitkeep
Normal file
23
test/integration/structure-examples.integration.test.js
Normal file
23
test/integration/structure-examples.integration.test.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const dir = path.resolve(__dirname, '../../examples');
|
||||
|
||||
function loadJson(file) {
|
||||
return JSON.parse(fs.readFileSync(path.join(dir, file), 'utf8'));
|
||||
}
|
||||
|
||||
test('examples package exists for valve', () => {
|
||||
for (const file of ['README.md', 'basic.flow.json', 'integration.flow.json', 'edge.flow.json']) {
|
||||
assert.equal(fs.existsSync(path.join(dir, file)), true, file + ' missing');
|
||||
}
|
||||
});
|
||||
|
||||
test('example flows are parseable arrays for valve', () => {
|
||||
for (const file of ['basic.flow.json', 'integration.flow.json', 'edge.flow.json']) {
|
||||
const parsed = loadJson(file);
|
||||
assert.equal(Array.isArray(parsed), true);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user