Inject preset numbers at different times of day

I want to change the value of a saved flow context several times during a day, for example;

0000hrs == 45
0400hrs == 64
0500hrs == 55
0800hrs == 50
etc, etc...

I realise that I could achieve this simply by having a number of inject nodes, all set with the relevant time & value (feeding into a change node) but wondered if anyone knew of a node which has this function instead of using lots of inject nodes?
I've looked through the flows library & searched the forum, but can't see anything obvious.

Thanks

Doh! just hit by a lightning bolt - a ramp-thermostat node!

You could mark this as the solution :slight_smile:

1 Like

I could.. but I want to try it first, to see if Plan A works....

1 Like

This is how i solve most variable configurations in my flows (although i guess your problem could be solved easier), but maybe it fits for you.

To try it you have to change the time in the config (keep the TZ in mind)

[{"id":"bd0ad736.9379c8","type":"inject","z":"c421dfeb.3e752","name":"config","topic":"","payload":"[{\"time\":\"1544\",\"name\":\"t1\",\"system\":\"xiaomi\",\"val\":5},{\"time\":\"1539\",\"name\":\"t2\",\"system\":\"xiaomi\",\"val\":15}]","payloadType":"json","repeat":"","crontab":"","once":true,"onceDelay":"","x":312,"y":2833,"wires":[["a99e0ad7.3ebd08"]]},{"id":"a99e0ad7.3ebd08","type":"split","z":"c421dfeb.3e752","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":450,"y":2848,"wires":[["835ad930.18c278"]]},{"id":"835ad930.18c278","type":"change","z":"c421dfeb.3e752","name":"prep","rules":[{"t":"set","p":"topic","pt":"msg","to":"payload.time","tot":"msg"},{"t":"set","p":"priority","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":598,"y":2863,"wires":[["9dff040d.392b88"]]},{"id":"80b5655e.140048","type":"inject","z":"c421dfeb.3e752","name":"","topic":"","payload":"","payloadType":"date","repeat":"60","crontab":"","once":false,"onceDelay":0.1,"x":437,"y":3013,"wires":[["e3aa05e8.6d6ce8"]]},{"id":"e3aa05e8.6d6ce8","type":"change","z":"c421dfeb.3e752","name":"prep","rules":[{"t":"set","p":"topic","pt":"msg","to":"$replace($substring($now(),11,5),\":\",\"\")","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":596,"y":2957,"wires":[["9dff040d.392b88"]]},{"id":"6ab6083d.058978","type":"debug","z":"c421dfeb.3e752","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":918,"y":2913,"wires":[]},{"id":"9dff040d.392b88","type":"function","z":"c421dfeb.3e752","name":"AJV8","func":"var countmsg = 2;          //how many items to join?\n\nvar nodublicates = false;   //only join if payload unequal existing payload\nvar limit;                 //only join if payloads are on both sides of the limit\nvar hysteresis;      //hysteresis \nvar clearaftersend = false;//clear queue after sending\nvar sendinstantly = false;\nvar reverse = false;         //reverse output array\nvar priomode = false;\nvar storagemode = true;     \n//------------ different topic mode ------------------\nvar diftopics = false;      //true: join only different topics; false: join only same topics\n\nvar inmsg = msg;\nvar outmsg = { \"topic\": inmsg.topic , \"payload\": \"\"};\nvar msgs = context.get(\"aggmsgs\")||{};\nvar topicmsgs = msgs[inmsg.topic]||[];\nvar lastval = context.get(\"lastval\");\nvar inprio = typeof inmsg.priority != \"undefined\" ? inmsg.priority: countmsg-1 ;     //default prio is 1\n\nif (inmsg.topic === \"\")\n    return null;\n\nif (typeof inmsg.reset != \"undefined\") {\n    msgs = {};\n    topicmsgs = [];\n    lastval = undefined;\n    context.set(\"aggmsgs\",msgs);\n    context.set(\"lastval\",lastval);\n    return null;\n}\nif (typeof inmsg.resettopic != \"undefined\") {\n    topicmsgs = [];\n    lastval = undefined;\n}\nif (typeof hysteresis !== 'undefined' && typeof lastval !== 'undefined') {\n    if (Math.abs(inmsg.payload - lastval) <= hysteresis) {\n        return null;\n    }\n}\nif (typeof lastval !== 'undefined') {\n    if (nodublicates && lastval == inmsg.payload)\n        return null;\n    if (typeof limit !== 'undefined' && countmsg == 2) {\n        if (!((lastval <= limit && inmsg.payload >= limit) || (lastval >= limit && inmsg.payload <= limit)))   \n            return null;\n    }\n} \n\nif (diftopics) {\n    if (topicmsgs.length > 0) {     //msg with same topic -> replace old msg\n        topicmsgs.shift();\n    }\n    topicmsgs.push(inmsg);\n    msgs[inmsg.topic] = topicmsgs;    \n    if (Object.keys(msgs).length > countmsg) {\n        for (var tmsgs in msgs) {\n            if (msgs.hasOwnProperty(tmsgs)) {   \n                delete msgs[tmsgs];\n                break;\n            }\n        }\n    }\n    context.set(\"aggmsgs\",msgs);\n    context.set(\"lastval\",inmsg.payload);\n    if (Object.keys(msgs).length == countmsg) {\n        var aout = {};\n        outmsg.topic = \"\";\n        for (var tmsgs in msgs) {\n            if (msgs.hasOwnProperty(tmsgs)) {\n                aout[tmsgs] = msgs[tmsgs][0];\n                outmsg.topic += tmsgs + \"_\";\n            }\n        }\n        if (clearaftersend) {\n            context.set(\"aggmsgs\",undefined);\n            context.set(\"lastval\",undefined);\n        }\n        outmsg.topic = outmsg.topic.substr(0,String(outmsg.topic).length-1);\n        outmsg.payload = aout;\n        if (reverse) {\n            var revArr = outmsg.payload.map(a => Object.assign({}, a));\n            revArr.reverse();\n            outmsg.payload = revArr;\n        }\n        return outmsg;\n    } else\n        return null;\n} else {\n    if (topicmsgs.length == countmsg && !storagemode){\n        topicmsgs.shift();\n    }\n    if (storagemode) {\n        topicmsgs[inprio] = inmsg;\n    } else {\n        topicmsgs.push(inmsg);\n    }\n\n    msgs[inmsg.topic] = topicmsgs;\n    context.set(\"aggmsgs\",msgs);\n    context.set(\"lastval\",inmsg.payload);\n    \n    if (storagemode) {                          //check send msg\n        if (inprio < topicmsgs.length - 1)      //only send on trigger msg => no priority\n            return null;\n        for (var i = 0; i < topicmsgs.length; i++) { //only send if storage is full\n            if (topicmsgs[i] === undefined)\n                return null;\n        }    \n    }\n\n    if (topicmsgs.length == countmsg || sendinstantly) {\n        outmsg.payload = topicmsgs;\n        if (clearaftersend) {\n            msgs[inmsg.topic] = undefined;\n            context.set(\"aggmsgs\",msgs);\n            context.set(\"lastval\",undefined);\n        }\n        if (reverse) {\n            var revArr = outmsg.payload.map(a => Object.assign({}, a));\n            revArr.reverse();\n            outmsg.payload = revArr;\n        }\n        return outmsg;\n    }\n    else\n        return null;\n}\n\n","outputs":1,"noerr":0,"x":740,"y":2914,"wires":[["6ab6083d.058978"]]}]
1 Like

@moebius Thanks, but a bit overkill for my needs.
Colin's node-red-contrib-ramp-thermostat works well also, so I'll stick with it.

Not mine.
I think it a pity that node combines the ramp and the t/stat. I think it would be better as two components, the ramp for profiling anything, possibly in no way related to a t/stat, and the t/stat as a separate node.

No problem - i've learned even something with the sample! Cause the use of a colon inside the topic gave me a hard time (guess because it's internally used as identifier)... :slight_smile:

Ah, my wrong assumption - it's the work of @cflurin
But yes, agree Colin. I'm getting around the 'ramp' problem by setting 2 values very close to each other.

0000hrs == 45
0359hrs == 45
0400hrs == 64
0459hrs == 64
0500hrs == 55
etc, etc...

From memory I thought you could make the timestamps the same to get an instantaneous change, so in your example
0000hrs == 45
0400hrs == 45
0400hrs == 64
0500hrs == 64
0500hrs == 55
etc, etc...

but I may be mistaken.

1 Like

No mistake Colin, that does work.

1 Like

Another possibility using the inbuilt nodes:

[{"id":"f4f88c80.c5fc5","type":"change","z":"1d66267b.4c5caa","name":"","rules":[{"t":"set","p":"time","pt":"msg","to":"$substring($fromMillis(payload+36E5),11,5)","tot":"jsonata"},{"t":"set","p":"output","pt":"flow","to":"$exists($flowContext(\"output\")) ? $flowContext(\"output\") : \"Assigned\" ","tot":"jsonata"},{"t":"set","p":"output","pt":"flow","to":"time = \"13:25\" ? \"First Condition\" : $flowContext(\"output\")","tot":"jsonata"},{"t":"set","p":"output","pt":"flow","to":"time = \"13:30\" ? \"Second Condition\" : $flowContext(\"output\")","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":460,"wires":[["b94eb2b2.7aaa1"]]},{"id":"b94eb2b2.7aaa1","type":"debug","z":"1d66267b.4c5caa","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"$flowContext(\"output\")","targetType":"jsonata","x":550,"y":460,"wires":[]},{"id":"7963cee6.9568e","type":"inject","z":"1d66267b.4c5caa","name":"","topic":"","payload":"","payloadType":"date","repeat":"10","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":460,"wires":[["f4f88c80.c5fc5"]]}]
1 Like

That's quite a clever solution!

Thanks