{"id":17309,"library":"node-red-contrib-ui-state-trail","title":"Node-RED Dashboard State Trail Chart","description":"node-red-contrib-ui-state-trail is a Node-RED dashboard UI node that renders a Gantt-type chart to visualize the historical changes of a state over a configurable time period. It is designed for displaying single-line state timelines, such as the operational status (on/off, running/stopped) of a device or process. The current stable version is 1.0.2. As a Node-RED contrib node, it typically receives updates on an as-needed basis rather than a strict release cadence, focusing on stability and new features. Key differentiators include its ability to accept both simple and timestamped historical data, customizable legend display (showing all states, current states, or latest state), state aggregation for performance, and optional persistent data storage when Node-RED's context storage is properly configured. It supports string, number, and boolean state types, which are treated distinctly.","status":"active","version":"1.0.2","language":"javascript","source_language":"en","source_url":"https://github.com/hotNipi/node-red-contrib-ui-state-trail","tags":["javascript","node-red","state-trail","state chart","dashboard"],"install":[{"cmd":"npm install node-red-contrib-ui-state-trail","lang":"bash","label":"npm"},{"cmd":"yarn add node-red-contrib-ui-state-trail","lang":"bash","label":"yarn"},{"cmd":"pnpm add node-red-contrib-ui-state-trail","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for the Node-RED runtime environment.","package":"node-red","optional":false},{"reason":"Provides the dashboard framework for the UI widget.","package":"node-red-dashboard","optional":false}],"imports":[{"note":"For current state updates, send the raw state value directly in `msg.payload`. The type (boolean, string, number) must match configured states.","wrong":"msg.payload = { value: true };","symbol":"msg.payload (simple state)","correct":"msg.payload = true; // or 'running', 1"},{"note":"To input historical data, `msg.payload` must be an object with `state` and `timestamp` (milliseconds since epoch). An array of such objects is also supported.","wrong":"msg.payload = { value: 'on', time: Date.now() };","symbol":"msg.payload (historical state)","correct":"msg.payload = { state: 'on', timestamp: Date.now() };"},{"note":"The chart's display period can be dynamically overridden by sending `msg.control` with a `period` property in milliseconds.","wrong":"msg.control = { period_ms: 300000 };","symbol":"msg.control (period override)","correct":"msg.control = { period: 300000 }; // 5 minutes"}],"quickstart":{"code":"[\n    {\n        \"id\": \"inject_current_state\",\n        \"type\": \"inject\",\n        \"name\": \"Send 'running'\",\n        \"topic\": \"\",\n        \"payload\": \"running\",\n        \"payloadType\": \"str\",\n        \"repeat\": \"5\",\n        \"crontab\": \"\",\n        \"once\": false,\n        \"onceDelay\": 0.1,\n        \"x\": 160,\n        \"y\": 100,\n        \"wires\": [\n            [\"state_trail_node\"]\n        ]\n    },\n    {\n        \"id\": \"inject_historical_data\",\n        \"type\": \"inject\",\n        \"name\": \"Send Historical Data\",\n        \"topic\": \"\",\n        \"payload\": \"[\n    {state: \\\"stopped\\\", timestamp: Date.now() - 3600000},\n    {state: \\\"running\\\", timestamp: Date.now() - 1800000},\n    {state: \\\"error\\\", timestamp: Date.now() - 600000}\n]\",\n        \"payloadType\": \"json_ata\",\n        \"repeat\": \"\",\n        \"crontab\": \"\",\n        \"once\": true,\n        \"onceDelay\": 1,\n        \"x\": 190,\n        \"y\": 160,\n        \"wires\": [\n            [\"state_trail_node\"]\n        ]\n    },\n    {\n        \"id\": \"inject_control_period\",\n        \"type\": \"inject\",\n        \"name\": \"Set Period to 10 min\",\n        \"topic\": \"\",\n        \"payload\": \"{\\\"period\\\":600000}\",\n        \"payloadType\": \"json\",\n        \"repeat\": \"\",\n        \"crontab\": \"\",\n        \"once\": true,\n        \"onceDelay\": 2,\n        \"x\": 190,\n        \"y\": 220,\n        \"wires\": [\n            [\"state_trail_node\"]\n        ]\n    },\n    {\n        \"id\": \"state_trail_node\",\n        \"type\": \"ui_state_trail\",\n        \"z\": \"flow_id\", // Replace with your flow ID\n        \"group\": \"dashboard_group\", // Replace with your dashboard group ID\n        \"name\": \"My State Trail\",\n        \"label\": \"Process State\",\n        \"order\": 0,\n        \"width\": 0,\n        \"height\": 2,\n        \"period\": 3600000, // Default to 1 hour\n        \"period_unit\": \"hour\",\n        \"combine\": true,\n        \"states\": [\n            { \"state\": \"running\", \"label\": \"Running\" },\n            { \"state\": \"stopped\", \"label\": \"Stopped\" },\n            { \"state\": \"error\", \"label\": \"Error\" },\n            { \"state\": true, \"label\": \"Active\" },\n            { \"state\": false, \"label\": \"Inactive\" }\n        ],\n        \"legend\": 0,\n        \"ticks\": 6,\n        \"x\": 450,\n        \"y\": 100,\n        \"wires\": []\n    }\n]","lang":"javascript","description":"This Node-RED flow demonstrates sending a simple current state, an array of historical states, and a control message to dynamically change the chart's display period for the 'State Trail' UI node. Replace `flow_id` and `dashboard_group` with actual IDs from your Node-RED instance."},"warnings":[{"fix":"Keep the input rate low for long periods, or configure shorter display periods. Ensure the 'Combine similar states' option is enabled in the node's configuration if individual state instances are not critical for analysis.","message":"Performance can significantly degrade with long periods and high input rates, especially on lower-end hardware, due to the volume of data needing to be rendered. Use the 'combine similar states' option to mitigate this.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"To retain data, enable 'Data Storage' in the node properties and follow Node-RED documentation to configure a persistent context store (e.g., file-based) in `settings.js`.","message":"Chart data will be lost on Node-RED redeploy, restart, or system reboot unless persistent context storage is explicitly configured in Node-RED's `settings.js` file AND the 'Data Storage' option is enabled in the node's configuration.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure consistency in state types. If you intend `true` and `\"true\"` to represent the same state, standardize on one type or configure both with identical labels.","message":"Boolean states (`true`, `false`) and string states (`\"true\"`, `\"false\"`) are treated as distinct values. Mixing types for what appears to be the 'same' state will result in separate entries on the chart and in the legend.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Increase the widget height to at least 2 units in the Node-RED Dashboard UI tab to display the label and legend correctly.","message":"The legend and labels configured for the widget will not be visible on the dashboard if the widget's height is set to less than 2 units in the Node-RED Dashboard layout.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If continuous appending of historical data is needed, send individual historical state messages one by one rather than large arrays, or manage the data set externally before sending the complete array.","message":"When feeding an array of historical data (`msg.payload = [...]`), the previous set of data in the chart is cleared and replaced by the new array. This is intentional for batch updates but can be unexpected if continuous appending is desired.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Go to Node-RED `settings.js`, configure a persistent context storage (e.g., `localfilesystem`), and ensure the 'Data Storage' checkbox is selected in the State Trail node's properties.","cause":"Persistent context storage is not enabled or configured incorrectly.","error":"Chart data disappears after Node-RED restart or full redeploy."},{"fix":"Reduce the `Period` setting in the node's configuration, lower the frequency of input messages, or ensure the 'Combine similar states' option is checked to reduce data points.","cause":"Too much data is being fed to the node over a long configured period, overwhelming rendering capabilities.","error":"Chart performance is slow, or the dashboard becomes unresponsive when viewing the State Trail."},{"fix":"Edit the Node-RED Dashboard layout, find the State Trail node, and increase its 'Height' property to at least 2 units.","cause":"The UI widget's height is set too low in the dashboard layout.","error":"The chart legend or node label is not displayed on the Node-RED dashboard."},{"fix":"Standardize the data type for your states (e.g., always send `true` boolean or always send `\"true\"` string) or configure both `true` and `\"true\"` as distinct states with appropriate labels in the node's configuration.","cause":"The node differentiates between data types (boolean, string, number).","error":"States like 'true' and \"true\" are shown as different entries on the chart or in the legend."}],"ecosystem":"npm","meta_description":null}