fix(charts): add all required FlowFuse ui-chart properties + document in rule set
Some checks failed
CI / lint-and-test (push) Has been cancelled
Some checks failed
CI / lint-and-test (push) Has been cancelled
Charts rendered blank because the helper was missing 15+ required
FlowFuse properties. The critical three:
- interpolation: "linear" (no line drawn without it)
- yAxisProperty: "payload" + yAxisPropertyType: "msg" (chart didn't
know which msg field to plot)
- xAxisPropertyType: "timestamp" (chart didn't know the x source)
Also: width/height must be numbers not strings, colors/textColor/
gridColor arrays must be present, and stackSeries/bins/xAxisFormat/
xAxisFormatType all need explicit values.
Fixed the ui_chart helper to include every property from the working
rotatingMachine/examples/03-Dashboard.json charts. Added the full
required-property template + gotcha list to the flow-layout rule set
(Section 4) so this class of bug is caught by reference on the next
chart build.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,51 @@ ui-chart with `category: "topic"` + `categoryType: "msg"` plots one series per u
|
|||||||
- One chart per **metric type** (one chart for flow, one for power).
|
- One chart per **metric type** (one chart for flow, one for power).
|
||||||
- Each chart receives msgs whose `topic` is the **series label** (e.g. `Pump A`, `Pump B`, `Pump C`).
|
- Each chart receives msgs whose `topic` is the **series label** (e.g. `Pump A`, `Pump B`, `Pump C`).
|
||||||
|
|
||||||
|
### Required chart properties (FlowFuse ui-chart renders blank without ALL of these)
|
||||||
|
|
||||||
|
Derived from working charts in rotatingMachine/examples/03-Dashboard. Every property listed below is mandatory — omit any one and the chart renders blank with no error message.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "ui-chart",
|
||||||
|
"chartType": "line",
|
||||||
|
"interpolation": "linear",
|
||||||
|
"category": "topic",
|
||||||
|
"categoryType": "msg",
|
||||||
|
"xAxisType": "time",
|
||||||
|
"xAxisProperty": "",
|
||||||
|
"xAxisPropertyType": "timestamp",
|
||||||
|
"xAxisFormat": "",
|
||||||
|
"xAxisFormatType": "auto",
|
||||||
|
"yAxisProperty": "payload",
|
||||||
|
"yAxisPropertyType": "msg",
|
||||||
|
"action": "append",
|
||||||
|
"stackSeries": false,
|
||||||
|
"pointShape": "circle",
|
||||||
|
"pointRadius": 4,
|
||||||
|
"showLegend": true,
|
||||||
|
"bins": 10,
|
||||||
|
"width": 12,
|
||||||
|
"height": 6,
|
||||||
|
"removeOlder": "15",
|
||||||
|
"removeOlderUnit": "60",
|
||||||
|
"removeOlderPoints": "",
|
||||||
|
"colors": ["#0095FF","#FF0000","#FF7F0E","#2CA02C","#A347E1","#D62728","#FF9896","#9467BD","#C5B0D5"],
|
||||||
|
"textColor": ["#666666"],
|
||||||
|
"textColorDefault": true,
|
||||||
|
"gridColor": ["#e5e5e5"],
|
||||||
|
"gridColorDefault": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key gotchas:**
|
||||||
|
- `interpolation` MUST be set (`"linear"`, `"step"`, `"bezier"`, `"cubic"`, `"cubic-mono"`). Without it: no line drawn.
|
||||||
|
- `yAxisProperty: "payload"` + `yAxisPropertyType: "msg"` tells the chart WHERE in the msg to find the y-value. Without these: chart has no data to plot.
|
||||||
|
- `xAxisPropertyType: "timestamp"` tells the chart to use `msg.timestamp` (or auto-generated) for the x-axis.
|
||||||
|
- `width` and `height` are **numbers, not strings**. `width: 12` (correct) vs `width: "12"` (may break).
|
||||||
|
- `removeOlderPoints: ""` (empty string) → retention is controlled by removeOlder + removeOlderUnit only. Set to a number string to additionally cap points per series.
|
||||||
|
- `colors` array defines the palette for auto-assigned series colours. Provide at least 3.
|
||||||
|
|
||||||
### The trend-split function pattern
|
### The trend-split function pattern
|
||||||
|
|
||||||
A common bug: feeding both flow and power msgs to a single function output that wires to both charts. Both charts then plot all metrics, garbling the legend.
|
A common bug: feeding both flow and power msgs to a single function output that wires to both charts. Both charts then plot all metrics, garbling the legend.
|
||||||
|
|||||||
@@ -258,32 +258,65 @@ def ui_switch(node_id, tab, x, y, group, name, label, on_value, off_value,
|
|||||||
|
|
||||||
|
|
||||||
def ui_chart(node_id, tab, x, y, group, name, label,
|
def ui_chart(node_id, tab, x, y, group, name, label,
|
||||||
width="12", height="6",
|
width=12, height=6,
|
||||||
remove_older="10", remove_older_unit="60",
|
remove_older="15", remove_older_unit="60",
|
||||||
remove_older_points="200",
|
remove_older_points="",
|
||||||
ymin=None, ymax=None, order=1):
|
y_axis_label="", ymin=None, ymax=None, order=1):
|
||||||
"""
|
"""
|
||||||
FlowFuse ui-chart. Dimensions are in grid units:
|
FlowFuse ui-chart (line type, time x-axis).
|
||||||
width="12" = full group width
|
|
||||||
height="6" = about 300 px tall
|
IMPORTANT: This template is derived from the working charts in
|
||||||
`remove_older` + `remove_older_unit` define the rolling window
|
rotatingMachine/examples/03-Dashboard.json. Every field listed below
|
||||||
(e.g. "10" + "60" = 10 minutes). `remove_older_points` caps points
|
is required or the chart renders blank. Key gotchas:
|
||||||
per series.
|
|
||||||
|
- `width` / `height` must be NUMBERS not strings.
|
||||||
|
- `interpolation` must be set ("linear", "step", "bezier",
|
||||||
|
"cubic", "cubic-mono") or no line is drawn.
|
||||||
|
- `yAxisProperty: "payload"` + `yAxisPropertyType: "msg"` tells
|
||||||
|
the chart WHERE in the msg to find the y-value. Without these
|
||||||
|
the chart has no data to plot.
|
||||||
|
- `xAxisPropertyType: "timestamp"` tells the chart to use
|
||||||
|
msg.timestamp (or auto-generated timestamp) for the x-axis.
|
||||||
|
- `removeOlderPoints` should be "" (empty string) to let
|
||||||
|
removeOlder + removeOlderUnit control retention, OR a number
|
||||||
|
string to cap points per series.
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
"id": node_id, "type": "ui-chart", "z": tab, "group": group,
|
"id": node_id, "type": "ui-chart", "z": tab, "group": group,
|
||||||
"name": name, "label": label, "order": order, "chartType": "line",
|
"name": name, "label": label, "order": order,
|
||||||
|
"chartType": "line",
|
||||||
|
"interpolation": "linear",
|
||||||
|
# Series identification
|
||||||
"category": "topic", "categoryType": "msg",
|
"category": "topic", "categoryType": "msg",
|
||||||
"xAxisLabel": "", "xAxisType": "time", "xAxisTimeFormat": "auto",
|
# X-axis (time)
|
||||||
"yAxisLabel": "", "ymin": "" if ymin is None else str(ymin),
|
"xAxisLabel": "", "xAxisType": "time",
|
||||||
|
"xAxisProperty": "", "xAxisPropertyType": "timestamp",
|
||||||
|
"xAxisFormat": "", "xAxisFormatType": "auto",
|
||||||
|
"xmin": "", "xmax": "",
|
||||||
|
# Y-axis (msg.payload)
|
||||||
|
"yAxisLabel": y_axis_label,
|
||||||
|
"yAxisProperty": "payload", "yAxisPropertyType": "msg",
|
||||||
|
"ymin": "" if ymin is None else str(ymin),
|
||||||
"ymax": "" if ymax is None else str(ymax),
|
"ymax": "" if ymax is None else str(ymax),
|
||||||
"action": "append", "pointShape": "circle", "pointRadius": 2,
|
# Data retention
|
||||||
"showLegend": True,
|
|
||||||
"removeOlder": str(remove_older),
|
"removeOlder": str(remove_older),
|
||||||
"removeOlderUnit": str(remove_older_unit),
|
"removeOlderUnit": str(remove_older_unit),
|
||||||
"removeOlderPoints": str(remove_older_points),
|
"removeOlderPoints": str(remove_older_points),
|
||||||
"colors": [], "textColor": [], "textColorDefault": True,
|
# Rendering
|
||||||
"width": str(width), "height": str(height), "className": "",
|
"action": "append",
|
||||||
|
"stackSeries": False,
|
||||||
|
"pointShape": "circle", "pointRadius": 4,
|
||||||
|
"showLegend": True,
|
||||||
|
"bins": 10,
|
||||||
|
# Colours (defaults — chart auto-cycles through these per series)
|
||||||
|
"colors": [
|
||||||
|
"#0095FF", "#FF0000", "#FF7F0E", "#2CA02C",
|
||||||
|
"#A347E1", "#D62728", "#FF9896", "#9467BD", "#C5B0D5",
|
||||||
|
],
|
||||||
|
"textColor": ["#666666"], "textColorDefault": True,
|
||||||
|
"gridColor": ["#e5e5e5"], "gridColorDefault": True,
|
||||||
|
# Editor layout + dimensions (NUMBERS, not strings)
|
||||||
|
"width": int(width), "height": int(height), "className": "",
|
||||||
"x": x, "y": y,
|
"x": x, "y": y,
|
||||||
"wires": [[]],
|
"wires": [[]],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3102,26 +3102,52 @@
|
|||||||
"label": "Flow per pump (m\u00b3/h)",
|
"label": "Flow per pump (m\u00b3/h)",
|
||||||
"order": 1,
|
"order": 1,
|
||||||
"chartType": "line",
|
"chartType": "line",
|
||||||
|
"interpolation": "linear",
|
||||||
"category": "topic",
|
"category": "topic",
|
||||||
"categoryType": "msg",
|
"categoryType": "msg",
|
||||||
"xAxisLabel": "",
|
"xAxisLabel": "",
|
||||||
"xAxisType": "time",
|
"xAxisType": "time",
|
||||||
"xAxisTimeFormat": "auto",
|
"xAxisProperty": "",
|
||||||
|
"xAxisPropertyType": "timestamp",
|
||||||
|
"xAxisFormat": "",
|
||||||
|
"xAxisFormatType": "auto",
|
||||||
|
"xmin": "",
|
||||||
|
"xmax": "",
|
||||||
"yAxisLabel": "",
|
"yAxisLabel": "",
|
||||||
|
"yAxisProperty": "payload",
|
||||||
|
"yAxisPropertyType": "msg",
|
||||||
"ymin": "",
|
"ymin": "",
|
||||||
"ymax": "",
|
"ymax": "",
|
||||||
"action": "append",
|
|
||||||
"pointShape": "circle",
|
|
||||||
"pointRadius": 2,
|
|
||||||
"showLegend": true,
|
|
||||||
"removeOlder": "10",
|
"removeOlder": "10",
|
||||||
"removeOlderUnit": "60",
|
"removeOlderUnit": "60",
|
||||||
"removeOlderPoints": "300",
|
"removeOlderPoints": "300",
|
||||||
"colors": [],
|
"action": "append",
|
||||||
"textColor": [],
|
"stackSeries": false,
|
||||||
|
"pointShape": "circle",
|
||||||
|
"pointRadius": 4,
|
||||||
|
"showLegend": true,
|
||||||
|
"bins": 10,
|
||||||
|
"colors": [
|
||||||
|
"#0095FF",
|
||||||
|
"#FF0000",
|
||||||
|
"#FF7F0E",
|
||||||
|
"#2CA02C",
|
||||||
|
"#A347E1",
|
||||||
|
"#D62728",
|
||||||
|
"#FF9896",
|
||||||
|
"#9467BD",
|
||||||
|
"#C5B0D5"
|
||||||
|
],
|
||||||
|
"textColor": [
|
||||||
|
"#666666"
|
||||||
|
],
|
||||||
"textColorDefault": true,
|
"textColorDefault": true,
|
||||||
"width": "12",
|
"gridColor": [
|
||||||
"height": "8",
|
"#e5e5e5"
|
||||||
|
],
|
||||||
|
"gridColorDefault": true,
|
||||||
|
"width": 12,
|
||||||
|
"height": 8,
|
||||||
"className": "",
|
"className": "",
|
||||||
"x": 900,
|
"x": 900,
|
||||||
"y": 2320,
|
"y": 2320,
|
||||||
@@ -3138,26 +3164,52 @@
|
|||||||
"label": "Power per pump (kW)",
|
"label": "Power per pump (kW)",
|
||||||
"order": 1,
|
"order": 1,
|
||||||
"chartType": "line",
|
"chartType": "line",
|
||||||
|
"interpolation": "linear",
|
||||||
"category": "topic",
|
"category": "topic",
|
||||||
"categoryType": "msg",
|
"categoryType": "msg",
|
||||||
"xAxisLabel": "",
|
"xAxisLabel": "",
|
||||||
"xAxisType": "time",
|
"xAxisType": "time",
|
||||||
"xAxisTimeFormat": "auto",
|
"xAxisProperty": "",
|
||||||
|
"xAxisPropertyType": "timestamp",
|
||||||
|
"xAxisFormat": "",
|
||||||
|
"xAxisFormatType": "auto",
|
||||||
|
"xmin": "",
|
||||||
|
"xmax": "",
|
||||||
"yAxisLabel": "",
|
"yAxisLabel": "",
|
||||||
|
"yAxisProperty": "payload",
|
||||||
|
"yAxisPropertyType": "msg",
|
||||||
"ymin": "",
|
"ymin": "",
|
||||||
"ymax": "",
|
"ymax": "",
|
||||||
"action": "append",
|
|
||||||
"pointShape": "circle",
|
|
||||||
"pointRadius": 2,
|
|
||||||
"showLegend": true,
|
|
||||||
"removeOlder": "10",
|
"removeOlder": "10",
|
||||||
"removeOlderUnit": "60",
|
"removeOlderUnit": "60",
|
||||||
"removeOlderPoints": "300",
|
"removeOlderPoints": "300",
|
||||||
"colors": [],
|
"action": "append",
|
||||||
"textColor": [],
|
"stackSeries": false,
|
||||||
|
"pointShape": "circle",
|
||||||
|
"pointRadius": 4,
|
||||||
|
"showLegend": true,
|
||||||
|
"bins": 10,
|
||||||
|
"colors": [
|
||||||
|
"#0095FF",
|
||||||
|
"#FF0000",
|
||||||
|
"#FF7F0E",
|
||||||
|
"#2CA02C",
|
||||||
|
"#A347E1",
|
||||||
|
"#D62728",
|
||||||
|
"#FF9896",
|
||||||
|
"#9467BD",
|
||||||
|
"#C5B0D5"
|
||||||
|
],
|
||||||
|
"textColor": [
|
||||||
|
"#666666"
|
||||||
|
],
|
||||||
"textColorDefault": true,
|
"textColorDefault": true,
|
||||||
"width": "12",
|
"gridColor": [
|
||||||
"height": "8",
|
"#e5e5e5"
|
||||||
|
],
|
||||||
|
"gridColorDefault": true,
|
||||||
|
"width": 12,
|
||||||
|
"height": 8,
|
||||||
"className": "",
|
"className": "",
|
||||||
"x": 900,
|
"x": 900,
|
||||||
"y": 2400,
|
"y": 2400,
|
||||||
@@ -3174,26 +3226,52 @@
|
|||||||
"label": "Flow per pump (m\u00b3/h)",
|
"label": "Flow per pump (m\u00b3/h)",
|
||||||
"order": 1,
|
"order": 1,
|
||||||
"chartType": "line",
|
"chartType": "line",
|
||||||
|
"interpolation": "linear",
|
||||||
"category": "topic",
|
"category": "topic",
|
||||||
"categoryType": "msg",
|
"categoryType": "msg",
|
||||||
"xAxisLabel": "",
|
"xAxisLabel": "",
|
||||||
"xAxisType": "time",
|
"xAxisType": "time",
|
||||||
"xAxisTimeFormat": "auto",
|
"xAxisProperty": "",
|
||||||
|
"xAxisPropertyType": "timestamp",
|
||||||
|
"xAxisFormat": "",
|
||||||
|
"xAxisFormatType": "auto",
|
||||||
|
"xmin": "",
|
||||||
|
"xmax": "",
|
||||||
"yAxisLabel": "",
|
"yAxisLabel": "",
|
||||||
|
"yAxisProperty": "payload",
|
||||||
|
"yAxisPropertyType": "msg",
|
||||||
"ymin": "",
|
"ymin": "",
|
||||||
"ymax": "",
|
"ymax": "",
|
||||||
"action": "append",
|
|
||||||
"pointShape": "circle",
|
|
||||||
"pointRadius": 2,
|
|
||||||
"showLegend": true,
|
|
||||||
"removeOlder": "60",
|
"removeOlder": "60",
|
||||||
"removeOlderUnit": "60",
|
"removeOlderUnit": "60",
|
||||||
"removeOlderPoints": "1800",
|
"removeOlderPoints": "1800",
|
||||||
"colors": [],
|
"action": "append",
|
||||||
"textColor": [],
|
"stackSeries": false,
|
||||||
|
"pointShape": "circle",
|
||||||
|
"pointRadius": 4,
|
||||||
|
"showLegend": true,
|
||||||
|
"bins": 10,
|
||||||
|
"colors": [
|
||||||
|
"#0095FF",
|
||||||
|
"#FF0000",
|
||||||
|
"#FF7F0E",
|
||||||
|
"#2CA02C",
|
||||||
|
"#A347E1",
|
||||||
|
"#D62728",
|
||||||
|
"#FF9896",
|
||||||
|
"#9467BD",
|
||||||
|
"#C5B0D5"
|
||||||
|
],
|
||||||
|
"textColor": [
|
||||||
|
"#666666"
|
||||||
|
],
|
||||||
"textColorDefault": true,
|
"textColorDefault": true,
|
||||||
"width": "12",
|
"gridColor": [
|
||||||
"height": "8",
|
"#e5e5e5"
|
||||||
|
],
|
||||||
|
"gridColorDefault": true,
|
||||||
|
"width": 12,
|
||||||
|
"height": 8,
|
||||||
"className": "",
|
"className": "",
|
||||||
"x": 900,
|
"x": 900,
|
||||||
"y": 2480,
|
"y": 2480,
|
||||||
@@ -3210,26 +3288,52 @@
|
|||||||
"label": "Power per pump (kW)",
|
"label": "Power per pump (kW)",
|
||||||
"order": 1,
|
"order": 1,
|
||||||
"chartType": "line",
|
"chartType": "line",
|
||||||
|
"interpolation": "linear",
|
||||||
"category": "topic",
|
"category": "topic",
|
||||||
"categoryType": "msg",
|
"categoryType": "msg",
|
||||||
"xAxisLabel": "",
|
"xAxisLabel": "",
|
||||||
"xAxisType": "time",
|
"xAxisType": "time",
|
||||||
"xAxisTimeFormat": "auto",
|
"xAxisProperty": "",
|
||||||
|
"xAxisPropertyType": "timestamp",
|
||||||
|
"xAxisFormat": "",
|
||||||
|
"xAxisFormatType": "auto",
|
||||||
|
"xmin": "",
|
||||||
|
"xmax": "",
|
||||||
"yAxisLabel": "",
|
"yAxisLabel": "",
|
||||||
|
"yAxisProperty": "payload",
|
||||||
|
"yAxisPropertyType": "msg",
|
||||||
"ymin": "",
|
"ymin": "",
|
||||||
"ymax": "",
|
"ymax": "",
|
||||||
"action": "append",
|
|
||||||
"pointShape": "circle",
|
|
||||||
"pointRadius": 2,
|
|
||||||
"showLegend": true,
|
|
||||||
"removeOlder": "60",
|
"removeOlder": "60",
|
||||||
"removeOlderUnit": "60",
|
"removeOlderUnit": "60",
|
||||||
"removeOlderPoints": "1800",
|
"removeOlderPoints": "1800",
|
||||||
"colors": [],
|
"action": "append",
|
||||||
"textColor": [],
|
"stackSeries": false,
|
||||||
|
"pointShape": "circle",
|
||||||
|
"pointRadius": 4,
|
||||||
|
"showLegend": true,
|
||||||
|
"bins": 10,
|
||||||
|
"colors": [
|
||||||
|
"#0095FF",
|
||||||
|
"#FF0000",
|
||||||
|
"#FF7F0E",
|
||||||
|
"#2CA02C",
|
||||||
|
"#A347E1",
|
||||||
|
"#D62728",
|
||||||
|
"#FF9896",
|
||||||
|
"#9467BD",
|
||||||
|
"#C5B0D5"
|
||||||
|
],
|
||||||
|
"textColor": [
|
||||||
|
"#666666"
|
||||||
|
],
|
||||||
"textColorDefault": true,
|
"textColorDefault": true,
|
||||||
"width": "12",
|
"gridColor": [
|
||||||
"height": "8",
|
"#e5e5e5"
|
||||||
|
],
|
||||||
|
"gridColorDefault": true,
|
||||||
|
"width": 12,
|
||||||
|
"height": 8,
|
||||||
"className": "",
|
"className": "",
|
||||||
"x": 900,
|
"x": 900,
|
||||||
"y": 2560,
|
"y": 2560,
|
||||||
|
|||||||
Reference in New Issue
Block a user