This flow provides a status display for a device (a fan) using Node-RED Dashboard. It uses Material Icons and color coding to visualize different states.
How it shoud work:
Inject Nodes
Four inject nodes simulate different status messages: "on"
, "off"
, "warn"
, and "error"
. Each inject node sends its payload to the function node for testing.
Function Node ("Status interpretieren")
This node interprets the status string and maps it to:
- An icon (from Google Material Icons)
- A color (green, gray, orange, or red)
- A descriptive text (e.g., "Eingeschaltet" = "On", "Ausgeschaltet" = "Off", etc.)
Mapping:
"on"
→ green power icon, "Eingeschaltet""off"
→ gray power_off icon, "Ausgeschaltet""warn"
→ orange warning icon, "Warnung""error"
→ red error icon, "Fehler"
UI Template Node ("Statusanzeige"):
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<div style="text-align: center;">
<span class="material-icons" style="font-size: 64px; color: {{msg.payload.color}};">
{{msg.payload.icon}}
</span>
<div style="font-size: 18px; margin-top: 8px;">
{{msg.payload.text}}
</div>
</div>
This node displays the icon and text in the dashboard, centered and styled according to the payload from the function node.
Debug Node:
For troubleshooting, the output is also sent to a debug node.
The icon and the text change, but the color does not.
I have tried it on two different Node-RED instances and displayed it on different pages, browsers, iPhone, and computer, so it seems that changing the color does not work in my setup.
Can anyone give me a tip where the problem might be?
In Dashboard 1, everything was so easy
[
{
"id": "4f939a4c6949aad0",
"type": "debug",
"z": "96021c4f811b5928",
"name": "debug 65",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1180,
"y": 920,
"wires": []
},
{
"id": "c90a1a41d6bd105d",
"type": "ui-template",
"z": "96021c4f811b5928",
"group": "e48a101406376c80",
"page": "",
"ui": "",
"name": "Statusanzeige",
"order": 2,
"width": 3,
"height": 2,
"format": "<link href=\"https://fonts.googleapis.com/icon?family=Material+Icons\" rel=\"stylesheet\">\n\n<div style=\"text-align: center;\">\n <span class=\"material-icons\" style=\"font-size: 64px; color: {{msg.payload.color}};\">\n {{msg.payload.icon}}\n </span>\n <div style=\"font-size: 18px; margin-top: 8px;\">\n {{msg.payload.text}}\n </div>\n</div>",
"storeOutMessages": false,
"passthru": false,
"resendOnRefresh": true,
"templateScope": "local",
"className": "",
"x": 1240,
"y": 860,
"wires": [
[]
]
},
{
"id": "4778c6fa41a35d40",
"type": "function",
"z": "96021c4f811b5928",
"name": "Status interpretieren",
"func": "let status = msg.payload;\n\nlet result = {\n icon: \"help\",\n color: \"gray\",\n text: \"Unbekannt\"\n};\n\nif (status === \"on\") {\n result.icon = \"power\";\n result.color = \"green\";\n result.text = \"Eingeschaltet\";\n} else if (status === \"off\") {\n result.icon = \"power_off\";\n result.color = \"gray\";\n result.text = \"Ausgeschaltet\";\n} else if (status === \"warn\") {\n result.icon = \"warning\";\n result.color = \"orange\";\n result.text = \"Warnung\";\n} else if (status === \"error\") {\n result.icon = \"error\";\n result.color = \"red\";\n result.text = \"Fehler\";\n}\n\nmsg.payload = result;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 940,
"y": 860,
"wires": [
[
"c90a1a41d6bd105d",
"4f939a4c6949aad0"
]
]
},
{
"id": "539b16f9db1fbfcb",
"type": "inject",
"z": "96021c4f811b5928",
"name": "ON",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "on",
"payloadType": "str",
"x": 640,
"y": 800,
"wires": [
[
"4778c6fa41a35d40"
]
]
},
{
"id": "f60964ceb0086413",
"type": "inject",
"z": "96021c4f811b5928",
"name": "OFF",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "off",
"payloadType": "str",
"x": 640,
"y": 840,
"wires": [
[
"4778c6fa41a35d40"
]
]
},
{
"id": "d1def772a3467d5e",
"type": "inject",
"z": "96021c4f811b5928",
"name": "WARN",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "warn",
"payloadType": "str",
"x": 640,
"y": 880,
"wires": [
[
"4778c6fa41a35d40"
]
]
},
{
"id": "5b10ba8ca031a2d8",
"type": "inject",
"z": "96021c4f811b5928",
"name": "ERROR",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "error",
"payloadType": "str",
"x": 640,
"y": 920,
"wires": [
[
"4778c6fa41a35d40"
]
]
},
{
"id": "e48a101406376c80",
"type": "ui-group",
"name": "LĂĽfter Keller1",
"page": "4bf14cd0fe0d343e",
"width": "3",
"height": "1",
"order": 1,
"showTitle": true,
"className": "",
"visible": "true",
"disabled": "false",
"groupType": "default"
},
{
"id": "4bf14cd0fe0d343e",
"type": "ui-page",
"name": "Page 2",
"ui": "f96401822df0a597",
"path": "/page2",
"icon": "thermometer",
"layout": "grid",
"theme": "e69c750bbe40bb7a",
"breakpoints": [
{
"name": "Default",
"px": "0",
"cols": "3"
},
{
"name": "Tablet",
"px": "576",
"cols": "6"
},
{
"name": "Small Desktop",
"px": "768",
"cols": "9"
},
{
"name": "Desktop",
"px": "1024",
"cols": "12"
}
],
"order": 4,
"className": "",
"visible": "true",
"disabled": "false"
},
{
"id": "f96401822df0a597",
"type": "ui-base",
"name": "My Dashboard",
"path": "/dashboard",
"appIcon": "",
"includeClientData": true,
"acceptsClientConfig": [
"ui-notification",
"ui-control"
],
"showPathInSidebar": false,
"showPageTitle": true,
"navigationStyle": "default",
"titleBarStyle": "default"
},
{
"id": "e69c750bbe40bb7a",
"type": "ui-theme",
"name": "Default Theme",
"colors": {
"surface": "#ffffff",
"primary": "#0094ce",
"bgPage": "#eeeeee",
"groupBg": "#eeeeee",
"groupOutline": "#cccccc"
},
"sizes": {
"density": "default",
"pagePadding": "12px",
"groupGap": "12px",
"groupBorderRadius": "4px",
"widgetGap": "12px"
}
}
]