Thank you all (esp @Colin.Smith1205 - Also, nice to see you're still involved @dceejay, post retirement )
This now all works perfectly: instance value gauge shows a variable colour coded threshold segment and historic-value graph has a line series showing the threshold value and history (last 4 hrs)
[
{
"id": "4b79199fafd41be7",
"type": "mqtt in",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "Humidity",
"topic": "bathroom/humidity",
"qos": "0",
"datatype": "json",
"broker": "3f447ded17b259ee",
"nl": false,
"rap": false,
"rh": 0,
"inputs": 0,
"x": 300,
"y": 400,
"wires": [
[
"0a351ffd80a868c9",
"e2cb3b16443d36da",
"81209091e69e650e",
"75b5ad00fd309030"
]
]
},
{
"id": "be3e70d8bd7590ee",
"type": "inject",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "High humidity (95%)",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "bathroom/humidity",
"payload": "100",
"payloadType": "num",
"x": 250,
"y": 460,
"wires": [
[
"0a351ffd80a868c9",
"e2cb3b16443d36da",
"81209091e69e650e",
"75b5ad00fd309030"
]
]
},
{
"id": "af02c8f8d2b3e3b7",
"type": "inject",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "Low humidity (50%)",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "bathroom/humidity",
"payload": "50",
"payloadType": "num",
"x": 250,
"y": 500,
"wires": [
[
"0a351ffd80a868c9",
"e2cb3b16443d36da",
"81209091e69e650e",
"75b5ad00fd309030"
]
]
},
{
"id": "0a351ffd80a868c9",
"type": "function",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "RecordHumidity",
"func": "flow.set('lastHumidity', msg.payload);\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 920,
"y": 480,
"wires": [
[]
]
},
{
"id": "a59102097a2337a3",
"type": "comment",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "Old function code",
"info": "//}\n\n\n\n//Gather persistent variables\nvar requiredFanState = flow.get('requiredFanState') || \"humidityTrigger\";\nvar startTimer = flow.get('startTimer') || 0;\nvar fanTimerInterval = 600000000; //milliseconds (1 minute = 60000ms)\nvar fanSwitch = {payload: \"\"};\nvar fanStateNR = {payload: \"\"};\nvar DashSync = {payload: \"\"};\n\n//If the timer has expired, reset the timer, \n//send a message to turn the fan off and change the persistent \n//flow variable to reflect the resumed default mode\n\nif (requiredFanState == 'fanOn10') { //show timer progress for debug\n var progress = (Date.now()-startTimer);\n fanSwitch.payload = 'ON';\n if ((progress >= fanTimerInterval) && (startTimer > 0)) { //timer interval spent\n //node.warn('Resetting timer! and changing mode to: humidityTrigger');\n startTimer = 0; //local\n flow.set('startTimer',0); //flow\n \n //fanSwitch.payload = 'OFF'; //This will get set by the humidity threshold check function\n \n requiredFanState = \"humidityTrigger\"; //local\n flow.set('requiredFanState',\"humidityTrigger\"); //flow\n \n fanStateNR.payload = \"humidityTrigger\"; //ready to tell the ESP+Sensor\n DashSync.payload = \"humidityTrigger\"; //ready to tell the dashboard dropdown\n \n \n flow.set('fanTimerInterval',fanTimerInterval);\n \n } else if ((progress < fanTimerInterval) && (startTimer > 0)) {\n //node.warn('timer progress:'+ progress + 'to:'+ fanTimerInterval); // progress up to the point the timer is spent\n fanSwitch.payload = 'ON';\n }\n \n flow.set('requiredFanState',requiredFanState); //set the flow params on exit, even if there's no change\n flow.set('fanTimerInterval',fanTimerInterval);\n\n return [ DashSync, fanSwitch, fanStateNR ];\n} \n\n",
"x": 920,
"y": 520,
"wires": []
},
{
"id": "e2cb3b16443d36da",
"type": "debug",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "Humidity",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 890,
"y": 360,
"wires": []
},
{
"id": "81209091e69e650e",
"type": "ui-chart",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"group": "fc3876ca5fad0f6a",
"name": "Humidity",
"label": "chart",
"order": 2,
"chartType": "line",
"category": "topic",
"categoryType": "msg",
"xAxisLabel": "Time",
"xAxisProperty": "",
"xAxisPropertyType": "timestamp",
"xAxisType": "time",
"xAxisFormat": "",
"xAxisFormatType": "auto",
"xmin": "",
"xmax": "",
"yAxisLabel": "Humidity %",
"yAxisProperty": "payload",
"yAxisPropertyType": "msg",
"ymin": "20",
"ymax": "100",
"bins": 10,
"action": "append",
"stackSeries": false,
"pointShape": "false",
"pointRadius": 4,
"showLegend": true,
"removeOlder": "4",
"removeOlderUnit": "3600",
"removeOlderPoints": "",
"colors": [
"#0095ff",
"#e01b24",
"#ff7f0e",
"#2ca02c",
"#a347e1",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"textColor": [
"#666666"
],
"textColorDefault": true,
"gridColor": [
"#e5e5e5"
],
"gridColorDefault": true,
"width": 6,
"height": 8,
"className": "",
"interpolation": "linear",
"x": 890,
"y": 440,
"wires": [
[]
]
},
{
"id": "75b5ad00fd309030",
"type": "ui-gauge",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "Humidity",
"group": "fc3876ca5fad0f6a",
"order": 1,
"value": "payload",
"valueType": "msg",
"width": 3,
"height": 3,
"gtype": "gauge-half",
"gstyle": "needle",
"title": "Humidity",
"alwaysShowTitle": false,
"floatingTitlePosition": "top-left",
"units": "%",
"icon": "",
"prefix": "",
"suffix": "",
"segments": [
{
"from": "20",
"color": "#99c1f1",
"text": "",
"textType": "label"
},
{
"from": "85",
"color": "#ea5353",
"text": "",
"textType": "label"
}
],
"min": "20",
"max": "100",
"sizeThickness": 16,
"sizeGap": 4,
"sizeKeyThickness": 8,
"styleRounded": true,
"styleGlow": false,
"className": "",
"x": 890,
"y": 400,
"wires": [
[]
]
},
{
"id": "7c642c5673f59101",
"type": "inject",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "OnStart",
"props": [
{
"p": "topic",
"vt": "str"
}
],
"repeat": "30",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"x": 310,
"y": 340,
"wires": [
[
"86f4f6c57298e008"
]
]
},
{
"id": "86f4f6c57298e008",
"type": "function",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "TraceThresholdVal",
"func": "let humidityThresholdVal = global.get('humidityThreshold');\n\nmsg.ui_update = { segments: [{ color: \"green\", from: 0 }, { color: \"red\", from: humidityThresholdVal }] }\n\n//return [msg]\n\nlet msg2 = {} //initialise a new message\nmsg2.payload = humidityThresholdVal //message passes the value for the graph\nmsg2.topic = 'bathroom/humidityThreshold' //message passes the topic for a different series\nreturn [msg, msg2]",
"outputs": 2,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 500,
"y": 340,
"wires": [
[
"80169acbf2886566",
"75b5ad00fd309030"
],
[
"81209091e69e650e",
"704f9f4ddd08f932"
]
]
},
{
"id": "80169acbf2886566",
"type": "debug",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "ChangeSegmentJSON",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1280,
"y": 300,
"wires": []
},
{
"id": "704f9f4ddd08f932",
"type": "debug",
"z": "a0ebd549a544bb25",
"g": "84074881becbb9f2",
"name": "HumidityThresholdValue",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1290,
"y": 340,
"wires": []
},
{
"id": "3f447ded17b259ee",
"type": "mqtt-broker",
"name": "Mosquitto",
"broker": "192.168.7.245",
"port": "1883",
"clientid": "",
"usetls": false,
"protocolVersion": "5",
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willPayload": "",
"willMsg": {},
"sessionExpiry": ""
},
{
"id": "fc3876ca5fad0f6a",
"type": "ui-group",
"name": "Humidity",
"page": "cda4aeea5584ffaa",
"width": 6,
"height": 1,
"order": 1,
"showTitle": true,
"className": "",
"visible": "true",
"disabled": "false",
"groupType": "default"
},
{
"id": "cda4aeea5584ffaa",
"type": "ui-page",
"name": "Bathroom",
"ui": "5158dba2ce9db01c",
"path": "/page1",
"icon": "home",
"layout": "grid",
"theme": "f149993e218cdb7d",
"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": 2,
"className": "",
"visible": "true",
"disabled": "false"
},
{
"id": "5158dba2ce9db01c",
"type": "ui-base",
"name": "Archery",
"path": "/dashboard",
"appIcon": "",
"includeClientData": true,
"acceptsClientConfig": [
"ui-notification",
"ui-control"
],
"showPathInSidebar": false,
"headerContent": "page",
"navigationStyle": "default",
"titleBarStyle": "default",
"showReconnectNotification": true,
"notificationDisplayTime": 1,
"showDisconnectNotification": true,
"allowInstall": true
},
{
"id": "f149993e218cdb7d",
"type": "ui-theme",
"name": "Default Theme",
"colors": {
"surface": "#ffffff",
"primary": "#0094CE",
"bgPage": "#eeeeee",
"groupBg": "#ffffff",
"groupOutline": "#cccccc"
},
"sizes": {
"density": "default",
"pagePadding": "12px",
"groupGap": "12px",
"groupBorderRadius": "4px",
"widgetGap": "12px"
}
},
{
"id": "b383a3225650aa4f",
"type": "global-config",
"env": [],
"modules": {
"@flowfuse/node-red-dashboard": "1.27.1"
}
}
]