question

joshuaattridge avatar image
joshuaattridge asked

MQTT JS/TS Implementation

Hello All!

I am attempting to connect to the Victron MQTT broker using typescript using this package mqtt - npm (npmjs.com)

This is the code I currently have (I have replaced some parts with * to hide personal information but I can assure that these details are correct):

const mqtt = require('mqtt')
const TRUSTED_CA_LIST = `-----BEGIN CERTIFICATE-----
***
***
***
***
***
-----END CERTIFICATE-----`

function _get_vrm_broker_url(vrm_id: string) {
    var sum = 0
    for (var i = 0; i < vrm_id.length; i++) {
        sum += vrm_id.charCodeAt(i)
    }
    var broker_index = sum % 128
    return "mqtt" + broker_index + ".victronenergy.com"
}

const client = mqtt.connect('mqtts://' + _get_vrm_broker_url('*****'), {
    username: '*****',
    password: '*****',
    ca: TRUSTED_CA_LIST,
})

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

However when I test this in the browser I get the following error message:

WebSocket connection to 'wss://mqtt91.victronenergy.com/' failed: Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID

I hope someone can tell me where I'm going wrong and lead me in the right direction,

thank you for your time!

Josh

MQTTjavascript
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

5 Answers
gone-sailing avatar image
gone-sailing answered ·

Try MQTT not WS as the protocol.

1 comment
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

joshuaattridge avatar image joshuaattridge commented ·

Hi,

thanks for replying so quickly,

I tried this and I get the same error, I added *protocolId: 'MQTT'* as one of the options on the mqtt.connect call.

Also I believe as this is coming from a browser you have to use web sockets rather than direct MQTT, but please correct me if I'm wrong.

0 Likes 0 ·
gone-sailing avatar image
gone-sailing answered ·

There is nothing in the dbus-Mqtt documentation to suggest that web sockets is enabled in the VRM Mqtt servers. It seems it’s just MQTT over ssl.

https://github.com/victronenergy/dbus-mqtt


2 comments
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

joshuaattridge avatar image joshuaattridge commented ·

No it doesn't however the Victron web-app uses websockets victronenergy/venus-html5-app: HTML5 App including Javascript library that communicates with Venus OS over MQTT websockets (github.com) which suggests it is possible.

0 Likes 0 ·
gone-sailing avatar image gone-sailing joshuaattridge commented ·
I believe that web app communicates with the MQTT server on your own local Venus GX device. You are trying to connect to Victron’s VRM servers.
0 Likes 0 ·
joshuaattridge avatar image
joshuaattridge answered ·

So I finally figured out how to get this working.

If you want to have a MQTT connection Victron broker using a browser (Javascript/Typescript) then you need to have the following parameters:

host: wss://webmqtt***.victronenergy.com

username: YOURVRMUSERNAME

password: YOURVRMPASSWORD

I found out that Victron have another broker address that works with web sockets so on the address rather than having 'mqtt.' you need to have 'webmqtt.' I hope you find this useful please look at this programming example below:

const mqtt = require('mqtt')

function _get_vrm_broker_url(vrm_id: string) {
    var sum = 0
    for (var i = 0; i < vrm_id.length; i++) {
        sum += vrm_id.charCodeAt(i)
    }
    var broker_index = sum % 128
    return "webmqtt" + broker_index + ".victronenergy.com"
}

const client = mqtt.connect('wss://' + _get_vrm_broker_url('YOURVRMDEVICEID'), {
    username: 'YOURVRMUSERNAME',
    password: 'YOURVRMPASSWORD',
})

client.on('connect', function () {
    console.log('connected')
    client.subscribe('#', function (err) {
        if (!err) {
            console.log('no error')
        }
    })
})
client.on('message', function (topic, message) {
    // message is Buffer
    console.log(topic.toString(), message.toString())
    client.end()
})

And thanks to @gone-sailing for the help you provided :D

2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

taylortops avatar image
taylortops answered ·

Could you please show how you're handling the keepalive.

2 comments
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

joshuaattridge avatar image joshuaattridge commented ·

Yes of course.

So on the connection I have added a function that will loop every 5 seconds and publish to the keep alive topic

client.on('connect', function () {
  (function theLoop() {
    setTimeout(() => {
      client.publish('R/YOURVRMDEVICEID/keepalive', '')
      theLoop();
    }, 5000);
  })();
})
0 Likes 0 ·
taylortops avatar image taylortops joshuaattridge commented ·
Many Thanks. I found that 55secs was a nice interval.
0 Likes 0 ·
goups avatar image
goups answered ·

As a side note, here are the settings to connect to the WebSocket with SSLcapture-decran-le-2024-03-05-a-133310.png


Is there a way to connect without SSL ? Which port ?


2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

Related Resources

Victron MQTT readme

Additional resources still need to be added for this topic