Uibuilder - load data after a webpage has loaded

I am probably aiming higher than I can reach, but as they say, go big, or go home. I am writing a Burglar Alarm system, yes another one, but of course mine will be better than all the others :-). I am fine doing the node-red side of things, I program industrial PLCs as my job, but I am very much a beginner with uibuilder. To prepare I have done a beginners course on html, beginners course on CSS and a beginners course on bootstrap, and if I understood what bootstrap-vue was for I might do a course on that :-). I have managed to get node-red sending messages to uibuilder and to get uibuilder to send messages to node-red.

Should have said, nice work on uibuilder, thank you.

Programs I write for HMIs (industrial screens) tend to be multilanguage and allow a factory to even set the colours of things on screen, there is very little hard-coded, which brings me to my problem. I don't want to hard-code the name of Zones in the alarm, the user will go to a webpage where they can alter names and then store them to a Global file. So if you had 'Granny's Flat' as a zone and Granny sadly passed away, you could rename it to 'The Hobbies Room' without having to reprogram. I can get the current names to load in to a uibuilder webpage by having a button called 'Load Current Zone Settings' (v-on:click="sendRequest"), but it would be better if the current names loaded automatically when the webpage finished loading. Is there anything like v-on:pageloaded I can use to call the function ("sendRequest") to send a message to node-red asking for the current settings? I have web-searched but didn't find anything that worked. Sorry if this is beginner's stuff, but we all have to start somewhere.

I think I just saw the answer to this today... from this section of the uibuilder docs:

Client (re)Connection (Control Message)
Is sent from Node-RED by uibuilder to the client whenever a new client connects or when an existing client re-connects (by reloading their page).

{
    "uibuilderCtrl": "client connect",  // control message type
    "cacheControl": "REPLAY",           // Cache control request type: REPLAY or CLEAR
    "serverTimestamp": "2020-09-24T12:56:13.125Z",  // Can be used in client to work out their timezone or at least time offset from the server
    "from": "server",                   // NR->Client
    "_socketId": "/extras#sct0MeMrdeS5lwc0AAAB",    // ID of client (from Socket.IO)
    "_msgid": "8d4307ce.d5e428"         // Node-RED internal msg id
}

I admin I have not used it yet, but it seems like you just need a flow connected to the second output port, that can listen for this event msg and send the necessary data back to the front end ui.

1 Like

Thank you. That may bend my head for a while :slight_smile: but I will have a play. It does seem to say that the message is sent 'from' Node-RED by uibuilder, still it should be easy to see that message if it does come out of the second port. As I say, I will experiment and come back to you. Thanks again. B

Good news and bad news! On my uibuilder nodes I only get undefined messages coming out of the second port when a client connects. So I tried importing samples that are installed when you install uibuilder and those do give 'connected' and 'ready for content' and even 'disconnected' messages:

04/10/2021, 09:19:29node: uib controls
msg : Object
object
uibuilderCtrl: "client connect"
cacheControl: "REPLAY"
serverTimestamp: "2021-10-04T08:19:29.667Z"
topic: undefined
from: "server"
_socketId: "rYkd5OdNGkX9zYpqAAAT"
_msgid: "6f0c3cdcc84f1ce0"

and:

04/10/2021, 09:19:30node: uib controls
msg : Object
object
uibuilderCtrl: "ready for content"
cacheControl: "REPLAY"
from: "client"
_socketId: "rYkd5OdNGkX9zYpqAAAT"
topic: ""
_msgid: "20bdcb898f50139f"

But the sample I based my uibuilder nodes on:
https://flows.nodered.org/flow/b69182516daf2aebc0823f965eaf6a02/in/oIlM1_y7X0GW
gives the undefined messages. So I will have to try to see the differences between the samples that do and don't work. Thanks again for the idea. B

Is your debug node is showing 'undefined' then try changing it so "show complete msg object" instead of just the default payload (or whatever you currently have set). If you are seeing a debug message show up from port 2, then there has to be SOMETHING in the msg object. Notice how the structure of the msg from the docs above does indeed have NO payload field...

Thank you, you may have just saved my sanity :-). For a couple of hours I have been comparing html and js and even css files between uibuilder flows that gave me debug data and uibuilder flows that gave me undefined. And all I had to do was switch it to 'complete message object'. I would say 'lesson learnt', but I can guarantee that I will get caught out in the future. Thank you again.
B

So hopefully you already now know that when a uibuilder client page connects to Node-RED (over socket.io), Node-RED issues a "control" message to the client:

{
    "uibuilderCtrl": "client connect",
    "serverTimestamp": "2021-10-04T19:53:38.809Z",
    "security": false,
    "_socketId": "bEZdZzHqVKcJOxBuAAAD",
    "from": "server"
}

Which you can detect and use in your client code by using this kind of function:

        uibuilder.onChange('ctrlMsg', function(msg){
            //console.info('[indexjs:uibuilder.onChange:ctrlMsg] CONTROL msg received from Node-RED server:', msg)
            app.msgCtrl = msg
            app.msgsControl = uibuilder.get('msgsCtrl')
        })

Also upon client connection, the client sends a control message to the server:

{
    "uibuilderCtrl": "ready for content",
    "cacheControl": "REPLAY",
    "from": "client",
    "_socketId": "bEZdZzHqVKcJOxBuAAAD"
}

And this appears out of the bottom output port of the node. You will note how each message is cunningly marked as to where it originates :slight_smile:

This message can be used to trigger sending of some information back to the newly connected client. For example, you will note the cacheControl property that can be used with a suitable function node to send previously cached data to newly connected clients. You will find examples of that in the library and on the WIKI.

It is probably this message that you want to use to send an initial setup message to the client so that it builds the interface for you.

Well, you missed out the important thing that you certainly will want to do at least a tutorial on and that is VueJS.

Bootstrap-vue is an extension to VueJS that enables you to get really nice looking pages with minimal boilerplate coding.

It is VueJS that will do all of the clever heavy lifting for you, bootstrap-vue will make it look nicer and provide some additional helpers.

I hope that you will be able to share your project once you have got something useful out of it because using Node-RED and uibuilder to build a generic UI is very much a hot topic at the moment.

Thank you, I got it to work though I struggled for a while. In the flow I used a Switch Node to compare the msg.uibuilderCtrl property to 'ready for content', and though I could see that it was getting a message and passing it on, I couldn't seem to get the next function node in the flow to load in the global values from file. But an inject button connected to the same function node made it work as expected. Eventually I found that I had to delete the uibuilderCtrl property from the msg object using a change node, and then everything worked OK. I guess that uibuilder receiving an unexpected uibuilderCtrl message caused issues. My inexperience with Node-Red slows me down, but I get there in the end :slight_smile:

Looks like I will have to do a beginners course on VueJS!!

And of course I am happy to share my project, however amateur it may be :blush:

B

Ah, yes - sorry, that IS in the documentation but probably rather buried. You can't send a control msg into uibuilder, it drops it. That's for safety of course. Though I thought it output a warning to at least the log?