-
-
Notifications
You must be signed in to change notification settings - Fork 86
Cache and Replay Messages without using node red contrib infocache
Update 2023-01-10: uib-cache went live with uibuilder v5 as expected and has been improved since then. Caching leverages Node-RED's native context storage and so can be persistent across restarts if desired. Some of the other uibuilder nodes can also now use the same caching capabilities. uib-cache will continue to improve and so it strongly recommended that you use it rather than creating your own scheme.
Update 2022-01-19: When v5 goes live, a new node uib-cache
will be available which could be used instead of a function node.
If you want to cache and replay messages without another node, here is a very simple example flow.
This is the function that is key. As always, it is up to you to keep track of how much memory is being consumed. The replayed messages will go to the client that requested them if it can identify it.
The function only keeps the last 1 message of each topic and this version has no method to clear the cache.
// Expects input msgs with topic set
// saved context
var homeMsgs = context.get('homeMsgs') || {}
// Replay cache if requested
if ( msg.hasOwnProperty('cacheControl') && msg.cacheControl === 'REPLAY' ) {
for (var topic in homeMsgs) {
// Only send to a single client if we can
if ( msg.hasOwnProperty('_socketId') )
node.send({
"topic": topic,
"payload": homeMsgs[topic],
"_socketId": msg._socketId
})
else
node.send({
"topic": topic,
"payload": homeMsgs[topic]
})
}
return null
}
// ignore cacheControl and uibuilder control messages
if ( msg.hasOwnProperty('cacheControl') || msg.hasOwnProperty('uibuilderCtrl') ) return null
// Keep the last msg.payload by topic
homeMsgs[msg.topic] = msg.payload
// save context for next time
context.set('homeMsgs', homeMsgs)
return msg;
Note that the flow doesn't contain the MQTT-in node that drives it. Adapt to your own requirements.
[{"id":"401897b8.9931e8","type":"uibuilder","z":"9974253c.de8db8","name":"","topic":"","url":"home","fwdInMessages":false,"allowScripts":true,"allowStyles":true,"debugFE":false,"copyIndex":true,"x":490,"y":700,"wires":[["d0dec491.704248"],["bbc35ca3.97343","ff280acc.207098"]]},{"id":"d0dec491.704248","type":"debug","z":"9974253c.de8db8","name":"home data out","active":true,"console":"false","complete":"true","x":680,"y":680,"wires":[]},{"id":"889a6459.17d2f8","type":"function","z":"9974253c.de8db8","name":"","func":"// Expects input msgs with topic set\n\n// saved context\nvar homeMsgs = context.get('homeMsgs') || {}\n\n// Replay cache if requested\nif ( msg.hasOwnProperty('cacheControl') && msg.cacheControl === 'REPLAY' ) {\n for (var topic in homeMsgs) {\n // Only send to a single client if we can\n if ( msg.hasOwnProperty('_socketId') )\n node.send({\n \"topic\": topic, \n \"payload\": homeMsgs[topic],\n \"_socketId\": msg._socketId\n })\n else\n node.send({\n \"topic\": topic, \n \"payload\": homeMsgs[topic]\n })\n }\n return null\n}\n\n// ignore cacheControl and uibuilder control messages\nif ( msg.hasOwnProperty('cacheControl') || msg.hasOwnProperty('uibuilderCtrl') ) return null\n\n// Keep the last msg.payload by topic\nhomeMsgs[msg.topic] = msg.payload\n\n// save context for next time\ncontext.set('homeMsgs', homeMsgs)\n\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":700,"wires":[["401897b8.9931e8","b4850396.c9aef"]]},{"id":"bbc35ca3.97343","type":"debug","z":"9974253c.de8db8","name":"home controls","active":true,"console":"false","complete":"true","x":680,"y":720,"wires":[]},{"id":"e35dc750.bbfbe8","type":"link in","z":"9974253c.de8db8","name":"home-replay","links":["ff280acc.207098"],"x":115,"y":700,"wires":[["889a6459.17d2f8"]]},{"id":"ff280acc.207098","type":"link out","z":"9974253c.de8db8","name":"home-controls","links":["e35dc750.bbfbe8"],"x":615,"y":760,"wires":[]},{"id":"b4850396.c9aef","type":"debug","z":"9974253c.de8db8","name":"input messages","active":true,"console":"false","complete":"true","x":480,"y":640,"wires":[]}]
Please feel free to add comments to the page (clearly mark with your initials & please add a commit msg so we know what has changed). You can contact me in the Discourse forum, or raise an issue here in GitHub! I will make sure all comments & suggestions are represented here.
-
Walkthrough 🔗 Getting started
-
In Progress and To Do 🔗 What's coming up for uibuilder?
-
Awesome uibuilder Examples, tutorials, templates and references.
-
How To
- How to send data when a client connects or reloads the page
- Send messages to a specific client
- Cache & Replay Messages
- Cache without a helper node
- Use webpack to optimise front-end libraries and code
- How to contribute & coding standards
- How to use NGINX as a proxy for Node-RED
- How to manage packages manually
- How to upload a file from the browser to Node-RED
-
Vanilla HTML/JavaScript examples
-
VueJS general hints, tips and examples
- Load Vue (v2 or v3) components without a build step (modern browsers only)
- How to use webpack with VueJS (or other frameworks)
- Awesome VueJS - Tips, info & libraries for working with Vue
- Components that work
-
VueJS v3 hints, tips and examples
-
VueJS v2 hints, tips and examples
- Dynamically load .vue files without a build step (Vue v2)
- Really Simple Example (Quote of the Day)
- Example charts using Chartkick, Chart.js, Google
- Example Gauge using vue-svg-gauge
- Example charts using ApexCharts
- Example chart using Vue-ECharts
- Example: debug messages using uibuilder & Vue
- Example: knob/gauge widget for uibuilder & Vue
- Example: Embedded video player using VideoJS
- Simple Button Acknowledgement Example Thanks to ringmybell
- Using Vue-Router without a build step Thanks to AFelix
- Vue Canvas Knob Component Thanks to Klaus Zerbe
-
Examples for other frameworks (check version before trying)
- Basic jQuery example - Updated for uibuilder v6.1
- ReactJS with no build - updated for uibuilder v5/6
-
Examples for other frameworks (may not work, out-of-date)
-
Outdated Pages (Historic only)
- v1 Examples (these need updating to uibuilder v2/v3/v4/v5)