diff --git a/diffuser.html b/diffuser.html
index 969e73f..b3a2eea 100644
--- a/diffuser.html
+++ b/diffuser.html
@@ -1,17 +1,29 @@
+
+
+
+
@@ -40,8 +81,11 @@ RED.nodes.registerType('diffuser', {
@@ -55,6 +99,7 @@ RED.nodes.registerType('diffuser', {
+
Output Formats
@@ -72,21 +117,14 @@ RED.nodes.registerType('diffuser', {
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/diffuser.js b/diffuser.js
index 8674480..86c6d1e 100644
--- a/diffuser.js
+++ b/diffuser.js
@@ -1,9 +1,31 @@
const nameOfNode = 'diffuser';
const nodeClass = require('./src/nodeClass.js');
+const { MenuManager, configManager } = require('generalFunctions');
module.exports = function(RED) {
RED.nodes.registerType(nameOfNode, function(config) {
RED.nodes.createNode(this, config);
this.nodeClass = new nodeClass(config, RED, this, nameOfNode);
});
+
+ const menuMgr = new MenuManager();
+ const cfgMgr = new configManager();
+
+ RED.httpAdmin.get(`/${nameOfNode}/menu.js`, (req, res) => {
+ try {
+ const script = menuMgr.createEndpoint(nameOfNode, ['asset', 'logger']);
+ res.type('application/javascript').send(script);
+ } catch (err) {
+ res.status(500).send(`// Error generating menu: ${err.message}`);
+ }
+ });
+
+ RED.httpAdmin.get(`/${nameOfNode}/configData.js`, (req, res) => {
+ try {
+ const script = cfgMgr.createEndpoint(nameOfNode);
+ res.type('application/javascript').send(script);
+ } catch (err) {
+ res.status(500).send(`// Error generating configData: ${err.message}`);
+ }
+ });
};
diff --git a/src/nodeClass.js b/src/nodeClass.js
index 7973638..87e9475 100644
--- a/src/nodeClass.js
+++ b/src/nodeClass.js
@@ -14,11 +14,19 @@ class nodeClass extends BaseNodeAdapter {
buildDomainConfig(uiConfig) {
const n = (v, fb) => (Number.isFinite(Number(v)) ? Number(v) : fb);
+ const s = (v, fb) => (typeof v === 'string' && v.length ? v : fb);
return {
+ asset: {
+ model: s(uiConfig.model, 'gva-elastox-r'),
+ assetTagNumber: s(uiConfig.assetTagNumber, ''),
+ },
+ general: {
+ unit: s(uiConfig.unit, 'Nm3/h'),
+ },
diffuser: {
number: n(uiConfig.number, 1),
elements: n(uiConfig.i_elements, 1),
- density: n(uiConfig.i_diff_density, 2.4),
+ density: n(uiConfig.i_diff_density, 15),
waterHeight: n(uiConfig.i_m_water, 0),
alfaFactor: n(uiConfig.alfaf, 0.7),
headerPressure: n(uiConfig.i_pressure, 0),
diff --git a/src/specificClass.js b/src/specificClass.js
index 214dbb0..42ea754 100644
--- a/src/specificClass.js
+++ b/src/specificClass.js
@@ -1,6 +1,12 @@
'use strict';
-const { BaseDomain, statusBadge, interpolation, gravity, convert } = require('generalFunctions');
+const { BaseDomain, statusBadge, interpolation, gravity, convert, loadCurve } = require('generalFunctions');
+
+// Default curve used when the node's asset model field is not set. Preserves
+// the historical behaviour of the hardcoded _loadSpecs() (GVA ELASTOX-R at
+// density 2.4 elements/m²) — the existing test suite calibrates against
+// these numbers.
+const DEFAULT_DIFFUSER_MODEL = 'gva-elastox-r';
class Diffuser extends BaseDomain {
static name = 'diffuser';
@@ -19,7 +25,7 @@ class Diffuser extends BaseDomain {
this.i_water_density = _num(d.waterDensity, 997);
this.i_alfa_factor = _num(d.alfaFactor, 0.7);
this.i_n_elements = _posInt(d.elements, 1);
- this.i_diff_density = _num(d.density, 2.4);
+ this.i_diff_density = _num(d.density, 15);
this.i_m_water = _num(d.waterHeight, 0);
this.i_flow = 0;
this.zoneVolume = _num(d.zoneVolume, 0);
@@ -219,11 +225,27 @@ class Diffuser extends BaseDomain {
}
_loadSpecs() {
+ // Curve lookup id: prefer the asset-menu-saved field, fall back to the
+ // legacy GVA ELASTOX-R reference (same numbers as the previous inline
+ // _loadSpecs). If a configured id misses the registry, fall back too —
+ // a missing curve would otherwise crash the constructor in production.
+ const cfgModel =
+ this.config?.asset?.model ||
+ this.config?.model ||
+ DEFAULT_DIFFUSER_MODEL;
+ const raw = loadCurve(cfgModel) || loadCurve(DEFAULT_DIFFUSER_MODEL);
+ if (!raw || !raw.otr_curve || !raw.p_curve) {
+ throw new Error(
+ `diffuser: curve '${cfgModel}' is missing otr_curve/p_curve (registry has: ${Object.keys(raw || {}).join(',') || 'nothing'})`,
+ );
+ }
return {
- supplier: 'GVA', type: 'ELASTOX-R',
+ supplier: raw._meta?.supplier || null,
+ type: raw._meta?.type || null,
+ model: raw._meta?.model || cfgModel,
units: { Nm3: { temp: 20, pressure: 1.01325, RH: 0 } },
- otr_curve: { 2.4: { x: [2, 3, 4, 5, 6, 7, 8, 9, 10], y: [26, 25, 24, 23.5, 23, 22.75, 22.5, 22.25, 22] } },
- p_curve: { 0: { x: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], y: [40, 42.5, 45, 47.5, 50, 51.5, 53, 54.5, 56, 57.5, 59] } },
+ otr_curve: raw.otr_curve,
+ p_curve: raw.p_curve,
};
}
}