Files
EVOLV/wiki/concepts/generalfunctions-api.md
znetsixe 7ded2a4415
Some checks failed
CI / lint-and-test (push) Has been cancelled
docs: consolidate scattered documentation into wiki
Move architecture/, docs/ content into wiki/ for a single source of truth:
- architecture/deployment-blueprint.md → wiki/architecture/
- architecture/stack-architecture-review.md → wiki/architecture/
- architecture/wiki-platform-overview.md → wiki/architecture/
- docs/ARCHITECTURE.md → wiki/architecture/node-architecture.md
- docs/API_REFERENCE.md → wiki/concepts/generalfunctions-api.md
- docs/ISSUES.md → wiki/findings/open-issues-2026-03.md

Remove stale files:
- FUNCTIONAL_ISSUES_BACKLOG.md (was just a redirect pointer)
- temp/ (stale cloud env examples)

Fix README.md gitea URL (centraal.wbd-rd.nl → wbd-rd.nl).
Update wiki index with all consolidated pages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:08:35 +02:00

15 KiB

title, created, updated, status, tags
title created updated status tags
generalFunctions API Reference 2026-03-01 2026-04-07 evolving
api
generalFunctions
reference

generalFunctions API Reference

Shared library (nodes/generalFunctions/) used across all EVOLV Node-RED nodes.

const { logger, outputUtils, MeasurementContainer, ... } = require('generalFunctions');

Table of Contents

  1. Logger
  2. OutputUtils
  3. ValidationUtils
  4. MeasurementContainer
  5. ConfigManager
  6. ChildRegistrationUtils
  7. MenuUtils
  8. EndpointUtils
  9. Positions
  10. AssetLoader / loadCurve

Logger

Structured, level-filtered console logger.

File: src/helper/logger.js

Constructor

new Logger(logging = true, logLevel = 'debug', nameModule = 'N/A')
Param Type Default Description
logging boolean true Enable/disable all output
logLevel string 'debug' Minimum severity: 'debug' | 'info' | 'warn' | 'error'
nameModule string 'N/A' Label prefixed to every message

Methods

Method Signature Description
debug (message: string): void Log at DEBUG level
info (message: string): void Log at INFO level
warn (message: string): void Log at WARN level
error (message: string): void Log at ERROR level
setLogLevel (level: string): void Change minimum level at runtime
toggleLogging (): void Flip logging on/off

Example

const Logger = require('generalFunctions').logger;
const log = new Logger(true, 'info', 'MyNode');
log.info('Node started');    // [INFO] -> MyNode: Node started
log.debug('ignored');        // silent (below 'info')
log.setLogLevel('debug');
log.debug('now visible');    // [DEBUG] -> MyNode: now visible

OutputUtils

Tracks output state and formats messages for InfluxDB or process outputs. Only emits changed fields.

File: src/helper/outputUtils.js

Constructor

new OutputUtils()   // no parameters

Methods

Method Signature Returns Description
formatMsg (output, config, format) object | undefined Diff against last output; returns formatted msg or undefined if nothing changed
checkForChanges (output, format) object Returns only the key/value pairs that changed since last call

format must be 'influxdb' or 'process'.

Example

const out = new OutputUtils();
const msg = out.formatMsg(
  { temperature: 22.5, pressure: 1013 },
  config,
  'influxdb'
);
// msg = { topic: 'nodeName', payload: { measurement, fields, tags, timestamp } }

ValidationUtils

Schema-driven config validation with type coercion, range clamping, and nested object support.

File: src/helper/validationUtils.js

Constructor

new ValidationUtils(loggerEnabled = true, loggerLevel = 'warn')

Methods

Method Signature Returns Description
validateSchema (config, schema, name) object Walk the schema, validate every field, return a clean config. Unknown keys are stripped. Missing keys get their schema default.
constrain (value, min, max) number Clamp a numeric value to [min, max]
removeUnwantedKeys (obj) object Strip rules/description metadata, collapse default values

Supported rules.type values: number, integer, boolean, string, enum, array, set, object, curve, machineCurve.

Example

const ValidationUtils = require('generalFunctions').validation;
const v = new ValidationUtils(true, 'warn');

const schema = {
  temperature: { default: 20, rules: { type: 'number', min: -40, max: 100 } },
  unit:        { default: 'C', rules: { type: 'enum', values: [{ value: 'C' }, { value: 'F' }] } }
};

const validated = v.validateSchema({ temperature: 999 }, schema, 'myNode');
// validated.temperature === 100  (clamped)
// validated.unit === 'C'         (default applied)

MeasurementContainer

Chainable measurement storage organised by type / variant / position. Supports auto unit conversion, windowed statistics, events, and positional difference calculations.

File: src/measurements/MeasurementContainer.js

Constructor

new MeasurementContainer(options = {}, logger)
Option Type Default Description
windowSize number 10 Rolling window for statistics
defaultUnits object { pressure:'mbar', flow:'m3/h', ... } Default unit per measurement type
autoConvert boolean true Auto-convert values to target unit
preferredUnits object {} Per-type unit overrides

Chainable Setters

All return this for chaining.

container
  .type('pressure')
  .variant('static')
  .position('upstream')
  .distance(5)
  .unit('bar')
  .value(3.2, Date.now(), 'bar');
Method Signature Description
type (typeName): this Set measurement type (e.g. 'pressure')
variant (variantName): this Set variant (e.g. 'static', 'differential')
position (positionValue): this Set position (e.g. 'upstream', 'downstream')
distance (distance): this Set physical distance from parent
unit (unitName): this Set unit on the underlying measurement
value (val, timestamp?, sourceUnit?): this Store a value; auto-converts if sourceUnit differs from target

Terminal / Query Methods

Method Signature Returns Description
get () Measurement | null Get the raw measurement object
getCurrentValue (requestedUnit?) number | null Latest value, optionally converted
getAverage (requestedUnit?) number | null Windowed average
getMin () number | null Window minimum
getMax () number | null Window maximum
getAllValues () array | null All stored samples
getLaggedValue (lag?, requestedUnit?) number | null Value from lag samples ago
getLaggedSample (lag?, requestedUnit?) object | null Full sample { value, timestamp, unit } from lag samples ago
exists ({ type?, variant?, position?, requireValues? }) boolean Check if a measurement series exists
difference ({ from?, to?, unit? }) object | null Compute { value, avgDiff, unit } between two positions

Introspection / Lifecycle

Method Signature Returns Description
getTypes () string[] All registered measurement types
getVariants () string[] Variants under current type
getPositions () string[] Positions under current type+variant
getAvailableUnits (measurementType?) string[] Units available for a type
getBestUnit (excludeUnits?) object | null Best human-readable unit for current value
setPreferredUnit (type, unit) this Override default unit for a type
setChildId (id) this Tag container with a child node ID
setChildName (name) this Tag container with a child node name
setParentRef (parent) this Store reference to parent node
clear () void Reset all measurements and chain state

Events

The internal emitter fires "type.variant.position" on every value() call with:

{ value, originalValue, unit, sourceUnit, timestamp, position, distance, variant, type, childId, childName, parentRef }

Example

const { MeasurementContainer } = require('generalFunctions');
const mc = new MeasurementContainer({ windowSize: 5 });

mc.type('pressure').variant('static').position('upstream').value(3.2);
mc.type('pressure').variant('static').position('downstream').value(2.8);

const diff = mc.type('pressure').variant('static').difference();
// diff = { value: -0.4, avgDiff: -0.4, unit: 'mbar', from: 'downstream', to: 'upstream' }

ConfigManager

Loads JSON config files from disk and builds merged runtime configs.

File: src/configs/index.js

Constructor

new ConfigManager(relPath = '.')

relPath is resolved relative to the configs directory.

Methods

Method Signature Returns Description
getConfig (configName) object Load and parse <configName>.json
getAvailableConfigs () string[] List config names (without .json)
hasConfig (configName) boolean Check existence
getBaseConfig () object Shortcut for getConfig('baseConfig')
buildConfig (nodeName, uiConfig, nodeId, domainConfig?) object Merge base schema + UI overrides into a runtime config
createEndpoint (nodeName) string Generate browser JS that injects config into window.EVOLV.nodes

Example

const { configManager } = require('generalFunctions');
const cfg = configManager.buildConfig('measurement', uiConfig, node.id, {
  scaling: { enabled: true, inputMin: 0, inputMax: 100 }
});

ChildRegistrationUtils

Manages parent-child node relationships: registration, lookup, and structure storage.

File: src/helper/childRegistrationUtils.js

Constructor

new ChildRegistrationUtils(mainClass)

mainClass is the parent node instance (must expose .logger and optionally .registerChild()).

Methods

Method Signature Returns Description
registerChild (child, positionVsParent, distance?) Promise<any> Register a child node under the parent. Sets up parent refs, measurement context, and stores by softwareType/category.
getChildrenOfType (softwareType, category?) array Get children filtered by software type and optional category
getChildById (childId) object | null Lookup a single child by its ID
getAllChildren () array All registered children
logChildStructure () void Debug-print the full child tree

Example

const { childRegistrationUtils: CRU } = require('generalFunctions');
const cru = new CRU(parentNode);
await cru.registerChild(sensorNode, 'upstream');
cru.getChildrenOfType('measurement');  // [sensorNode]

MenuUtils

Browser-side UI helper for Node-RED editor. Methods are mixed in from separate modules: toggles, data fetching, URL utils, dropdown population, and HTML generation.

File: src/helper/menuUtils.js

Constructor

new MenuUtils()   // no parameters; sets isCloud=false, configData=null

Key Methods

Toggles -- control UI element visibility:

Method Signature Description
initBasicToggles (elements) Bind log-level row visibility to log checkbox
initMeasurementToggles (elements) Bind scaling input rows to scaling checkbox
initTensionToggles (elements, node) Show/hide tension row based on interpolation method

Data Fetching:

Method Signature Returns Description
fetchData (url, fallbackUrl) Promise<array> Fetch JSON from primary URL; fall back on failure
fetchProjectData (url) Promise<object> Fetch project-level data
apiCall (node) Promise<object> POST to asset-register API

URL Construction:

Method Signature Returns Description
getSpecificConfigUrl (nodeName, cloudAPI) { cloudConfigURL, localConfigURL } Build cloud + local config URLs
constructUrl (base, ...paths) string Join URL segments safely
constructCloudURL (base, ...paths) string Same as constructUrl, for cloud endpoints

Dropdown Population:

Method Signature Description
fetchAndPopulateDropdowns (configUrls, elements, node) Cascading supplier > subType > model > unit dropdowns
populateDropdown (htmlElement, options, node, property, callback?) Fill a <select> with options and wire change events
populateLogLevelOptions (logLevelSelect, configData, node) Populate log-level dropdown from config
populateSmoothingMethods (configUrls, elements, node) Populate smoothing method dropdown
populateInterpolationMethods (configUrls, elements, node) Populate interpolation method dropdown
generateHtml (htmlElement, options, savedValue) Write <option> HTML into an element

EndpointUtils

Server-side helper that serves MenuUtils as browser JavaScript via Node-RED HTTP endpoints.

File: src/helper/endpointUtils.js

Constructor

new EndpointUtils({ MenuUtilsClass? })
Param Type Default Description
MenuUtilsClass class MenuUtils The MenuUtils constructor to introspect

Methods

Method Signature Returns Description
createMenuUtilsEndpoint (RED, nodeName, customHelpers?) void Register GET /<nodeName>/resources/menuUtils.js
generateMenuUtilsCode (nodeName, customHelpers?) string Produce the browser JS string (introspects MenuUtils.prototype)

Example

const EndpointUtils = require('generalFunctions/src/helper/endpointUtils');
const ep = new EndpointUtils();
ep.createMenuUtilsEndpoint(RED, 'valve');
// Browser can now load: GET /valve/resources/menuUtils.js

Positions

Canonical constants for parent-child spatial relationships.

File: src/constants/positions.js

Exports

const { POSITIONS, POSITION_VALUES, isValidPosition } = require('generalFunctions');
Export Type Value
POSITIONS object { UPSTREAM: 'upstream', DOWNSTREAM: 'downstream', AT_EQUIPMENT: 'atEquipment', DELTA: 'delta' }
POSITION_VALUES string[] ['upstream', 'downstream', 'atEquipment', 'delta']
isValidPosition (pos: string): boolean Returns true if pos is one of the four values

AssetLoader / loadCurve

Loads JSON asset files (machine curves, etc.) from the datasets directory with LRU caching.

File: datasets/assetData/curves/index.js

Singleton convenience functions

const { loadCurve } = require('generalFunctions');
Function Signature Returns Description
loadCurve (curveType: string) object | null Load <curveType>.json from the curves directory
loadAsset (datasetType, assetId) object | null Load any JSON asset by dataset folder and ID
getAvailableAssets (datasetType) string[] List asset IDs in a dataset folder

AssetLoader class

new AssetLoader(maxCacheSize = 100)

Same methods as above (loadCurve, loadAsset, getAvailableAssets), plus clearCache().

Example

const { loadCurve } = require('generalFunctions');
const curve = loadCurve('hidrostal-H05K-S03R');
// curve = { flow: [...], head: [...], ... } or null