====== DigitalSTROM MQTTG Gateway in a Docker container ====== this is how i set up Chriss Gross' [[https://github.com/cgHome/mqtt-dss-bridge|MQTT bridge]] to run inside a node docker container. i have also slightly modified his script to use authentication and to allow setting the ''qos'' in the config file as well. in addition to that i have written a wrapper script in bash that will constantly (as in every second) check when the last contact was established to the dss server. if that's too long ago, it will restart the bridge. this was necessary because otherwise the bridge script would not recognize when it had lost the connection to the dss server (i.e. because of a network outage or because the dss has been restarted or whatever other reason there might be) and it would need a manual intervention. this script fixed this issue for me pretty reliably. on a personal note i want to add: kudos to node.js for still being able to run a script that hasn't been touched for 9 years without modifying a single line of code! this actually makes the need to dockerize this quite questionable. however, i still perfer it this way in my current setup :) so here is how i set it up: # create ./app directory with uid and gid 1000 first services: node: build: ./build restart: always user: 1000:1000 working_dir: /app environment: - NODE_ENV=production volumes: - ./app:/app mkdir ./app chown 1000.1000 app mkdir ./build #!/bin/bash USERNAME="myuser" PASSWORD="mysecret" MQTT_SERVER="mqtt.psuter.ch" if [ -z "$(ls -A /app)" ]; then echo "installing dss mqtt bridge (see https://github.com/cgHome/mqtt-dss-bridge)" cd /app npm install --save mqtt-dss-bridge echo "IMPORTANT: configure the bridge by editing /app/node_modules/mqtt-dss-bridge/config.js" echo "installation completed" fi echo "Starting DSS to MQTT bridge" # start the bridge in the background cd /app node /app/node_modules/mqtt-dss-bridge/index.js 2>&1 & PID=$! echo "DSS Bridge started with PID $PID" # start a loop to monitor the status every second errcntr=0 lastUpdate=999 while true; do lastUpdate=$(( \ $(date +%s)\ -\ $(date -d "$(\ mosquitto_sub -h $MQTT_SERVER -u $USERNAME -P $PASSWORD -t dss/state/lastDiscovered -C 1 | \ sed -E -e 's/"([0-9]{4}-[0-9]{2}-[0-9]{2})T([0-9]{2}:[0-9]{2}:[0-9]{2}).*$/\1 \2Z/'\ )" +%s)\ )) if [ 10 -lt $lastUpdate ]; then if [ $errcntr -lt 10 ]; then let errcntr++ echo "DSS Bridge state is too old (last updated $lastUpdate seconds ago, max 10 allowed). This was failure $errcntr out of 10 accepted failures" else echo "DSS bridge state is still too old ($lastUpdate seconds) after 10 retries. killing mqtt-dss-bridge (pid $PID) and exit with error status 1" kill $PID exit 1 fi fi sleep 1 done obviously you need to adjust the three variables at the top of the script to match your setup chmod 755 build/startup.sh FROM node:22-bookworm ARG DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Zurich # mqtt client RUN apt-get update && apt-get install -y mosquitto-clients #RUN npm install --save mqtt-dss-bridge COPY startup.sh /startup.sh CMD /startup.sh docker compose build docker compose up press ''ctrl+C'' to stop the app again, then edit the config file nano ./app/node_modules/mqtt-dss-bridge/config.js now your setup might be different, but i wanted to be able to use a password authentication for mqtt and i wanted to set ''qos'' to ''2'', by default this is hardcoded to ''1''. so in the settings in the ''var config='' section i edited the ''client'' attribute to look like this: // MQTT-Client client: { url: 'mqtt://mqtt.psuter.ch:1883', baseTopic: dssTopic, qos: 2, username: 'myuser', password: 'mysecret' }, again of course with the correct username and password. next i had to slightly modify the script in ''app/node_modules/mqtt-dss-bridge/lib/dss.js'' starting from ''line 23'' i have added the ''qos'' setting as well as the ''username'' and ''password'' settings, so this section now looks like this: var clientSettings = { keepalive: 10, clientId: config.name, will: { topic: config.client.baseTopic + '/state/online', payload: new Buffer('{"$value": "false"}'), qos: config.client.qos, retain: true }, username: config.client.username, password: config.client.password }; with all this done, we can now start the container and hope for it to run ;) docker compose up -d