forked from p.vanderwilt/settler
Compare commits
4 Commits
efb99df107
...
7f2d326612
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f2d326612 | |||
| 9c98f1a139 | |||
| 49eeafdcf9 | |||
| 93b67e607a |
119
package-lock.json
generated
119
package-lock.json
generated
@@ -1,119 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "settler",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "settler",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"license": "SEE LICENSE",
|
|
||||||
"dependencies": {
|
|
||||||
"generalFunctions": "git+https://gitea.centraal.wbd-rd.nl/RnD/generalFunctions.git",
|
|
||||||
"mathjs": "^14.5.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/runtime": {
|
|
||||||
"version": "7.28.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
|
||||||
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/complex.js": {
|
|
||||||
"version": "2.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.4.2.tgz",
|
|
||||||
"integrity": "sha512-qtx7HRhPGSCBtGiST4/WGHuW+zeaND/6Ld+db6PbrulIB1i2Ev/2UPiqcmpQNPSyfBKraC0EOvOKCB5dGZKt3g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/rawify"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/decimal.js": {
|
|
||||||
"version": "10.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
|
|
||||||
"integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/escape-latex": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/fraction.js": {
|
|
||||||
"version": "5.3.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
|
|
||||||
"integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/rawify"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/generalFunctions": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "git+https://gitea.centraal.wbd-rd.nl/RnD/generalFunctions.git#9b7a8ae2c8ae149f48608e2fa5a180b486700978",
|
|
||||||
"license": "SEE LICENSE"
|
|
||||||
},
|
|
||||||
"node_modules/javascript-natural-sort": {
|
|
||||||
"version": "0.7.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
|
|
||||||
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/mathjs": {
|
|
||||||
"version": "14.9.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/mathjs/-/mathjs-14.9.1.tgz",
|
|
||||||
"integrity": "sha512-xhqv8Xjf+caWG3WlaPekg4v8QFOR3D5+8ycfcjMcPcnCNDgAONQLaLfyGgrggJrcHx2yUGCpACRpiD4GmXwX+Q==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.26.10",
|
|
||||||
"complex.js": "^2.2.5",
|
|
||||||
"decimal.js": "^10.4.3",
|
|
||||||
"escape-latex": "^1.2.0",
|
|
||||||
"fraction.js": "^5.2.1",
|
|
||||||
"javascript-natural-sort": "^0.7.1",
|
|
||||||
"seedrandom": "^3.0.5",
|
|
||||||
"tiny-emitter": "^2.1.0",
|
|
||||||
"typed-function": "^4.2.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"mathjs": "bin/cli.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/seedrandom": {
|
|
||||||
"version": "3.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
|
|
||||||
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/tiny-emitter": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/typed-function": {
|
|
||||||
"version": "4.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.2.1.tgz",
|
|
||||||
"integrity": "sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"description": "Sludge settler model for Node-Red",
|
"description": "Sludge settler model for Node-Red",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://gitea.centraal.wbd-rd.nl/p.vanderwilt/settler.git"
|
"url": "https://gitea.centraal.wbd-rd.nl/RnD/settler.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"settler",
|
"settler",
|
||||||
|
|||||||
18
settler.html
18
settler.html
@@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
RED.nodes.registerType("settler", {
|
RED.nodes.registerType("settler", {
|
||||||
category: "WWTP",
|
category: "EVOLV",
|
||||||
color: "#e4a363",
|
color: "#e4a363",
|
||||||
defaults: {
|
defaults: {
|
||||||
name: { value: "" },
|
name: { value: "" },
|
||||||
TS_set: { value: 0.1, required: true },
|
|
||||||
inlet: { value: 1, required: true }
|
enableLog: { value: false },
|
||||||
|
logLevel: { value: "error" },
|
||||||
|
|
||||||
|
positionVsParent: { value: "" }
|
||||||
},
|
},
|
||||||
inputs: 1,
|
inputs: 1,
|
||||||
outputs: 3,
|
outputs: 3,
|
||||||
@@ -42,11 +45,6 @@
|
|||||||
if (window.EVOLV?.nodes?.measurement?.positionMenu?.saveEditor) {
|
if (window.EVOLV?.nodes?.measurement?.positionMenu?.saveEditor) {
|
||||||
window.EVOLV.nodes.rotatingMachine.positionMenu.saveEditor(this);
|
window.EVOLV.nodes.rotatingMachine.positionMenu.saveEditor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inlet = parseInt($("#node-input-n_inlets").typedInput("value"));
|
|
||||||
if (inlet < 1) {
|
|
||||||
RED.notify("Number of inlets not set correctly", {type: "error"});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -56,10 +54,6 @@
|
|||||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
<input type="text" id="node-input-name" placeholder="Name">
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
|
||||||
<label for="node-input-inlet"><i class="fa fa-tag"></i> Assigned inlet return line</label>
|
|
||||||
<input type="text" id="node-input-inlet" placeholder="#">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Logger fields injected here -->
|
<!-- Logger fields injected here -->
|
||||||
<div id="logger-fields-placeholder"></div>
|
<div id="logger-fields-placeholder"></div>
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class nodeClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_tick(){
|
_tick(){
|
||||||
this.node.send([null, null, null]);
|
this.node.send([this.source.getEffluent, null, null]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_attachCloseHandler() {
|
_attachCloseHandler() {
|
||||||
|
|||||||
@@ -14,14 +14,57 @@ class Settler {
|
|||||||
this.returnPump = null;
|
this.returnPump = null;
|
||||||
|
|
||||||
// state variables
|
// state variables
|
||||||
this.F_in = 0;
|
this.F_in = 0; // debit in
|
||||||
|
this.Cs_in = new Array(13).fill(0); // Concentrations in
|
||||||
|
this.C_TS = 2500; // Total solids concentration sludge
|
||||||
}
|
}
|
||||||
|
|
||||||
get getEffluent() {
|
get getEffluent() {
|
||||||
return;
|
// constrain flow to prevent negatives
|
||||||
|
const F_s = Math.min((this.F_in * this.Cs_in[12]) / this.C_TS, this.F_in);
|
||||||
|
const F_eff = this.F_in - F_s;
|
||||||
|
|
||||||
|
let F_sr = 0;
|
||||||
|
if (this.returnPump) {
|
||||||
|
F_sr = Math.min(this.returnPump.measurements.type("flow").variant("measured").position("atEquipment").getCurrentValue(), F_s);
|
||||||
|
}
|
||||||
|
const F_so = F_s - F_sr;
|
||||||
|
|
||||||
|
// effluent
|
||||||
|
const Cs_eff = structuredClone(this.Cs_in);
|
||||||
|
if (F_s > 0) {
|
||||||
|
Cs_eff[7] = 0;
|
||||||
|
Cs_eff[8] = 0;
|
||||||
|
Cs_eff[9] = 0;
|
||||||
|
Cs_eff[10] = 0;
|
||||||
|
Cs_eff[11] = 0;
|
||||||
|
Cs_eff[12] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sludge
|
||||||
|
const Cs_s = structuredClone(this.Cs_in);
|
||||||
|
if (F_s > 0) {
|
||||||
|
Cs_s[7] = this.F_in * this.Cs_in[7] / F_s;
|
||||||
|
Cs_s[8] = this.F_in * this.Cs_in[8] / F_s;
|
||||||
|
Cs_s[9] = this.F_in * this.Cs_in[9] / F_s;
|
||||||
|
Cs_s[10] = this.F_in * this.Cs_in[10] / F_s;
|
||||||
|
Cs_s[11] = this.F_in * this.Cs_in[11] / F_s;
|
||||||
|
Cs_s[12] = this.F_in * this.Cs_in[12] / F_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{ topic: "Fluent", payload: { inlet: 0, F: F_eff, C: Cs_eff }, timestamp: Date.now() },
|
||||||
|
{ topic: "Fluent", payload: { inlet: 1, F: F_so, C: Cs_s }, timestamp: Date.now() },
|
||||||
|
{ topic: "Fluent", payload: { inlet: 2, F: F_sr, C: Cs_s }, timestamp: Date.now() }
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
registerChild(child, softwareType) {
|
registerChild(child, softwareType) {
|
||||||
|
if(!child) {
|
||||||
|
this.logger.error(`Invalid ${softwareType} child provided.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (softwareType) {
|
switch (softwareType) {
|
||||||
case "measurement":
|
case "measurement":
|
||||||
this.logger.debug(`Registering measurement child...`);
|
this.logger.debug(`Registering measurement child...`);
|
||||||
@@ -42,11 +85,6 @@ class Settler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_connectMeasurement(measurementChild) {
|
_connectMeasurement(measurementChild) {
|
||||||
if (!measurementChild) {
|
|
||||||
this.logger.error("Invalid measurement provided.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const position = measurementChild.config.functionality.positionVsParent;
|
const position = measurementChild.config.functionality.positionVsParent;
|
||||||
const measurementType = measurementChild.config.asset.type;
|
const measurementType = measurementChild.config.asset.type;
|
||||||
const eventName = `${measurementType}.measured.${position}`;
|
const eventName = `${measurementType}.measured.${position}`;
|
||||||
@@ -67,13 +105,8 @@ class Settler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_connectReactor(reactorChild) {
|
_connectReactor(reactorChild) {
|
||||||
if (!reactorChild) {
|
|
||||||
this.logger.error("Invalid reactor provided.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reactorChild.config.functionality.positionVsParent != "upstream") {
|
if (reactorChild.config.functionality.positionVsParent != "upstream") {
|
||||||
this.logger.warn("Reactor children of reactors should always be upstream.");
|
this.logger.warn("Reactor children of settlers should be upstream.");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.upstreamReactor = reactorChild;
|
this.upstreamReactor = reactorChild;
|
||||||
@@ -87,14 +120,23 @@ class Settler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_connectMachine(machineChild) {
|
_connectMachine(machineChild) {
|
||||||
if (!machineChild) {
|
if (machineChild.config.functionality.positionVsParent == "downstream") {
|
||||||
this.logger.error("Invalid rotating machine provided.");
|
machineChild.upstreamSource = this;
|
||||||
|
this.returnPump = machineChild;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.logger.warn(`Failed to register machine child.`);
|
||||||
|
}
|
||||||
|
|
||||||
if (machineChild.config.functionality.positionVsParent == "downstream") {
|
_updateMeasurement(measurementType, value, position, context) {
|
||||||
machineChild.upstreamReactor = this;
|
switch(measurementType) {
|
||||||
this.returnPump = machineChild;
|
case "quantity (tss)":
|
||||||
|
this.C_TS = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.logger.error(`Type '${measurementType}' not recognized for measured update.`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user