UPDATED - 6th May
Still experimenting with settings using MQTT (doesn't seem hopeful ATM, but early days yet!)
MQTT published every minute or when http call makes a 'valid' change to the settings Otherwise no calls seem to work
Temperature can be changed AND Position can be changed (Automatic Temp Control en/dis) (MQTT/HTTTP) (Not yet sure what actual interaction is with TRV, assume stays in set mode (Auto Temp Control) )
Only 2 MQTT messages come back
EDIT & UPDATE - 6th May
Major Observation: Summer is not the time to set about configuring a TRV on a radiator in Node-RED or indeed any other Control System. No heat is required!!
Played around with everything and ended up with this as the final flow to control the valve. Still need to get the MQTT alive/announce messages monitored. But the TRV is not that easy to switch on and off - needs resetting all the time.
Updated flow using @Colin node-red-contrib-pid. Unfortunately due to my 'Major Observation', I can't set the system up without wasting a lot of heat and sweating my eyeballs out!!
[{"id":"b4973237.46ab6","type":"subflow","name":"Process Simulation","info":"","in":[{"x":37,"y":103,"wires":[{"id":"ec719d4d.0d54f8"}]}],"out":[{"x":728.5,"y":294,"wires":[{"id":"ae1a6e5.d4c0d9","port":0}]}]},{"id":"7fe4b5c3.32e58c","type":"function","z":"b4973237.46ab6","name":"30 sec RC + 20","func":"// Applies a simple RC low pass filter to incoming payload values\nvar tc = 30*1000; // time constant in milliseconds\n\nvar lastValue = context.get('lastValue');\nif (typeof lastValue == \"undefined\") lastValue = msg.payload;\nvar lastTime = context.get('lastTime') || null;\nvar now = new Date();\nvar currentValue = msg.payload;\nif (lastTime === null) {\n // first time through\n newValue = currentValue;\n} else {\n var dt = now - lastTime;\n var newValue;\n \n if (dt > 0) {\n var dtotc = dt / tc;\n newValue = lastValue * (1 - dtotc) + currentValue * dtotc;\n } else {\n // no time has elapsed leave output the same as last time\n newValue = lastValue;\n }\n}\ncontext.set('lastValue', newValue);\ncontext.set('lastTime', now);\n\nmsg.payload = newValue + 20;\nreturn msg;","outputs":1,"noerr":0,"x":626.5,"y":207,"wires":[["ae1a6e5.d4c0d9"]]},{"id":"1bacd004.9753c","type":"inject","z":"b4973237.46ab6","name":"Inject -0.2 at start","props":[{"p":"payload","v":"-0.2","vt":"num"},{"p":"topic","v":"","vt":"str"}],"repeat":"","crontab":"","once":true,"topic":"","payload":"-0.2","payloadType":"num","x":134.5,"y":30,"wires":[["ec719d4d.0d54f8"]]},{"id":"999a52c2.f465f","type":"function","z":"b4973237.46ab6","name":"10 sec RC","func":"// Applies a simple RC low pass filter to incoming payload values\nvar tc = 10*1000; // time constant in milliseconds\n\nvar lastValue = context.get('lastValue');\nif (typeof lastValue == \"undefined\") lastValue = msg.payload;\nvar lastTime = context.get('lastTime') || null;\nvar now = new Date();\nvar currentValue = msg.payload;\nif (lastTime === null) {\n // first time through\n newValue = currentValue;\n} else {\n var dt = now - lastTime;\n var newValue;\n \n if (dt > 0) {\n var dtotc = dt / tc;\n newValue = lastValue * (1 - dtotc) + currentValue * dtotc;\n } else {\n // no time has elapsed leave output the same as last time\n newValue = lastValue;\n }\n}\ncontext.set('lastValue', newValue);\ncontext.set('lastTime', now);\n\nmsg.payload = newValue;\nreturn msg;","outputs":1,"noerr":0,"x":451,"y":207,"wires":[["7fe4b5c3.32e58c"]]},{"id":"ec719d4d.0d54f8","type":"delay","z":"b4973237.46ab6","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":268,"y":104,"wires":[["ede39236.1961f8"]]},{"id":"a823c9cf.2a6178","type":"function","z":"b4973237.46ab6","name":"2 msg transport delay","func":"// stores messages in a fifo until the specified number have been received, \n// then releases them as new messages are received.\n// during the filling phase the earliest message is passed on each time \n// a message is received, but it is also left in the fifo\nvar fifoMaxLength = 2;\nvar fifo = context.get('fifo') || [];\n// push the new message onto the top of the array, messages are shifted down and\n// drop off the front\nvar length = fifo.push(msg); // returns new length\nif (length > fifoMaxLength) {\n newMsg = fifo.shift();\n} else {\n // not full yet, make a copy of the msg and pass it on\n var newMsg = JSON.parse(JSON.stringify(fifo[0]));\n}\ncontext.set('fifo', fifo);\nreturn newMsg;","outputs":1,"noerr":0,"x":258,"y":208,"wires":[["999a52c2.f465f"]]},{"id":"ae1a6e5.d4c0d9","type":"function","z":"b4973237.46ab6","name":"Clear all except payload","func":"msg2 = {payload: msg.payload};\nreturn msg2;","outputs":1,"noerr":0,"x":545,"y":293,"wires":[[]]},{"id":"ede39236.1961f8","type":"range","z":"b4973237.46ab6","minin":"0","maxin":"1","minout":"0","maxout":"100","action":"scale","round":false,"property":"payload","name":"","x":87,"y":208,"wires":[["a823c9cf.2a6178"]]},{"id":"d02432332410fee7","type":"tab","label":"TRV (experimental)","disabled":false,"info":"","env":[]},{"id":"560e1bddf38cc31f","type":"http request","z":"d02432332410fee7","name":"TRV Basic","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://172.27.123.250/{{{topic}}}","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":710,"y":220,"wires":[["0668e8a3091344bd"]]},{"id":"bc0fd61e8b0e9da0","type":"debug","z":"d02432332410fee7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1030,"y":220,"wires":[]},{"id":"3a0aa17655d036f2","type":"inject","z":"d02432332410fee7","d":true,"name":"LR Temp","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":true,"onceDelay":"37","topic":"ext_t?temp","payload":"incomingTemperature","payloadType":"global","x":330,"y":220,"wires":[["86e75ef344fa6d7f","632778447a5b0a6c"]]},{"id":"632778447a5b0a6c","type":"function","z":"d02432332410fee7","name":"","func":"msg.topic = msg.topic + \"=\" + msg.payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":220,"wires":[["560e1bddf38cc31f"]]},{"id":"01321ae30cbd3c04","type":"comment","z":"d02432332410fee7","name":"LRoom temp from ESP set TRV and load PID","info":"","x":210,"y":140,"wires":[]},{"id":"c3cfa5de699d9335","type":"rbe","z":"d02432332410fee7","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":false,"property":"setpoint","topi":"topic","x":430,"y":300,"wires":[["c210bd83a3d901af","86e75ef344fa6d7f"]]},{"id":"c210bd83a3d901af","type":"debug","z":"d02432332410fee7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":630,"y":300,"wires":[]},{"id":"e36ca8663ce106be","type":"comment","z":"d02432332410fee7","name":"msg.setpoint from Opto","info":"","x":360,"y":260,"wires":[]},{"id":"86e75ef344fa6d7f","type":"PID","z":"d02432332410fee7","name":"","setpoint":"","pb":"0","ti":"1080","td":"0","integral_default":"0","smooth_factor":"0","max_interval":600,"enable":"1","disabled_op":"0","x":490,"y":440,"wires":[["07743f5b26a95c03","b2d9acaae01c6021","9bb80bbba7590d7d","f548234b8e0e62e5","e063d72d64ad0f63","819c26e31b6b382a"]]},{"id":"81924ea443ec8e39","type":"change","z":"d02432332410fee7","name":"plot op","rules":[{"t":"set","p":"topic","pt":"msg","to":"op","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":600,"wires":[["0dfe07175542b3fa"]]},{"id":"16aa0f2c2bc09abe","type":"inject","z":"d02432332410fee7","name":"enable","repeat":"","crontab":"","once":false,"topic":"enable","payload":"true","payloadType":"bool","x":290,"y":420,"wires":[["86e75ef344fa6d7f"]]},{"id":"0519eed112476ddb","type":"inject","z":"d02432332410fee7","name":"disable","repeat":"","crontab":"","once":false,"topic":"enable","payload":"false","payloadType":"bool","x":290,"y":460,"wires":[["86e75ef344fa6d7f"]]},{"id":"07743f5b26a95c03","type":"subflow:b4973237.46ab6","z":"d02432332410fee7","d":true,"name":"","x":210,"y":520,"wires":[["e063d72d64ad0f63","86e75ef344fa6d7f"]]},{"id":"e063d72d64ad0f63","type":"change","z":"d02432332410fee7","name":"plot pv","rules":[{"t":"set","p":"topic","pt":"msg","to":"pv","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"pv","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":520,"wires":[["0dfe07175542b3fa"]]},{"id":"b2d9acaae01c6021","type":"range","z":"d02432332410fee7","minin":"0","maxin":"1","minout":"0","maxout":"100","action":"scale","round":false,"property":"payload","name":"Scale power","x":650,"y":440,"wires":[["7ac010c03d4e4881"]]},{"id":"0dfe07175542b3fa","type":"ui_chart","z":"d02432332410fee7","name":"","group":"c45a83a3.d00908","order":1,"width":20,"height":"10","label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"30","removeOlder":"6","removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#cf0005","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":910,"y":500,"wires":[[]]},{"id":"c99a2afa44718110","type":"inject","z":"d02432332410fee7","name":"Clear chart on deploy","repeat":"","crontab":"","once":true,"topic":"","payload":"{\"data\":[]}","payloadType":"json","x":220,"y":660,"wires":[["40fa26f84a7e0cfa"]]},{"id":"40fa26f84a7e0cfa","type":"change","z":"d02432332410fee7","name":"","rules":[{"t":"move","p":"payload.data","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":660,"wires":[["0dfe07175542b3fa"]]},{"id":"9bb80bbba7590d7d","type":"debug","z":"d02432332410fee7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":770,"y":340,"wires":[]},{"id":"f548234b8e0e62e5","type":"change","z":"d02432332410fee7","name":"plot sp","rules":[{"t":"set","p":"payload","pt":"msg","to":"setpoint","tot":"msg"},{"t":"set","p":"topic","pt":"msg","to":"sp","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":560,"wires":[["0dfe07175542b3fa"]]},{"id":"24479212f574dad9","type":"debug","z":"d02432332410fee7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":770,"y":380,"wires":[]},{"id":"919778142ca4fb49","type":"inject","z":"d02432332410fee7","d":true,"name":"","props":[{"p":"setpoint","v":"CHDesired","vt":"global"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":true,"onceDelay":"36","topic":"","x":270,"y":300,"wires":[["c3cfa5de699d9335"]]},{"id":"eefd39435a608ebf","type":"comment","z":"d02432332410fee7","name":"msg.payload to PID (Actual temp)","info":"","x":610,"y":260,"wires":[]},{"id":"7ac010c03d4e4881","type":"function","z":"d02432332410fee7","name":"Pos control","func":"msg.payload = msg.payload\nmsg.topic = \"pos\"\nmsg.payload1 = \"0\";\nmsg.topic1 = \"target_t_enabled\"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":830,"y":440,"wires":[["b6b184198d84aa47","24479212f574dad9"]]},{"id":"b6b184198d84aa47","type":"http request","z":"d02432332410fee7","name":"/thermostat/0","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://172.27.123.250/thermostat/0/?{{{topic1}}}={{{payload1}}}&{{{topic}}}={{{payload}}}","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":1010,"y":440,"wires":[["716b2b6c91de1882"]]},{"id":"716b2b6c91de1882","type":"function","z":"d02432332410fee7","name":"Get 'status'","func":"msg.topic = \"status\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1090,"y":480,"wires":[["8163b3e32192f2d9"]]},{"id":"3d054e3d45f82631","type":"mqtt in","z":"d02432332410fee7","name":"ALL TRV MQTT","topic":"shellies/shellytrv-14B4571946F0/#","qos":"2","datatype":"utf8","broker":"0549f612016b7da9","nl":false,"rap":true,"rh":0,"inputs":0,"x":240,"y":840,"wires":[["9f3d35490b3d76f7"]]},{"id":"741168a7b9d865c9","type":"switch","z":"d02432332410fee7","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"shellies/shellytrv-14B4571946F0/info","vt":"str"},{"t":"eq","v":"shellies/shellytrv-14B4571946F0/settings","vt":"str"},{"t":"eq","v":"status","vt":"str"},{"t":"eq","v":"settings","vt":"str"},{"t":"eq","v":"boost_minutes","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":6,"x":550,"y":840,"wires":[["9abee14ebcf82de5"],["7e74adf60be50ec9"],["15e20e91bd2cb834"],["593036628a5eeb0b"],["3d98d1fa52e8307c"],["06cb50c8bf39a59d"]]},{"id":"be286980df423f96","type":"catch","z":"d02432332410fee7","name":"","scope":["9f3d35490b3d76f7"],"uncaught":false,"x":550,"y":940,"wires":[["a4d6bbfda6d4390e"]]},{"id":"06cb50c8bf39a59d","type":"debug","z":"d02432332410fee7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":900,"wires":[]},{"id":"9abee14ebcf82de5","type":"function","z":"d02432332410fee7","name":"","func":"let position = msg.payload.thermostats[0].pos || 0;\nlet target_temp = msg.payload.thermostats[0].target_t.value || 0;\nlet actual_temp = msg.payload.thermostats[0].tmp.value || 0;\nlet battery = msg.payload.bat.value || 0;\nlet voltage = msg.payload.bat.voltage || 0;\nlet tempPos = msg.payload.thermostats[0].target_t.enabled || 0;\n\nreturn {position:position, target_temp:target_temp, actual_temp:actual_temp, battery:battery, voltage:voltage}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":700,"y":740,"wires":[["8cb18138b7e1d975"]]},{"id":"8cb18138b7e1d975","type":"rbe","z":"d02432332410fee7","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":850,"y":740,"wires":[["a499318a6364361e"]]},{"id":"a499318a6364361e","type":"debug","z":"d02432332410fee7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":740,"wires":[]},{"id":"7e74adf60be50ec9","type":"debug","z":"d02432332410fee7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":780,"wires":[]},{"id":"15e20e91bd2cb834","type":"debug","z":"d02432332410fee7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":820,"wires":[]},{"id":"593036628a5eeb0b","type":"debug","z":"d02432332410fee7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":860,"wires":[]},{"id":"3d98d1fa52e8307c","type":"debug","z":"d02432332410fee7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":900,"wires":[]},{"id":"a4d6bbfda6d4390e","type":"debug","z":"d02432332410fee7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":940,"wires":[]},{"id":"8163b3e32192f2d9","type":"http request","z":"d02432332410fee7","name":"TRV Basic","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://172.27.123.250/{{{topic}}}","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":1270,"y":480,"wires":[[]]},{"id":"335ce69c5d3bd2ab","type":"comment","z":"d02432332410fee7","name":"ALL TRV MQTT Messages","info":"","x":210,"y":800,"wires":[]},{"id":"819c26e31b6b382a","type":"range","z":"d02432332410fee7","minin":"0","maxin":"1","minout":"0","maxout":"25","action":"scale","round":false,"property":"payload","name":"Scale power","x":430,"y":600,"wires":[["81924ea443ec8e39"]]},{"id":"1a068d9678ce1855","type":"inject","z":"d02432332410fee7","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"status","x":110,"y":60,"wires":[["560e1bddf38cc31f","f0fb12b53f97e3d4"]]},{"id":"3c0adb0a635b3200","type":"inject","z":"d02432332410fee7","name":"","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"settings","payloadType":"str","x":120,"y":100,"wires":[["560e1bddf38cc31f","f0fb12b53f97e3d4"]]},{"id":"9f3d35490b3d76f7","type":"json","z":"d02432332410fee7","name":"json 1","property":"payload","action":"obj","pretty":false,"x":410,"y":840,"wires":[["741168a7b9d865c9","5add9b9caa86824c"]]},{"id":"5add9b9caa86824c","type":"debug","z":"d02432332410fee7","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":410,"y":900,"wires":[]},{"id":"f0fb12b53f97e3d4","type":"debug","z":"d02432332410fee7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":290,"y":60,"wires":[]},{"id":"0668e8a3091344bd","type":"json","z":"d02432332410fee7","name":"","property":"payload","action":"","pretty":false,"x":870,"y":220,"wires":[["bc0fd61e8b0e9da0"]]},{"id":"c1fb5cae138c486c","type":"change","z":"d02432332410fee7","name":"","rules":[{"t":"set","p":"setpoint","pt":"msg","to":"CHDesired","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":180,"wires":[["c3cfa5de699d9335","981c92e7df97a04b"]]},{"id":"981c92e7df97a04b","type":"change","z":"d02432332410fee7","name":"LR Temp.","rules":[{"t":"set","p":"payload","pt":"msg","to":"incomingTemperature","tot":"global"},{"t":"set","p":"topic","pt":"msg","to":"ext_t?temp","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":180,"wires":[["86e75ef344fa6d7f","632778447a5b0a6c"]]},{"id":"122cbde94b33b529","type":"inject","z":"d02432332410fee7","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":true,"onceDelay":".75","topic":"","payload":"","payloadType":"date","x":130,"y":180,"wires":[["c1fb5cae138c486c"]]},{"id":"c45a83a3.d00908","type":"ui_group","name":"PID","tab":"80cd4062.93a5","order":1,"disp":true,"width":20,"collapse":false,"className":""},{"id":"0549f612016b7da9","type":"mqtt-broker","name":"NodeRED MQTT","broker":"172.27.123.58","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""},{"id":"80cd4062.93a5","type":"ui_tab","name":"TRV Chart","icon":"dashboard","disabled":false,"hidden":false}]