O gateway zwave-js-ui MQTT publica cada valor Z-Wave, de sensores de porta a níveis de dimmer, como mensagens MQTT que qualquer dashboard, script ou ferramenta de automação pode usar. Neste guia você vai rodar o Z-Wave JS UI no Docker, configurar os ajustes de MQTT e do gateway, escrever valores de volta com topics /set e encaminhar os dados para um broker na nuvem com TLS.
O que o gateway MQTT do Z-Wave JS UI faz
O Z-Wave JS UI (antigo zwavejs2mqtt) envolve o driver Z-Wave JS em uma interface web para incluir dispositivos, fazer o heal da rede e editar parâmetros de configuração. Ele expõe a rede de duas formas: um servidor WebSocket, usado pela integração Z-Wave JS do Home Assistant, e um gateway MQTT, que publica valores em um broker e aceita escritas vindas dele.
O lado MQTT é o que você quer quando os consumidores não são o Home Assistant: fluxos do Node-RED, o Telegraf alimentando um banco de dados de séries temporais, um backend próprio ou um dashboard remoto. Cada um deles simplesmente assina topics no broker. Se o papel do broker é novidade para você, leia primeiro o que um broker MQTT faz.
Passo 1: rodar o Z-Wave JS UI
O Docker é a forma mais comum de executá-lo. Descubra o caminho estável do seu stick Z-Wave com ls -l /dev/serial/by-id/ e inicie o contêiner:
docker run -d --name zwave-js-ui --restart unless-stopped \
-p 8091:8091 -p 3000:3000 \
--device=/dev/serial/by-id/usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge-if00-port0:/dev/zwave \
-v zwave-config:/usr/src/app/store \
zwavejs/zwave-js-ui:latest
Substitua o caminho do dispositivo pelo seu. Abra http://<host>:8091, vá em Settings e depois em Z-Wave, defina a porta serial como /dev/zwave, gere as chaves de segurança e salve. Inclua um ou dois dispositivos antes de seguir em frente, para que haja algo a publicar.
Passo 2: entender a estrutura de topics
Os valores são publicados seguindo este padrão:
<prefix>/<location>/<node name>/<command class>/<endpoint>/<property>
Para um dimmer chamado desk_lamp na localização office, com o prefixo zwave, o nível atual fica em zwave/office/desk_lamp/38/0/currentValue, onde 38 é a command class Multilevel Switch. Para alterá-lo, publique no mesmo topic com /set no final, normalmente em targetValue:
| Finalidade | Topic | Payload |
|---|---|---|
| Atualização de valor | zwave/office/desk_lamp/38/0/currentValue |
{"time":1760600000000,"value":60} |
| Escrever um valor | zwave/office/desk_lamp/38/0/targetValue/set |
{"value":100} |
| Status do nó | zwave/office/desk_lamp/status |
true / false ou JSON |
| Status do gateway | zwave/_CLIENTS/ZWAVE_GATEWAY-<name>/status |
true / false |
| Chamada de API | zwave/_CLIENTS/ZWAVE_GATEWAY-<name>/api/<api>/set |
{"args":[...]} |
O topic de status do gateway é especialmente útil: ele informa aos consumidores remotos se o próprio Z-Wave JS UI está conectado, independentemente de qualquer dispositivo.
Passo 3: testar o gateway zwave-js-ui MQTT no servidor MQTT público
Antes de montar algo definitivo, comprove que o gateway funciona com o servidor MQTT público (gratuito) em broker.connectmq.com. Ele aceita conexões anônimas com qualquer client ID único. Dois detalhes importam aqui:
- O Z-Wave JS UI monta seu client ID como
ZWAVE_GATEWAY-<Name>, então o campo Name precisa ser único. Use um sufixo aleatório. - A área pública permite no máximo oito níveis de topic. Um prefixo longo somado a localização, nome do nó, command class, endpoint, propriedade e
/setultrapassa isso facilmente, então use um prefixo curto e desative as localizações nos topics.
Em Settings e depois MQTT, informe:
| Campo | Valor |
|---|---|
| Name | zw-h2k8tp |
| Host url | mqtts://broker.connectmq.com |
| Port | 8883 |
| Reconnect period | 5000 |
| Prefix | connectmq/demo/h2k8tp |
| QoS | 1 |
| Retain | ativado |
| Clean | ativado |
| Auth | desativado |
| Allow self signed certs | desativado |
Depois, em Settings e então Gateway, escolha:
- Type: ValueId topics.
- Payload type: JSON Time-Value.
- Use nodes name instead of numeric nodeIDs: ativado.
- Ignore location: ativado.
Salve e assine a partir de um terminal:
mosquitto_sub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
-i watch-h2k8tp -t 'connectmq/demo/h2k8tp/#' -v
Você verá o status do gateway e depois os valores de cada nó. Acione a luminária:
mosquitto_pub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
-i send-h2k8tp -t 'connectmq/demo/h2k8tp/desk_lamp/38/0/targetValue/set' \
-m '{"value":40}'
Alguns instantes depois, currentValue é atualizado para 40. Lembre-se de que a área pública é visível para todos; use-a apenas para testes inofensivos, nunca para dados de produção, fechaduras, alarmes ou portões de garagem.
Passo 4: configuração de produção com uma bridge local
Brokers privados emitem credenciais junto com um client ID fixo. A ConnectMQ vincula o client ID ao usuário e à senha emitidos, e o Z-Wave JS UI sempre adiciona o prefixo ZWAVE_GATEWAY- ao seu client ID. Na prática, isso significa que o Z-Wave JS UI não consegue apresentar exatamente o ID emitido.
A solução limpa é uma pequena bridge Mosquitto ao lado do Z-Wave JS UI. O Z-Wave JS UI se conecta ao Mosquitto local sem TLS, e o Mosquitto encaminha os topics zwave/# para o broker na nuvem usando o client ID, o usuário e a senha emitidos, com TLS. De bônus, as automações locais continuam funcionando durante uma queda de internet.
docker-compose.yml:
services:
mosquitto:
image: eclipse-mosquitto:2
restart: unless-stopped
volumes:
- ./mosquitto.conf:/mosquitto/config/mosquitto.conf:ro
- /etc/ssl/certs:/etc/ssl/certs:ro
zwave-js-ui:
image: zwavejs/zwave-js-ui:latest
restart: unless-stopped
ports:
- "8091:8091"
- "3000:3000"
devices:
- /dev/serial/by-id/usb-Silicon_Labs_CP2102N_USB_to_UART_Bridge-if00-port0:/dev/zwave
volumes:
- zwave-config:/usr/src/app/store
depends_on:
- mosquitto
volumes:
zwave-config:
mosquitto.conf:
listener 1883
allow_anonymous true
connection connectmq
address broker.connectmq.com:8883
remote_clientid YOUR_CLIENT_ID
remote_username YOUR_USERNAME
remote_password YOUR_PASSWORD
bridge_capath /etc/ssl/certs
bridge_protocol_version mqttv311
try_private false
cleansession true
topic zwave/# both 1
O listener local só é acessível dentro da rede do Compose, porque a porta 1883 não é publicada no host. No Z-Wave JS UI, altere os ajustes de MQTT para Host url mqtt://mosquitto, Port 1883, Prefix zwave e Auth desativado. Você pode desativar novamente o Ignore location, já que brokers privados não estão sujeitos ao limite público de oito níveis.
O try_private false é importante: ele desativa um handshake de bridge específico do Mosquitto que outros brokers não entendem. O topic zwave/# both 1 encaminha nas duas direções, de modo que as mensagens /set vindas da nuvem chegam ao Z-Wave JS UI.
Consumindo dados Z-Wave remotamente
Agora qualquer cliente MQTT com credenciais próprias pode ler a rede de qualquer lugar. Um consumidor mínimo em Python (paho-mqtt 2.x) que registra sensores de porta e o status do gateway:
import json
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, reason_code, properties):
client.subscribe("zwave/_CLIENTS/+/status", qos=1)
client.subscribe("zwave/+/48/0/+", qos=1) # command class Binary Sensor
def on_message(client, userdata, msg):
try:
data = json.loads(msg.payload)
value = data["value"] if isinstance(data, dict) else data
except ValueError:
value = msg.payload.decode()
print(msg.topic, "->", value)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="YOUR_CLIENT_ID")
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set()
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 8883, keepalive=60)
client.loop_forever()
Use um conjunto de credenciais separado para este consumidor; ele não pode compartilhar o client ID da bridge.
Checklist de solução de problemas
- O status do gateway continua
false- verifique o esquema da host url (mqtt://vsmqtts://) e a combinação de porta: 1883 sem TLS, 8883 com TLS. - As escritas não fazem nada - publique em
targetValue/set, não emcurrentValue, e envie JSON com um campovalue. - Alguns topics nunca aparecem no servidor MQTT público - eles passam de oito níveis. Encurte o prefixo ou ignore a localização.
- A bridge conecta e depois cai - outro cliente está usando o mesmo client ID emitido.
- Os valores chegam como objetos JSON enormes - o tipo de payload está definido como "Entire ValueId Object"; troque para JSON Time-Value ou Just value.
A documentação oficial do Z-Wave JS UI lista todos os nomes de API e opções do gateway.
Guias relacionados de casa inteligente
O Z-Wave raramente vive sozinho. O guia de broker na nuvem para Zigbee2MQTT aplica o mesmo padrão remoto ao Zigbee, e o guia de rtl_433 com MQTT adiciona sensores baratos de 433 MHz. Uma estrutura de topics MQTT para casa inteligente consistente mantém tudo organizado, e o guia de automação IoT mostra como as peças se combinam.
Coloque sua rede Z-Wave online com a ConnectMQ
Um broker MQTT gerenciado dá à sua bridge um endpoint estável e protegido por TLS sem que você precise manter um servidor na internet. A ConnectMQ oferece MQTT 3.1.1 e 5.0, um explorador de topics em tempo real para conferir os topics Z-Wave e regras de alerta por limite para valores como temperatura ou nível de bateria. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito.
Perguntas frequentes
Qual client ID o Z-Wave JS UI usa para MQTT?
Ele usa ZWAVE_GATEWAY- seguido do Name definido nos ajustes de MQTT. Deixe o nome único para que dois gateways nunca compartilhem um client ID.
Como altero um valor Z-Wave via MQTT?
Publique um JSON como {"value":100} no topic do valor com /set no final, normalmente .../38/0/targetValue/set. O novo valor aparece no topic currentValue.
Preciso do gateway MQTT se uso o Home Assistant?
Não necessariamente. A integração Z-Wave JS do Home Assistant usa o servidor WebSocket; o gateway MQTT serve para outros consumidores, como Node-RED, bancos de dados ou dashboards remotos.
Por que usar uma bridge Mosquitto em vez de conectar diretamente?
Porque o Z-Wave JS UI adiciona um prefixo ao seu client ID, ele não consegue usar um client ID emitido que o broker vincula às credenciais. A bridge apresenta o ID exato e ainda mantém o tráfego local funcionando offline.



