[Fixed] binding mqtt subscribtions to node ejs, and alpine states

Issue

old Rails and php programmer that is new to js, tyring something and feel I am missing something pretty basic. I have a node server running a small webapp, express, ejs, jquery as well as alpinejs. (very exp with jquery, but learning alpinejs). I have a mqtt server running and can manipulate a couple of topics via my phone, and I can even see them in the node console (code below)

what I fail to understand is how to get, or maybe "bind" the subscription to a variable that I can "pass" into the express app so I can just show the mqtt message in the html. Im currently just trying to set things like fridgeFan = true or somehthing. My idea, I think, is to have mqtt update the alpinejs variable, hence updating the page, then viceversa…

Can someone point me in the general good direction of what im attemtping?

options={
  clientId:"node-admin",
  clean:true,
};

const express = require('express');
const app = express();
const mqtt = require('mqtt')
const client = mqtt.connect('mqtt://192.168.10.66', options)

client.on("connect",function(){
  console.log("connected");
});

client.on('message',function(topic, message, packet){
  console.log("message is "+ message);
  console.log("topic is "+ topic);
  // assume id like to bind topic and message to
  // some variable that I can pass or have access to
  // in the res.render calls below??

  // couple of things I was trying
  //document.getElementById('mqtt_div').innerHTML += topic;
  //document.querySelector('[x-data]').__x.getUnobservedData().fridgeFan = message;
});

client.subscribe("sensors/sensor1",{qos:1});


app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/public'));

app.get('/', (req, res) => {
  res.render('index', {
    title: 'Homepage'
  });
});

with the above code, I can publish to "sensors/sensor1" via a phone app, I can see it in the node console, of course not the browser console.

How can I bind the "message" to a alpinejs variable so it will update?

OR do I go a different direction and put the client.on calls elsewhere, say the ejs file? in my testings, the ejs files dont know about require mqtt

Solution

You can’t move your on message handler into the EJS files as they are only "executed" at the point you call render()

You can declare a global variable in the ExpressJS app and update fields with in it from the on('message',...) callback, you then pass this variable into the call to render() but this would mean that the page would only show the value at the time the page was loaded.

If you want live updates in the page as messages are published then you have one real option. That is to use a broker that supports MQTT over Websockets (nearly all modern brokers support this). With this you can load an MQTT client (either the Paho JavaScript client or you can use the MQTT.js client) into the page and subscribe to the topics you are interested in directly from the page. This way new messages are delivered directly to the page and you can then use what ever JavaScript framework you want to update the page.

Leave a Reply

(*) Required, Your email will not be published