Trying to troubleshoot a problem and I can't find anything that tells me where in a Pi system that the file is that stores the data when you do a flow.set command. Someone please help.
Thanks
flow.set.data
is another term for context
.
Depending on the settings - don't ask me - they are either stored in memory or in a file.
Memory means it is volatile to reboots and won't survive.
File means it can survive reboots but is more I/O intensive.
I've set settings.js to
ContextStorage: {
default: {
module:"localfilesystem"
},
},
but I'm looking for where the file is stored
The default is a bunch of cryptically named json files below ~/.node-red/context.
eg
pi@ZeroTwoPink:~/.node-red $ find context -ls
267160 4 drwxr-xr-x 10 pi pi 4096 Aug 13 22:18 context
272060 4 drwxr-xr-x 2 pi pi 4096 Aug 23 23:27 context/aa0a868df2ab245a
263452 4 -rw-r--r-- 1 pi pi 19 Aug 23 23:27 context/aa0a868df2ab245a/77eca9bb2b4b07a5.json
263450 4 -rw-r--r-- 1 pi pi 19 Aug 23 23:27 context/aa0a868df2ab245a/8469a1aec341cbbe.json
271927 4 drwxr-xr-x 2 pi pi 4096 Aug 23 23:27 context/3fd2634d3eb8f47a
263457 4 -rw-r--r-- 1 pi pi 22 Aug 23 23:27 context/3fd2634d3eb8f47a/flow.json
272058 4 drwxr-xr-x 2 pi pi 4096 Aug 23 23:23 context/52d3a9a7a5712824
263447 4 -rw-r--r-- 1 pi pi 189 Aug 23 23:23 context/52d3a9a7a5712824/flow.json
399809 4 drwxr-xr-x 2 pi pi 4096 Aug 23 23:23 context/global
399811 4 -rw-r--r-- 1 pi pi 1094 Aug 23 23:23 context/global/global.json
272236 4 drwxr-xr-x 2 pi pi 4096 Jul 3 13:47 context/f19ed86818b2c31d
272057 4 drwxr-xr-x 2 pi pi 4096 Aug 23 23:23 context/699e0a72d49c76f3
263454 4 -rw-r--r-- 1 pi pi 80 Aug 23 23:23 context/699e0a72d49c76f3/02b7e893a6230852.json
263455 4 -rw-r--r-- 1 pi pi 80 Aug 23 23:23 context/699e0a72d49c76f3/70ef4ccdaa6ac4b7.json
263451 4 -rw-r--r-- 1 pi pi 86 Aug 23 23:23 context/699e0a72d49c76f3/432c6119c3e95d36.json
268777 4 -rw-r--r-- 1 pi pi 22 Aug 13 22:01 context/699e0a72d49c76f3/fc552e50154e6e8b.json
263453 4 -rw-r--r-- 1 pi pi 86 Aug 23 23:23 context/699e0a72d49c76f3/9c1a7a927b8af746.json
263449 4 -rw-r--r-- 1 pi pi 639 Aug 23 23:23 context/699e0a72d49c76f3/flow.json
272059 4 drwxr-xr-x 2 pi pi 4096 Aug 23 23:23 context/43b59e5a75cfcb1b
263448 4 -rw-r--r-- 1 pi pi 3748 Aug 23 23:23 context/43b59e5a75cfcb1b/flow.json
269156 4 drwxr-xr-x 2 pi pi 4096 Jun 9 17:27 context/a36444dbe01769cb
272089 24 -rw-r--r-- 1 pi pi 20800 Jun 9 17:25 context/a36444dbe01769cb/flow.json
That's what I thought but I'd thought I'd ask. If my system doesn't have the /context sub-dir I assume that's why my flow.set is not working correctly.
It creates the directory automatically, after a delay (30s)?
So if you don't have that directory there's something wrong.
What NR version do you have?
Pi4 running nodejs 18, node red 3.0..2, I have just reinstalled node red and down graded from nodejs 20 to 18 and it still doesn't work.
[edit]
no error messages and any install
If I make ~/.node-red/context root and read-only and up the logging level to debug I do see an error message:
23 Aug 23:48:16 - [info] Stopping flows
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : b946eb07.fa1b98
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : a2a74143.03d2d
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 820b503366768e45
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 3fd2634d3eb8f47a
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 40d22656b0e9256d
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 548bfd7e27826d88
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 880331c83e3989d5
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 1ff7a51a41da7b57
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 52d3a9a7a5712824
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 43b59e5a75cfcb1b
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 1ca0aa7a1aebf715
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : db04fd79f3a93d19
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 8a1997dbadd616a7
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 7c2531c9428b61e9
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : fb74b6954e19413f
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : aa0a868df2ab245a
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : ce2c31fd397862f4
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 950c560f3bd27e74
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : 699e0a72d49c76f3
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : a3c3807e16ca19c8
23 Aug 23:48:16 - [debug] red/nodes/flows.stop : stopping flow : global
23 Aug 23:48:16 - [info] Stopped flows
23 Aug 23:48:16 - [debug] Flushing localfilesystem context scope global
23 Aug 23:48:16 - [debug] Flushing localfilesystem context scope 3fd2634d3eb8f47a
23 Aug 23:48:16 - [debug] Flushing localfilesystem context scope 52d3a9a7a5712824
23 Aug 23:48:16 - [debug] Flushing localfilesystem context scope 43b59e5a75cfcb1b
23 Aug 23:48:16 - [debug] Flushing localfilesystem context scope 699e0a72d49c76f3
23 Aug 23:48:16 - [debug] Flushing localfilesystem context scope 8469a1aec341cbbe:aa0a868df2ab245a
23 Aug 23:48:16 - [debug] Flushing localfilesystem context scope 77eca9bb2b4b07a5:aa0a868df2ab245a
23 Aug 23:48:16 - [error] Error writing context: Error: EACCES: permission denied, mkdir '/home/pi/.node-red/context/global'
My guess is at some point you ran something as root and now have mixed permissions.
In short, don't run the install script, npm or node-red as root.
A clean solution is to delete the .node-red
folder and install using the installer script - don't use root.
Not sure who you are talking to, haven't run anything as root
Ah, I mistook that log for yours. Apologies.
Can you show us an example of the code you are using?
Also post your start up log.
the flow
[{"id":"392c1bb3c1c96f96","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"5afda673dba62107","type":"ui_template","z":"392c1bb3c1c96f96","group":"9c90a075584ede2b","name":"GhostThermostat","order":1,"width":0,"height":0,"format":"<style>\n @import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');\n \n svg {\n transition: all .6s cubic-bezier(0.175, 0.885, 0.32, 1.2);\n }\n\n stop {\n transition: all .5s;\n }\n \n\t{{'#GhostThermostat' + $id}} .led {\n \t-webkit-transition: all 0.5s;\n \ttransition: all 0.5s;\n \tfill: url({{'#GhostThermostat' + $id + 'ledColor'}});\n }\n \n {{'#GhostThermostat' + $id}} .fa-text {\n font-family: FontAwesome !important; \n }\n {{'#GhostThermostat' + $id}} .dial {\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n }\n {{'#GhostThermostat' + $id}} .qGradient {\n fill : url({{'#GhostThermostat' + $id + 'qGradient'}});\n }\n {{'#GhostThermostat' + $id}} .qGradientT {\n fill : url({{'#GhostThermostat' + $id + 'qGradientT'}});\n }\n {{'#GhostThermostat' + $id}} .eGradient {\n fill : url({{'#GhostThermostat' + $id + 'eGradient'}});\n }\n {{'#GhostThermostat' + $id}} .lbl {\n font-family: 'Roboto', sans-serif;\n text-anchor: middle;\n fill : #ffffff;\n clip-path: url({{'#GhostThermostat' + $id + 'qClip'}});\n }\n {{'#GhostThermostat' + $id}} .lblDial {\n fill: #dddddd;\n }\n \n {{'#GhostThermostat' + $id}} .lblAmbient {\n font-weight: 400;\n clip-path: url({{'#GhostThermostat' + $id + 'qClip'}});\n }\n \n {{'#GhostThermostat' + $id}} .lblAmbient tspan {\n font-weight: 400;\n }\n \n {{'#GhostThermostat' + $id}} .lblTarget {\n font-weight: 400;\n fill: orange;\n }\n \n {{'#GhostThermostat' + $id}} .lblTarget tspan {\n font-weight: 400;\n fill: orange;\n clip-path: url({{'#GhostThermostat' + $id + 'qClip'}});\n } \n \n {{'#GhostThermostat' + $id}} .nodisplay {\n display: none !important;\n }\n \n {{'#GhostThermostat' + $id}} .icon {\n font-family: FontAwesome !important;\n }\n \n {{'#GhostThermostat' + $id}} .animate {\n transition: all 0.5s;\n }\n\n</style>\n<div id=\"{{'GhostThermostat' + $id}}\"></div> \n<script>\nvar mousedownID = -1;\nvar ghostThermostatDial = (function() {\n console.log(\"START\");\n\n function createSVGElement(tag, attributes, appendTo) {\n var element = document.createElementNS('http://www.w3.org/2000/svg', tag);\n attr(element, attributes);\n if (appendTo) {\n appendTo.appendChild(element);\n }\n return element;\n }\n\n function attr(element, attrs) {\n for (var i in attrs) {\n element.setAttribute(i, attrs[i]);\n }\n }\n\n function setClass(el, className, state) {\n el.classList[state ? 'add' : 'remove'](className);\n }\n\n return function(targetElement, options) {\n console.log(\"RET FUN\");\n var self = this;\n\n /*\n * Options\n */\n options = options || {};\n options = {\n diameter: options.diameter || 400,\n mintemp: options.mintemp || 10, // Minimum value for target temperature\n maxtemp: options.maxtemp || 30, // Maximum value for target temperature\n ledColors: {\n 'off': 'rgb(143,141,141)',\n 'heating': 'rgb(255,128,0)',\n 'cooling': 'rgb(81,170,214)'\n }, //Led Ring Colors\n labels: {\n ambient: \"AMBIENT\",\n set: \"SET\",\n mode: \"MODE\",\n minus: \"-\",\n plus: \"+\",\n left: \"<\",\n right: \">\"\n },\n onChangeState: options.onChangeState || function() {} // Function called when switch state change\n };\n\n /*\n * Properties\n */\n var properties = {\n radius: options.diameter / 2,\n modes: [{\n label: \"heating\",\n icon: \"\\uf06d\",\n color: \"orange\"\n }, {\n label: 'cooling',\n icon: \"\\uf2dc\",\n color: \"rgb(81,170,214)\"\n }, {\n label: \"off\",\n icon: \"\\uf011\",\n color: \"rgb(230,0,0)\"\n }\n /*, {\n\t\t\t\tlabel: 'away',\n\t\t\t\ticon: \"\\uf1ce\",\n\t\t\t\tcolor: \"gray\"\n\t\t\t} */\n ],\n modeNames: [\"heating\", \"cooling\", \"off\"],\n swtitchStates: [\"heating\", \"cooling\", \"off\"]\n };\n\n /*\n * Object state\n */\n var state = {\n target_temperature: options.mintemp,\n ambient_temperature: options.maxtemp,\n mode: properties.modes.indexOf(properties.modes[0]),\n switch_state: 'off',\n away: false\n };\n\n /*\n * Property getter / setters\n */\n Object.defineProperty(this, 'target_temperature', {\n get: function() {\n return state.target_temperature;\n },\n set: function(val) {\n state.target_temperature = rangedTemperature(+val);\n //render()\n }\n });\n\n Object.defineProperty(this, 'ambient_temperature', {\n get: function() {\n return state.ambient_temperature;\n },\n set: function(val) {\n state.ambient_temperature = +val;\n render();\n }\n });\n\n Object.defineProperty(this, 'mode_name', {\n get: function() {\n return properties.modeNames[state.mode];\n },\n set: function(val) {\n if (properties.modeNames.indexOf(val) >= 0) {\n state.mode = properties.modeNames.indexOf(val);\n //render();\n }\n }\n });\n\n Object.defineProperty(this, 'switch_state', {\n get: function() {\n return state.switch_state;\n },\n set: function(val) {\n if (properties.swtitchStates.indexOf(val) >= 0) {\n state.switch_state = val;\n //render();\n }\n }\n });\n\n\n function str2bool(strvalue) {\n return (strvalue && typeof strvalue == 'string') ? (strvalue.toLowerCase() == 'true') : (strvalue == true);\n }\n\n Object.defineProperty(this, 'away', {\n get: function() {\n return state.away;\n },\n set: function(val) {\n state.away = !!str2bool(val);\n //render();\n }\n });\n\n\n /*\n * SVG\n */\n var svg = createSVGElement('svg', {\n width: '100%', //options.diameter+'px',\n height: '100%', //options.diameter+'px',\n viewBox: '0 0 ' + options.diameter + ' ' + options.diameter,\n class: 'dial'\n }, targetElement);\n\n // DEFS \n var defs = createSVGElement('defs', null, svg);\n\n var qgradient = createSVGElement('linearGradient', {\n 'id': targetElement.getAttribute('id') + 'qGradient',\n gradientTransform: 'rotate(65)'\n }, defs);\n var stop = createSVGElement('stop', {\n 'offset': '50%',\n 'stop-color': 'rgb(86,89,94)'\n }, qgradient);\n var stop = createSVGElement('stop', {\n 'offset': '65%',\n 'stop-color': 'rgb(30,30,30)'\n }, qgradient);\n\n var qGradientT = createSVGElement('linearGradient', {\n 'id': targetElement.getAttribute('id') + 'qGradientT',\n gradientTransform: 'rotate(65)'\n }, defs);\n var stop = createSVGElement('stop', {\n 'offset': '55%',\n 'stop-color': '#3b3e43',\n 'stop-opacity': '1'\n }, qGradientT);\n var stop = createSVGElement('stop', {\n 'offset': '90%',\n 'stop-color': 'rgb(0,0,0)',\n 'stop-opacity': '1'\n }, qGradientT);\n\n var clipPath = createSVGElement('clipPath', {\n 'id': targetElement.getAttribute('id') + 'qClip',\n }, defs);\n var circle = createSVGElement('circle', {\n cx: properties.radius,\n cy: properties.radius,\n r: properties.radius - 25\n }, clipPath);\n\n\n var ledRingGradient = createSVGElement('radialGradient', {\n 'id': targetElement.getAttribute('id') + 'ledColor',\n 'cx': \"50%\",\n 'cy': \"50%\",\n 'r': \"95%\",\n 'fx': \"50%\",\n 'fy': \"50%\"\n }, defs);\n var ledRingGradientColorIn = createSVGElement('stop', {\n 'offset': '45%',\n 'stop-color': 'rgb(255,0,130)',\n 'stop-opacity': '1'\n }, ledRingGradient);\n var ledRingGradientColorOut = createSVGElement('stop', {\n 'offset': '65%',\n 'stop-color': 'rgb(0,0,0)',\n 'stop-opacity': '1'\n }, ledRingGradient);\n\n var egradient = createSVGElement('linearGradient', {\n 'id': targetElement.getAttribute('id') + 'eGradient',\n gradientTransform: 'rotate(55)'\n }, defs);\n var stop = createSVGElement('stop', {\n 'offset': '55%',\n 'stop-color': '#888888',\n 'stop-opacity': '1'\n }, egradient);\n var stop = createSVGElement('stop', {\n 'offset': '95%',\n 'stop-color': '#333333',\n 'stop-opacity': '1'\n }, egradient);\n\n // DIAL\n var circle = createSVGElement('circle', {\n cx: properties.radius,\n cy: properties.radius,\n r: properties.radius,\n class: 'eGradient'\n }, svg);\n var ledRing = createSVGElement('circle', {\n cx: properties.radius,\n cy: properties.radius,\n r: properties.radius - 3,\n 'stroke': 'black',\n 'stroke-width': '1',\n class: 'led'\n }, svg);\n var circle = createSVGElement('circle', {\n cx: properties.radius,\n cy: properties.radius,\n r: properties.radius - 20,\n class: 'qGradient'\n }, svg);\n var circle = createSVGElement('circle', {\n cx: properties.radius,\n cy: properties.radius,\n r: properties.radius - 25,\n class: 'qGradient'\n }, svg);\n var lblMain = createSVGElement('text', {\n x: properties.radius,\n y: 70,\n class: 'lbl lblDial'\n }, svg);\n var lblMainText = document.createTextNode(options.labels.ambient);\n lblMain.appendChild(lblMainText);\n\n var lblAmbient = createSVGElement('text', {\n x: properties.radius,\n y: 210,\n 'font-size': '160',\n class: 'lbl lblAmbient'\n }, svg);\n var lblAmbientText = document.createTextNode('21');\n lblAmbient.appendChild(lblAmbientText);\n var lblAmbientDec = createSVGElement('tspan', {\n 'font-size': '60',\n }, lblAmbient);\n var lblAmbientDecText = document.createTextNode('.5');\n lblAmbientDec.appendChild(lblAmbientDecText);\n\n var line = createSVGElement('line', {\n x1: 55,\n y1: properties.radius + 35,\n x2: options.diameter - 55,\n y2: properties.radius + 35,\n 'stroke': '#DDDDDD',\n 'stroke-width': '1',\n 'opacity': '0.8'\n }, svg);\n\n var lblLeft = createSVGElement('text', {\n x: 125,\n y: properties.radius + 75,\n class: 'lbl lblDial'\n }, svg);\n var lblLeftText = document.createTextNode(options.labels.set);\n lblLeft.appendChild(lblLeftText);\n\n var lblTarget = createSVGElement('text', {\n x: 125,\n y: properties.radius + 115,\n 'font-size': '35',\n class: 'lbl lblTarget',\n 'id': targetElement.getAttribute('id') + 'lblTarget'\n }, svg);\n var lblTargetText = document.createTextNode('20');\n lblTarget.appendChild(lblTargetText);\n\n var lblTargetDec = createSVGElement('tspan', {\n 'font-size': '20',\n }, lblTarget);\n\n var lblTargetDecText = document.createTextNode('.5');\n lblTargetDec.appendChild(lblTargetDecText);\n\n var lblRight = createSVGElement('text', {\n x: options.diameter - 125,\n y: properties.radius + 75,\n class: 'lbl lblDial'\n }, svg);\n var lblRightText = document.createTextNode(options.labels.mode);\n lblRight.appendChild(lblRightText);\n\n var lblMode = createSVGElement('text', {\n x: options.diameter - 125,\n y: properties.radius + 115,\n 'font-size': '35',\n class: 'lbl lblTarget icon',\n 'id' : targetElement.getAttribute('id') + 'lblMode'\n }, svg);\n var lblModeText = document.createTextNode(properties.modes[0].icon);\n lblMode.appendChild(lblModeText);\n\n var btnSet = createSVGElement('g', {\n transform: 'translate(200,200)'\n }, svg);\n var btnLeft = createSVGElement('path', {\n d: 'M0,40 L0,175 A175,175 0 0,1 -175,40 z',\n fill: 'blue',\n opacity: '0',\n 'id': targetElement.getAttribute('id') + 'btnLeft'\n }, btnSet);\n var btnRight = createSVGElement('path', {\n d: 'M0,40 L175,40 A175,175 0 0,1 0,175 z',\n fill: 'red',\n opacity: '0',\n 'id': targetElement.getAttribute('id') + 'btnRight'\n }, btnSet);\n\n\n\n btnLeft.onclick = function() {\n setTargetClick();\n };\n\n btnRight.onclick = function() {\n setModeClick();\n };\n\n var targetPanel = false;\n var modePanel = false;\n\n var lblAmbientAttributes = {\n x: lblAmbient.getAttribute('x'),\n y: lblAmbient.getAttribute('y'),\n size: lblAmbient.getAttribute('font-size')\n };\n\n var lblAmbientDecAttributes = {\n x: lblAmbientDec.getAttribute('x'),\n y: lblAmbientDec.getAttribute('y'),\n size: lblAmbientDec.getAttribute('font-size')\n };\n\n var lblTargetAttributes = {\n x: lblTarget.getAttribute('x'),\n y: lblTarget.getAttribute('y'),\n size: lblTarget.getAttribute('font-size')\n };\n\n var lblTargetDecAttributes = {\n x: lblTargetDec.getAttribute('x'),\n y: lblTargetDec.getAttribute('y'),\n size: lblTargetDec.getAttribute('font-size')\n };\n\n var lblModeAttributes = {\n x: lblMode.getAttribute('x'),\n y: lblMode.getAttribute('y'),\n size: lblMode.getAttribute('font-size')\n };\n\n var lblRightAttributes = {\n x: lblRight.getAttribute('x'),\n y: lblRight.getAttribute('y'),\n size: lblRight.getAttribute('font-size')\n };\n\n var lblLeftAttributes = {\n x: lblLeft.getAttribute('x'),\n y: lblLeft.getAttribute('y'),\n size: lblLeft.getAttribute('font-size')\n };\n\n render();\n\n function setAmbientTemperature(ambientTemp) {\n var splitValues = separateDecValue(ambientTemp);\n lblAmbientText.textContent = splitValues.int;\n lblAmbientDecText.textContent = splitValues.dec;\n };\n\n\n function calcTargetTemperature(operation) {\n let currentTemp = Number(parseFloat(lblTargetText.textContent + lblTargetDecText.textContent)).toFixed(1);\n let targetTemp = (operation == '-' ? Number(Number(currentTemp) - 0.5).toFixed(1) : Number(Number(currentTemp) + 0.5).toFixed(1));\n targetTemp = rangedTemperature(targetTemp);\n setTargetTemperature(targetTemp);\n chkSwitchState();\n };\n\n function setTargetTemperature(targetTemp) {\n var splitValues = separateDecValue(targetTemp);\n lblTargetText.textContent = splitValues.int;\n lblTargetDecText.textContent = splitValues.dec;\n if (state.target_temperature != targetTemp) {\n state.target_temperature = targetTemp\n sendMsg();\n };\n };\n\n function separateDecValue(floatFalue) {\n var int = Math.floor(floatFalue);\n var dec = Math.floor(((floatFalue % 1) * 10)) > 0 ? (\".\" + Math.floor(((floatFalue % 1) * 10))) : \"\";\n return {\n int,\n dec\n };\n };\n\n function rangedTemperature(temperature) {\n temperature = temperature < options.mintemp ? options.maxtemp : temperature;\n temperature = temperature > options.maxtemp ? options.mintemp : temperature;\n return temperature;\n };\n\n function chkSwitchState() {\n console.log(\"chkSwitchState\");\n var switchState = state.switch_state;\n switch (state.mode) {\n case 0:\n switchState = state.ambient_temperature < state.target_temperature ? 'heating' : 'off';\n break;\n case 1:\n switchState = state.ambient_temperature > state.target_temperature ? 'cooling' : 'off';\n break;\n default:\n switchState = 'off';\n };\n\n ledRingGradientColorIn.setAttribute('stop-color', options.ledColors[state.switch_state]);\n\n if (state.switch_state != switchState) {\n state.switch_state = switchState;\n sendMsg();\n };\n };\n\n\n function resetButton() {\n btnLeft.onmousedown = \"\";\n btnLeft.onmouseup = \"\";\n btnLeft.onclick = function() {\n setTargetClick();\n };\n btnRight.onmousedown = \"\";\n btnRight.onmouseup = \"\";\n btnRight.onclick = function() {\n setModeClick();\n };\n };\n\n function switchMainView(element, originalAttributes, mainLabel, leftLabel, rightLabel, panelState) {\n setClass(lblAmbient, \"nodisplay\", panelState);\n setClass(lblMain, \"animate\", panelState);\n setClass(lblLeft, \"animate\", panelState);\n setClass(lblRight, \"animate\", panelState);\n setClass(element, \"animate\", panelState);\n\n lblMainText.textContent = panelState ? mainLabel : options.labels.ambient;\n lblLeftText.textContent = panelState ? leftLabel : options.labels.set;\n\n lblLeft.setAttribute('y', panelState ? Number(lblLeftAttributes.y) + 40 : lblLeftAttributes.y);\n lblLeft.setAttribute('font-size', panelState ? \"3.5em\" : \"1em\");\n\n lblRightText.textContent = panelState ? rightLabel : options.labels.mode;\n lblRight.setAttribute('y', panelState ? Number(lblRightAttributes.y) + 40 : lblRightAttributes.y);\n lblRight.setAttribute('font-size', panelState ? \"3.5em\" : \"1em\");\n\n element.setAttribute('x', panelState ? lblAmbientAttributes.x : originalAttributes.x);\n element.setAttribute('x', panelState ? lblAmbientAttributes.x : originalAttributes.x);\n element.setAttribute('y', panelState ? lblAmbientAttributes.y : originalAttributes.y);\n element.setAttribute('font-size', panelState ? lblAmbientAttributes.size : originalAttributes.size);\n\n };\n\n\n function setTargetClick() {\n\n targetPanel = targetPanel ? false : true;\n setClass(lblMode, \"nodisplay\", targetPanel);\n switchMainView(lblTarget, lblTargetAttributes, options.labels.set, options.labels.minus, options.labels.plus, targetPanel);\n\n lblTargetDec.setAttribute('font-size', targetPanel ? lblAmbientDecAttributes.size : lblTargetDecAttributes.size);\n\n if (targetPanel) {\n btnLeft.onclick = \"\";\n btnRight.onclick = \"\";\n\n btnLeft.onmousedown = function() {\n calcTargetTemperature(\"-\");\n if (mousedownID == -1) { //Prevent multimple loops!\n mousedownID = setInterval(calcTargetTemperature, 500, '-');\n }\n };\n btnLeft.onmouseup = function() {\n if (mousedownID != -1) { //Only stop if exists\n clearInterval(mousedownID);\n mousedownID = -1;\n }\n };\n\n btnRight.onmousedown = function() {\n calcTargetTemperature(\"+\");\n if (mousedownID == -1) { //Prevent multimple loops!\n mousedownID = setInterval(calcTargetTemperature, 500, '+');\n }\n };\n btnRight.onmouseup = function() {\n if (mousedownID != -1) { //Only stop if exists\n clearInterval(mousedownID);\n mousedownID = -1;\n }\n };\n\n lblTarget.onclick = function() {\n setTargetClick();\n };\n } else {\n resetButton()\n }\n };\n\n function setModeClick() {\n\n modePanel = modePanel ? false : true;\n setClass(lblTarget, \"nodisplay\", modePanel);\n switchMainView(lblMode, lblModeAttributes, options.labels.mode, options.labels.left, options.labels.right, modePanel);\n\n if (modePanel) {\n\n btnLeft.onclick = function() {\n mode = state.mode;\n mode = --mode < 0 ? properties.modes.length - 1 : mode;\n console.log(\"MODE :\" + mode);\n setModeName(properties.modeNames[mode]);\n chkSwitchState();\n sendMsg();\n };\n\n btnRight.onclick = function() {\n mode = state.mode;\n mode = ++mode > properties.modes.length - 1 ? 0 : mode;\n console.log(\"MODE :\" + mode);\n setModeName(properties.modeNames[mode]);\n chkSwitchState();\n sendMsg();\n };\n// document.getElementById(targetElement.getAttribute('id') + \"lblMode\").onclick = function() {\n lblMode.onclick = function() {\n setModeClick();\n };\n } else {\n resetButton()\n }\n };\n\n function setModeName(modeName) {\n lblMode.textContent = properties.modes[properties.modeNames.indexOf(modeName)].icon;\n lblMode.style.fill = properties.modes[properties.modeNames.indexOf(modeName)].color;\n state.mode = properties.modeNames.indexOf(modeName);\n };\n\n function sendMsg() {\n if (typeof options.onChangeState == 'function') {\n options.onChangeState(state.switch_state);\n }\n };\n\n function render() {\n console.log(\"RENDER\");\n setAmbientTemperature(self.ambient_temperature);\n setTargetTemperature(self.target_temperature);\n setModeName(self.mode_name);\n chkSwitchState();\n };\n\n };\n})();\n\nvar initializing = true;\n(function(scope) {\n console.log(\"scope.id = GhostThermostat\" + scope.$id);\n $(function() {\n var ghostThermostat = new ghostThermostatDial(document.getElementById('GhostThermostat' + scope.$id), {\n onChangeState: function() {\n var p = {\n \"ambient_temperature\": ghostThermostat.ambient_temperature,\n \"target_temperature\": ghostThermostat.target_temperature,\n \"mode\": ghostThermostat.mode_name,\n \"switch_state\": ghostThermostat.switch_state,\n \"away\": ghostThermostat.away\n };\n scope.send({\n topic: \"changed_state\",\n payload: p\n });\n }\n });\n\n\n scope.$watch('msg', function(data) {\n if (initializing) {\n initializing = false;\n } else {\n ghostThermostat.ambient_temperature = data.payload.ambient_temperature || ghostThermostat.ambient_temperature;\n ghostThermostat.target_temperature = data.payload.target_temperature || ghostThermostat.target_temperature;\n ghostThermostat.mode_name = data.payload.mode || ghostThermostat.mode_name;\n ghostThermostat.switch_state = data.payload.switch_state || ghostThermostat.switch_state;\n ghostThermostat.away = data.payload.away || ghostThermostat.away;\n }\n });\n });\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":false,"resendOnRefresh":false,"templateScope":"local","className":"","x":590,"y":280,"wires":[["3619c6bb1af6d574","db8eed00df446e88","de86770d2afb8e56"]],"icon":"font-awesome/fa-tachometer"},{"id":"3619c6bb1af6d574","type":"function","z":"392c1bb3c1c96f96","name":"turn on heat","func":"let Z = msg.payload.switch_state;\n\nif (Z == \"heating\"){\n msg = {\n payload: 1,\n topic: \"heating\",\n }\n return msg;\n}\n\nif (Z == \"cooling\") {\n msg = {\n payload: 1,\n topic: \"cooling\",\n }\n return msg;\n}\n\nmsg = {\n payload: 0,\n topic: \"off\",\n}\n\nnode.status({fill:\"blue\",shape:\"dot\",text:msg.topic});\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":360,"wires":[[]]},{"id":"bd175ed19a1ca4cb","type":"function","z":"392c1bb3c1c96f96","name":"set ambient","func":"let Z = msg.payload;\nZ= Number(Z);\nZ = Z - 4;\nlet num = Z;\nZ = num.toFixed(1);\n\nmsg.topic = 'ambient_temperature';\nvar data = {\n 'ambient_temperature': Z,\n}\nmsg.payload = data;\n\nnode.status({ fill: \"blue\", shape: \"dot\", text: Z });\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":280,"wires":[["5afda673dba62107"]]},{"id":"1d8b2e54ef52fb6b","type":"smooth","z":"392c1bb3c1c96f96","name":"","property":"payload","action":"mean","count":"5","round":"1","mult":"single","reduce":false,"x":180,"y":280,"wires":[["bd175ed19a1ca4cb"]]},{"id":"db8eed00df446e88","type":"function","z":"392c1bb3c1c96f96","name":"store","func":"let Z = msg.payload.mode;\nflow.set(\"mode\",Z);\n\nZ = msg.payload.away;\nflow.set(\"away\",Z);\n\nZ = msg.payload.target_temperature;\nflow.set(\"target\",Z);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":750,"y":420,"wires":[[]]},{"id":"e6ba72baec704adf","type":"inject","z":"392c1bb3c1c96f96","name":"pwr on","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"10","topic":"","payload":"1","payloadType":"str","x":140,"y":160,"wires":[["d3a088cc0ed7208e"]]},{"id":"d3a088cc0ed7208e","type":"function","z":"392c1bb3c1c96f96","name":"set on pwr up","func":"var Ambient = flow.get(\"ambient\");\nvar Away = flow.get(\"away\");\nvar Mode = flow.get(\"mode\");\nvar Target = flow.get(\"target\");\n\nmsg.topic = 'ambient_temperature';\nvar data = {\n// 'ambient_temperature': Ambient,\n 'target_temperature': Target,\n 'away': Away,\n 'mode': Mode,\n}\nmsg.payload = data;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":200,"wires":[["de86770d2afb8e56"]]},{"id":"10636c65ec2b2239","type":"mqtt in","z":"392c1bb3c1c96f96","name":"","topic":"inside1_tempC","qos":"2","datatype":"auto-detect","broker":"718df452c076bbbe","nl":false,"rap":true,"rh":0,"inputs":0,"x":80,"y":220,"wires":[["1d8b2e54ef52fb6b"]]},{"id":"de86770d2afb8e56","type":"function","z":"392c1bb3c1c96f96","name":"refresh","func":"\nvar Ambient;\nvar Away;\nvar Mode;\nvar Target;\n//Target = context.get(\"Target\");\n\nif (msg.topic == \"changed_state\" || msg.topic == \"ambient_temperature\"){\n Ambient = msg.payload.ambient_temperature;\n context.set(\"Ambient\",Ambient);\n Away = msg.payload.away;\n context.set(\"Away\",Away);\n Mode = msg.payload.mode;\n context.set(\"Mode\",Mode);\n Target = msg.payload.target_temperature;\n context.set(\"Target\",Target);\n msg.topic = 'ambient_temperature';\n var data = {\n // 'ambient_temperature': Ambient,\n 'target_temperature': Target,\n 'away': Away,\n 'mode': Mode,\n }\n msg.payload = data;\n return msg;\n}\n\nAmbient = context.get(\"Ambient\");\nAway = context.get(\"Away\");\nMode = context.get(\"Mode\");\nTarget = context.get(\"Target\");\n\nif (Target == undefined) {\n msg.payload = \"undefined\";\n return msg;\n}\n\nmsg.topic = 'ambient_temperature';\nmsg.payload = {\n// 'ambient_temperature': Ambient,\n 'target_temperature': Target,\n 'away': Away,\n 'mode': Mode,\n}\n\nnode.status({ fill: \"blue\", shape: \"dot\", text: Away });\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":600,"y":200,"wires":[["5afda673dba62107"]]},{"id":"6912e86781efd9e9","type":"inject","z":"392c1bb3c1c96f96","name":"3 second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"3","crontab":"","once":true,"onceDelay":"1","topic":"5second","payload":"1","payloadType":"str","x":390,"y":140,"wires":[["de86770d2afb8e56"]]},{"id":"9c90a075584ede2b","type":"ui_group","name":"Thermostat","tab":"f394bc89e321d6f1","order":1,"disp":false,"width":6,"collapse":false,"className":""},{"id":"718df452c076bbbe","type":"mqtt-broker","name":"","broker":"192.168.1.5","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"5","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"f394bc89e321d6f1","type":"ui_tab","name":"Thermostat","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
this is the only node red log file in the /var/log sub-dir
nodered-install.log (1.6 KB)
and I did a restart command several times
Steve meant the output from
node-red-stop
node-red-start
It should be contextStorage, not ContextStorage. In .node-red/settings.js you should have found that line already present, and just had to amend the contents of the object.
Wow, great catch @Colin. That was the problem, Changed to small "c" and presto the sub-dir showed up.
I don't understand how you ended up with the error. The default settings.js file already includes a contextStorage entry that just needs to be edited. Did you not do that or did your settings.js not already include it?
I was wondering if you were going to bring it up. So... yes the entry was there and yes I only needed to modify it, however, and I'm making a guess here for part of it. The cursor wasn't where I thought it was and instead of deleting a character I deleted the block and thus I wound up having to retype the entire thing and used a capital letter instead of a lower case. But, I'm going with I did a great job with it as I only missed one character.
OK, that explains it. Hasn't your editor got an Undo feature?