Compare commits
5 Commits
76951f104d
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9427b64bbe | ||
|
|
6c88b6464d | ||
|
|
4eb286771e | ||
|
|
fa4f065104 | ||
|
|
aff866bd9b |
@@ -1,6 +1,6 @@
|
|||||||
# monster — Claude Code context
|
# monster — Claude Code context
|
||||||
|
|
||||||
Multi-parameter biological process monitoring.
|
Sampling-cabinet pulse counter — measures sampled volumes and pulse cadence; does *not* analyze constituents (NH4 / NO3 / COD / TSS). For multi-parameter analyses, wire the output to an upstream/downstream analyzer node.
|
||||||
Part of the [EVOLV](https://gitea.wbd-rd.nl/RnD/EVOLV) wastewater-automation platform.
|
Part of the [EVOLV](https://gitea.wbd-rd.nl/RnD/EVOLV) wastewater-automation platform.
|
||||||
|
|
||||||
## S88 classification
|
## S88 classification
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ Hand-maintained for Phase 6; the `## Inputs` table is generated from
|
|||||||
| `data.flow` | `input_q` | `{ value: number, unit: string }` | Converts to m³/h and pushes into `flow.manual.atequipment`. Blends with measured-child flow in `getEffectiveFlow()`. |
|
| `data.flow` | `input_q` | `{ value: number, unit: string }` | Converts to m³/h and pushes into `flow.manual.atequipment`. Blends with measured-child flow in `getEffectiveFlow()`. |
|
||||||
| `set.mode` | `setMode` | string | Delegated to `source.setMode()` if defined. Reserved for future use. |
|
| `set.mode` | `setMode` | string | Delegated to `source.setMode()` if defined. Reserved for future use. |
|
||||||
| `set.model-prediction` | `model_prediction` | numeric | Delegated to `source.setModelPrediction()` if defined. Reserved for future use. |
|
| `set.model-prediction` | `model_prediction` | numeric | Delegated to `source.setModelPrediction()` if defined. Reserved for future use. |
|
||||||
|
| `child.register` | `registerChild` | `string` — the child node's Node-RED id | Resolves the child via `RED.nodes.getNode` and registers it through `childRegistrationUtils` at the supplied `msg.positionVsParent`. |
|
||||||
|
|
||||||
Aliases log a one-time deprecation warning the first time they fire.
|
Aliases log a one-time deprecation warning the first time they fire.
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +1,34 @@
|
|||||||
# Monster Example Flows
|
# Monster Example Flows
|
||||||
|
|
||||||
Import-ready Node-RED examples for `monster`.
|
Import-ready Node-RED examples for `monster` — a sampling-cabinet pulse
|
||||||
|
counter (volumetric, not an analytical multi-parameter monitor; see
|
||||||
|
the framing note in `CONTRACT.md`).
|
||||||
|
|
||||||
|
## Files present in this repo
|
||||||
|
|
||||||
## Files
|
|
||||||
- `basic.flow.json`
|
- `basic.flow.json`
|
||||||
- Purpose: quick-start flow with dashboard charts for key monster outputs.
|
- Inject-driven quick-start flow with the dashboard widgets for the
|
||||||
- `integration.flow.json`
|
main monster outputs (`pulse`, `bucketVol`, `m3PerPuls`, `running`,
|
||||||
- Purpose: lightweight integration contract example (`registerChild` path).
|
`predFlow`).
|
||||||
- `edge.flow.json`
|
- `02-integrated-e2e.json`
|
||||||
- Purpose: unknown-topic/edge handling smoke example.
|
- End-to-end orchestration template: wires a flow source, a schedule,
|
||||||
- `monster-dashboard.flow.json`
|
rain-data input, and the dashboard surface. **Not yet validated
|
||||||
- Purpose: richer dashboard-focused visualization of process output.
|
against live Node-RED** — treat as a wiring reference until smoke-
|
||||||
- Includes:
|
tested. Placeholder credentials (`__SET_*__`) need to be replaced
|
||||||
- manual flow input
|
before any real deployment.
|
||||||
- manual start trigger
|
|
||||||
- seeded `rain_data` and `monsternametijden`
|
|
||||||
- parsed report fields (`m3Total`, `m3PerPuls`, `pulse`, `running`)
|
|
||||||
- `monster-api-dashboard.flow.json`
|
|
||||||
- Purpose: full orchestration template around `monster` with API paths and dashboard output.
|
|
||||||
- Includes:
|
|
||||||
- Open-Meteo weather fetch -> `rain_data`
|
|
||||||
- Aquon SFTP CSV fetch -> `monsternametijden`
|
|
||||||
- Z-Info token + import payload builder for `m3Total`/`m3PerPuls`
|
|
||||||
- dashboard API publish template (Grafana)
|
|
||||||
- placeholder-only credentials/hosts (`__SET_*__`)
|
|
||||||
|
|
||||||
## Notes
|
## Files referenced in earlier docs but not yet shipped
|
||||||
- `basic.flow.json` and `monster-dashboard.flow.json` are intentionally API-free.
|
|
||||||
- `monster-api-dashboard.flow.json` is the full API template variant and must be hardened with environment-backed secrets before production use.
|
`integration.flow.json`, `edge.flow.json`, `monster-dashboard.flow.json`,
|
||||||
- `ui-chart` uses series by `msg.topic` (`category: "topic"`, `categoryType: "msg"`).
|
and `monster-api-dashboard.flow.json` were mentioned by prior versions
|
||||||
|
of this README; they do not exist in the repo at this commit. They are
|
||||||
|
tracked as TODOs in `wiki/Reference-Examples.md`. When generated, follow
|
||||||
|
the tier convention used by the rotatingMachine examples
|
||||||
|
(`01-Basic.json`, `02-Integration.json`, `03-Dashboard.json`).
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- `ui-chart` uses series by `msg.topic` (`category: "topic"`,
|
||||||
|
`categoryType: "msg"`).
|
||||||
|
- API templates (rain fetch / Aquon SFTP / Z-Info import) must be
|
||||||
|
hardened with environment-backed secrets before production use.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<script>
|
<script>
|
||||||
RED.nodes.registerType("monster", {
|
RED.nodes.registerType("monster", {
|
||||||
category: "EVOLV",
|
category: "EVOLV",
|
||||||
color: "#4f8582",
|
color: "#9C5BB0",
|
||||||
defaults: {
|
defaults: {
|
||||||
|
|
||||||
// Define default properties
|
// Define default properties
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
// handler (the legacy nodeClass did it inline) — anything else inbound
|
// handler (the legacy nodeClass did it inline) — anything else inbound
|
||||||
// is passed straight through to source.handleInput.
|
// is passed straight through to source.handleInput.
|
||||||
|
|
||||||
const { convert } = require('generalFunctions');
|
|
||||||
|
|
||||||
exports.cmdStart = (source, msg) => {
|
exports.cmdStart = (source, msg) => {
|
||||||
source.handleInput('i_start', Boolean(msg.payload));
|
source.handleInput('i_start', Boolean(msg.payload));
|
||||||
};
|
};
|
||||||
@@ -20,17 +18,15 @@ exports.setRain = (source, msg) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.dataFlow = (source, msg, ctx) => {
|
exports.dataFlow = (source, msg, ctx) => {
|
||||||
|
// The registry has already normalised any accepted shape (number, numeric
|
||||||
|
// string, or { value, unit }) to a number in m3/h and tagged msg.unit.
|
||||||
const log = ctx?.logger || source.logger;
|
const log = ctx?.logger || source.logger;
|
||||||
const value = Number(msg.payload?.value);
|
const value = Number(msg.payload);
|
||||||
const unit = msg.payload?.unit;
|
if (!Number.isFinite(value)) {
|
||||||
if (!Number.isFinite(value) || !unit) {
|
log?.warn?.(`data.flow payload must be numeric, got '${JSON.stringify(msg.payload)}'.`);
|
||||||
log?.warn?.('data.flow payload must include numeric value and unit.');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let converted = value;
|
source.handleInput('input_q', { value, unit: msg.unit || 'm3/h' });
|
||||||
try { converted = convert(value).from(unit).to('m3/h'); }
|
|
||||||
catch (err) { log?.warn?.(`data.flow unit conversion failed: ${err.message}`); return; }
|
|
||||||
source.handleInput('input_q', { value: converted, unit: 'm3/h' });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.setMode = (source, msg) => {
|
exports.setMode = (source, msg) => {
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ module.exports = [
|
|||||||
{
|
{
|
||||||
topic: 'data.flow',
|
topic: 'data.flow',
|
||||||
aliases: ['input_q'],
|
aliases: ['input_q'],
|
||||||
payloadSchema: { type: 'object' },
|
// any: number, numeric string, or { value, unit } — the registry normalises
|
||||||
// Compound payload `{value, unit}` — handler converts internally to m3/h.
|
// all of them to a number in `unit` (m3/h) before the handler runs.
|
||||||
// Registry-level normalisation is skipped (the handler reads payload.value /
|
payloadSchema: { type: 'any' },
|
||||||
// payload.unit directly; flattening would break it).
|
unit: 'm3/h',
|
||||||
description: 'Push the upstream flow measurement (payload: {value, unit}).',
|
description: 'Push the upstream flow measurement (payload: number or {value, unit}).',
|
||||||
handler: handlers.dataFlow,
|
handler: handlers.dataFlow,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,19 +16,19 @@
|
|||||||
|
|
||||||
The registry lives in `src/commands/index.js`. Each descriptor maps a canonical `msg.topic` to its handler; aliases emit a one-time deprecation warning the first time they fire.
|
The registry lives in `src/commands/index.js`. Each descriptor maps a canonical `msg.topic` to its handler; aliases emit a one-time deprecation warning the first time they fire.
|
||||||
|
|
||||||
<!-- BEGIN AUTOGEN: topic-contract — populate via wiki-gen tool (TODO) -->
|
<!-- BEGIN AUTOGEN: topic-contract -->
|
||||||
|
|
||||||
| Canonical topic | Aliases | Payload | Unit | Effect |
|
| Canonical topic | Aliases | Payload | Unit | Effect |
|
||||||
|:---|:---|:---|:---|:---|
|
|---|---|---|---|---|
|
||||||
| `cmd.start` | `i_start` | `any` (coerced to `Boolean`) | — | Sets `source.i_start`. On the next tick a sampling run begins if `validateFlowBounds` passes. |
|
| `cmd.start` | `i_start` | any | — | Trigger / release the sampler start gate. |
|
||||||
| `set.schedule` | `monsternametijden` | array of AQUON rows (`SAMPLE_NAME`, `DESCRIPTION`, `SAMPLED_DATE`, `START_DATE`, `END_DATE`) | — | Stores the schedule and recomputes `nextDate` + `daysPerYear` for the configured `aquonSampleName`. |
|
| `set.schedule` | `monsternametijden` | any | — | Replace the sampling-times schedule. |
|
||||||
| `set.rain` | `rain_data` | per-location rain forecast (Open-Meteo shape) | — | Aggregates hourly precipitation into `sumRain` / `avgRain`. **Skipped while `running=true`.** |
|
| `set.rain` | `rain_data` | any | — | Push current rain-event data into the sampler logic. |
|
||||||
| `data.flow` | `input_q` | `{ value: number, unit: string }` | volumeFlowRate (any unit `convert()` accepts) | Converts to m³/h, pushes into `flow.manual.atequipment`. Blends with measured-child flow in `getEffectiveFlow()`. |
|
| `data.flow` | `input_q` | any | `volumeFlowRate` (default `m3/h`) | Push the upstream flow measurement (payload: number or {value, unit}). |
|
||||||
| `set.mode` | `setMode` | any | — | **Reserved.** Handler delegates to `source.setMode()` which is currently undefined; no-op today. |
|
| `set.mode` | `setMode` | any | — | Switch the monster between auto / manual modes. |
|
||||||
| `set.model-prediction` | `model_prediction` | any | — | **Reserved.** Handler delegates to `source.setModelPrediction()` which is currently undefined; no-op today. |
|
| `set.model-prediction` | `model_prediction` | any | — | Push the upstream rain-prediction snapshot used by the sampler. |
|
||||||
| `child.register` | `registerChild` | string (child node id) | — | Register a `measurement` child with this monster. Port 2 wiring does this automatically in normal flows. |
|
| `child.register` | `registerChild` | `string` | — | Register a child node (typically a measurement) with this monster. |
|
||||||
|
|
||||||
<!-- END AUTOGEN -->
|
<!-- END AUTOGEN: topic-contract -->
|
||||||
|
|
||||||
### Mode / source / action allow-lists
|
### Mode / source / action allow-lists
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user