Mqtt Werte in Ui-Builder anzeigen

Hallo zusammen,
da ich noch ein absoluter Anfänger bin. Möchte ich in diesem Forum um Rat fragen.
Ich verwende einen ESP32 Modul mit einem BME688 Sensor von Bosch, welcher die Werte per MQTT an einen Raspberry CM5 liefert. Diese Werte kann ich auch in Node-Red auslesen und sehe sie auch im Debug-Fenster.
Jetzt versuche ich die Werte über Ui-Builder an eine HTML Seite anzeigen zu lassen. Was leider nicht funktioniert.
Anbei meine Dateien die ich verwende:
index.html

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <title>MQTT Dashboard</title>
    <!-- uibuilderfe lädt die benötigte Front-End-Bibliothek automatisch -->
    <script src="./uibuilder/vendor/uibuilder/uibuilderfe.min.js"></script>
</head>
<body>

    <h1>Live MQTT Daten</h1>
    <div>
        <!-- Hier wird der MQTT-Wert eingefügt -->
        Temperatur: <span id="Temperature">Warte auf Daten...</span> °C
    </div>

    <!-- Verknüpfung zur Logik-Datei -->
    <script src="./index.js"></script>
</body>
</html>

index.js

// Initialisiere uibuilder Verbindung
uibuilder.start()

// Höre auf eingehende Nachrichten aus Node-RED
uibuilder.onChange('msg', function(msg) {
    // Überprüfen, ob die Nachricht existiert
    if (msg) {
        console.log('Nachricht empfangen:', msg);

        // Prüfen, ob die Nachricht vom richtigen MQTT-Topic kommt (optional)
        if (msg.topic === 'payload.BME680.Temperature') {
            // HTML-Inhalt mit dem MQTT-Payload überschreiben
            document.getElementById('Temperature').innerText = msg.payload;
        }
    }
});

Über jeden Hinweis oder Tipp wäre ich sehr dankbar :hugs:
Grüße
Guido

I would check the console.log to verify the msg

I would normally expect the msg.topic from MQTT to be something like 'BME688/Temperature' with the msg.payload to be either a number or text (depending on what you are sending from the ESP32)

Hi,

You are using outdated code I'm afraid and your link to the client library is incorrect. You are also missing a link to the socket.io client code.

If you want to use the old-style library (which I really don't recommend), where your index.js line is, amend that to the following and remove the incorrect link in the head section:

    <script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
    <script src="./uibuilderfe.min.js"></script>
    <script src="./index.js"></script>

I also think there is an error in your JavaScript as well if (msg.topic === 'payload.BME680.Temperature') - 'payload.BME680.Temperature' does not look like a message topic, rather it is content from the message.


However, a much better solution is to move to the newer version of the client that we switched to as a default back in v6.0 of UIBUILDER (we are now in v7.7).

The best approach is for you to add a new test uibuilder node to your Node-RED instance - it will deploy the latest default template which you can then adapt.

With the this version, there isn't as much boilerplate code required and, you may not even need any of your own JavaScript since uibuilder now has simpler methods for showing output from Node-RED.

If we assume that your msg.topic is "BME680-Temperature", then you can automatically display it using the following HTML:

<!doctype html>
<html lang="en"><head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" href="../uibuilder/images/node-blue.ico">

    <title>Live MQTT Daten - Node-RED UIBUILDER</title>
    <meta name="description" content="Node-RED UIBUILDER - Live MQTT Daten">

    <!-- Your own CSS (defaults to loading uibuilders css)-->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all">

    <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / -->
    <script defer src="../uibuilder/uibuilder.iife.min.js">/* THE UIBUILDER LIBRARY MUST BE IN THE HTML! DO NOT REMOVE */</script>
    <!-- <script defer src="./index.js">/* OPTIONAL: Put your custom code in that */</script>-->
    <!-- #endregion -->

</head><body>
    <header>
        <h1 class="with-subtitle">Live MQTT Daten</h1>
        <div role="doc-subtitle">Using UIBUILDER for Node-RED</div>
    </header>

    <main>
        <article>
            <!-- Hier wird der MQTT-Wert eingefügt -->
            Temperatur:
            <span id="Temperature" uib-topic="BME680-Temperature">
                Warte auf Daten...
            </span> °C
        </article>
    </main>
</body></html>

See the following in the docs for details of the easy display methods:

Hallo,
danke für die schnelle Antwort :hugs:
Leider erhalte ich nicht das gewünschte Ergebnis. Meine Version von UI-Builder ist 7.7.4.

Was mir aufgefallen ist, dass einige Verknüpfungen HTML-Code bei mir nicht vorhanden sind. Ist da was bei der Installation schiefgelaufen?

Have you tried a new uibuilder node using the default "blank" template? Can you confirm whether that works or not?

Haben Sie einen neuen Uibuilder-Knoten mit der Standardvorlage „leer“ ausprobiert? Können Sie bestätigen, ob das funktioniert oder nicht?

(auto-translation)

Yes, I’m using the blank ‘Minimal template’ (default).
This is what the result looks like.

OK, and if you check the browser dev console, are there any errors?

If you check the Network tab you should also see a line like this:
image
Which confirms that the 2-way comms channel with Node-RED has correctly started. Also, there should not be any "404" status errors on that page.

Is that what you mean? There are no Errors.

OK, that's good. So we know that the uibuilder client is working correctly.

Did you leave the div with the id "more" in your HTML file? If not, please add the following somewhere in the <body>:

<div id="more" uib-topic="more"></div>

This is simply a convenience since many of uibuilder's example flows and documentation use it.

Now use an inject node to send some data:


The topic is important and must match the uib-topic in the html.

You should get something like this:

That will show you that everything is working as expected. If your part isn't working, perhaps you could share a simplified flow and the html file.

I’ve now created a new template and set up an inject node using the details you provided. It’s working now.

Excellent. So now going back to my previous suggested code here, you should be able to change the inject to have the topic "BME680-Temperature" and it should appear on the page with no front-end JavaScript required.

Just so I understand. Should I adjust the Inject node? As I’m receiving the values from an MQTT broker, I thought I’d need to use an MQTT node there...

The inject node is just for testing. Once you can see something appearing on the page, then you can wire in your MQTT-in node. Just remember to change the topic string in your HTML if it is different to the test.

Just as I thought. Now I’ve got another problem understanding this. I’m not really sure what the right approach is when selecting the topic string

Ah, I see, you have an object as your payload. Sorry, I should have realised that.

OK, well we know that uibuilder is working correctly. So now we have to uncomment the line in the HTML that activates the index.js file. And then in that file you can do this:

uibuilder.onTopic('BME688Bad/SENSOR', (msg) => {
  // Be careful with the case here, JavaScript is generally case sensitive
  $('#Temperature').innerText = msg.payload.BME680.Temperature
})

You could also use a single onChange function like you had before but then you would likely need to add in some code to differentiate between topics. But either way is good.

Got to help the wife with dinner just now - will be back online later.

Ok, i have change it, this is the result

[object Object] is the string that JavaScript outputs when you feed a JS object into something that needs a plain string.

This tells us that you haven't quite got the msg.payload.BME680.Temperature part correct. If you add the following to your JavaScript, you will see what the issue is:

uibuilder.onTopic('BME688Bad/SENSOR', (msg) => {
  // Be careful with the case here, JavaScript is generally case sensitive
  $('#Temperature').innerText = msg.payload.BME680.Temperature
  // ADD THIS (or use whatever you are feeding to the line above:
  console.log(msg.payload.BME680.Temperature)
})

I was a bit rushed yesterday and I forgot to say that $('#Temperature') is a uibuilder helper function which is similar to jQuery or what is available in the browser dev console. it is shorthand for document.querySelector('#Temperature'). You can use the full version if you prefer - I added it because I can never remember the querySelector name and always have to look it up!

this is the error Message

image

I’ve checked it again. Now I’m getting the correct value in the console

It’s only on the website that I still get [object Object]

Can you share your JavaScript please?