Clone
3
Home
vps1_gitea_admin edited this page 2026-05-11 18:30:17 +00:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

dashboardAPI

Reflects code as of 92d7eba · regenerated 2026-05-11 via npm run wiki:all If this banner is stale, the page may be out of date. Treat as informative, not authoritative.

1. What this node is

dashboardAPI is an HTTP-emitter utility node — it listens for child.register events from other EVOLV nodes and emits one Grafana dashboard upsert HTTP request per node on Port 0. It is not a domain in the BaseDomain sense: no measurements, no tick loop, no children of its own, no parent registration.

2. Position in the platform

flowchart LR
    ps[pumpingStation<br/>Process Cell]:::pc -.child.register.-> dash
    mgc[machineGroupControl<br/>Unit]:::unit -.child.register.-> dash
    rm[rotatingMachine<br/>Equipment]:::equip -.child.register.-> dash
    meas[measurement<br/>Control Module]:::ctrl -.child.register.-> dash
    dash[dashboardAPI<br/>Utility]:::neutral -->|POST /api/dashboards/db| grafana[(Grafana<br/>HTTP API)]
    classDef pc fill:#0c99d9,color:#fff
    classDef unit fill:#50a8d9,color:#000
    classDef equip fill:#86bbdd,color:#000
    classDef ctrl fill:#a9daee,color:#000
    classDef neutral fill:#dddddd,color:#000

dashboardAPI has no S88 level — it's a utility node. Dashed arrows = inbound child.register events; the solid arrow is the outbound HTTP upsert on Port 0 to a downstream http request node.

3. Capability matrix

Capability Status Notes
Accept child.register from any EVOLV node Resolves via RED.nodes.getNodenode._flow.getNode → inline payload.
Emit Grafana dashboard upsert (Port 0) One msg per generated dashboard, shaped for http request.
Walk child graph + emit per-child dashboards includeChildren: true by default; opt-out per call.
Add root → child dashboard links[] Each direct child appears as a link on the root dashboard.
Template selection by softwareType Reads from config/<softwareType>.json; case-insensitive fallback.
Bearer-token auth Set via editor or INFLUXDB_BUCKET env (bucket only).
Domain output on Port 0 Never. Port 0 carries HTTP request envelopes, not measurements.
Port 1 telemetry / Port 2 registration Both unused — see Section 8.
Status badge / tick loop / FSM Stateless; no periodic emission.

4. Code map

flowchart TB
    subgraph nodeRED["nodeClass.js — passive adapter"]
        nc["createRegistry(commands)<br/>dispatch on msg input<br/>NO BaseNodeAdapter"]
    end
    subgraph domain["specificClass.js — DashboardApi service"]
        sc["buildDashboard()<br/>generateDashboardsForGraph()<br/>extractChildren()"]
    end
    subgraph cmd["src/commands/"]
        h["child.register handler<br/>+ registerChild alias"]
    end
    subgraph tpl["config/ (templates)"]
        t["<softwareType>.json<br/>Grafana JSON skeletons"]
    end
    nc --> sc
    nc --> cmd
    sc --> tpl
Module Owns Read first if you're changing…
src/nodeClass.js Input wiring, command dispatch, config build Topic dispatching, configuration mapping.
src/specificClass.js Template loading, dashboard composition, child graph walk UID stability, links, templating-var substitution.
src/commands/ child.register handler + legacy alias Adding / renaming inbound topics.
config/ Per-softwareType Grafana templates Adding support for new node types.

dashboardAPI deliberately does NOT split into concerns/ — its surface is too narrow. See CONTRACT.md → "Why no BaseNodeAdapter / BaseDomain" for the rationale.

5. Topic contract

Auto-generated from src/commands/index.js. Do NOT hand-edit between the markers. Re-run npm run wiki:contract.

Canonical topic Aliases Payload Unit Effect
child.register registerChild any Parent/child plumbing — registers or unregisters a child node.

The legacy registerChild alias logs a one-time deprecation warning on first use. The payload can be a string (child id), { source: {...} }, or { config: {...} }; msg.includeChildren (default true) controls graph-walk depth.

6. Child registration

dashboardAPI does not maintain a child registry of its own. Instead, every inbound child.register triggers a one-shot resolution + dashboard emission. No state is held between calls.

flowchart LR
    src["any EVOLV node<br/>(has functionality.softwareType)"]:::other -->|child.register| dash[dashboardAPI<br/>Utility]:::neutral
    dash --> resolve[resolve child source<br/>RED.nodes.getNode → _flow → inline]
    resolve --> walk["source.generateDashboardsForGraph(child)<br/>(includes children if flag set)"]
    walk --> emit[emit one msg per dashboard<br/>topic='create']
    emit --> http[(downstream<br/>http request node)]
    classDef neutral fill:#dddddd,color:#000
    classDef other fill:#ffffff,stroke:#666
Inbound softwareType Filter Side effect
any child has functionality.softwareType Loads config/<softwareType>.json; emits one upsert msg per dashboard in the graph walk.
(template missing) no matching config/*.json Warns and skips that dashboard. No error.

7. Lifecycle — what one event does

sequenceDiagram
    participant emitter as any EVOLV node
    participant dash as dashboardAPI
    participant api as DashboardApi
    participant out as Port-0 output
    participant grafana as Grafana HTTP API

    emitter->>dash: child.register {source / config / id}
    dash->>dash: commandRegistry dispatch
    dash->>api: generateDashboardsForGraph(child, {includeChildren})
    api->>api: loadTemplate(softwareType)
    api->>api: stableUid + updateTemplatingVar
    api->>api: walk children via childRegistrationUtils
    api-->>dash: [{dashboard, uid, title}, ...]
    loop per dashboard
        dash->>out: msg{topic:'create', url, method, headers, payload}
        out->>grafana: POST /api/dashboards/db
    end

One inbound event yields N outbound HTTP messages (N = 1 + direct child count when includeChildren=true).

8. Data model — getOutput()

dashboardAPI has no domain output. It does not extend BaseDomain and does not implement getOutput(). The wiki:datamodel script falls back to the placeholder below.

No domain output. dashboardAPI emits HTTP request envelopes on Port 0, shaped for a downstream http request node:

{
  topic: 'create',
  url: 'http://<grafana>:<port>/api/dashboards/db',
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    Authorization: 'Bearer …'   // only when bearerToken is set
  },
  payload: { dashboard: {}, folderId: 0, overwrite: true },
  meta: { nodeId, softwareType, uid, title }
}

Port 1 (InfluxDB telemetry) and Port 2 (registration / control plumbing) are unused — dashboardAPI has no measurements and does not register with a parent.

See CONTRACT.md for the full envelope spec.

9. Configuration — editor form ↔ config keys

flowchart TB
    subgraph editor["Node-RED editor form"]
        f1[Protocol]
        f2[Host]
        f3[Port]
        f4[Bearer token]
        f5[Default bucket]
    end
    subgraph config["Domain config slice"]
        c1[grafanaConnector.protocol]
        c2[grafanaConnector.host]
        c3[grafanaConnector.port]
        c4[grafanaConnector.bearerToken]
        c5[defaultBucket]
    end
    f1 --> c1
    f2 --> c2
    f3 --> c3
    f4 --> c4
    f5 --> c5
Form field Config key Default Range Where used
Protocol grafanaConnector.protocol http http|https grafanaUpsertUrl()
Host grafanaConnector.host localhost hostname grafanaUpsertUrl()
Port grafanaConnector.port 3000 165535 grafanaUpsertUrl()
Bearer token grafanaConnector.bearerToken '' string Authorization header
Default bucket defaultBucket '' / INFLUXDB_BUCKET env string updateTemplatingVar(bucket)

11. Examples

Tier File What it shows Status
Basic examples/01-Basic.flow.json Inject child.register payload + a downstream http request → mock Grafana TBD
Integration examples/02-Integration.flow.json Real EVOLV node (e.g. pumpingStation) wired into dashboardAPI TBD
Dashboard n/a dashboardAPI is the dashboard plumbing — no FlowFuse tier

12. Debug recipes

Symptom First thing to check Where to look
No HTTP request emitted Did the child.register resolve a source? source.generateDashboardsForGraph returns [] when child has no config. node_redlog for "generateDashboardsForGraph skipped" warning.
Skipping dashboard generation: no template config/<softwareType>.json missing for this node type. config/ directory; add a template.
Empty Authorization header bearerToken not set in editor. Editor form → Bearer token field.
Wrong bucket in Grafana defaultBucket overrides position-based default. Check INFLUXDB_BUCKET env. _buildConfig in nodeClass.js.
registerChild alias warns once Expected — migrate callers to child.register. Caller's msg.topic.

Never ship enableLog: 'debug' in a demo — fills the container log within seconds and obscures real errors.

13. When you would NOT use this node

  • Use dashboardAPI when you want auto-generated Grafana dashboards from EVOLV node topology. If you maintain dashboards by hand in Grafana, skip it.
  • Don't use dashboardAPI as a generic HTTP client — it only emits Grafana dashboard upserts. For arbitrary HTTP, use a plain http request node.
  • Don't put dashboardAPI in a hot data path. It fires on registration events, not on each tick — wiring tick data to it is a misuse.

14. Known limitations / current issues

# Issue Tracked in
1 No domain output — cannot be introspected through the standard getOutput() channel; debugging relies on Port 0 HTTP envelopes. CONTRACT.md → "Why no BaseNodeAdapter / BaseDomain"
2 Template discovery is filename-based; renaming a node's softwareType requires renaming the template file (with the machineGroupControl → machineGroup.json alias being a one-off). _templateFileForSoftwareType in specificClass.js
3 No retry / circuit-breaker on the downstream http request — Grafana outages drop dashboards silently. TBD
4 Tier 1/2 example flows not yet written. P9 wiki cleanup follow-up