LoRaWAN
Não existe um conector “LoRaWAN” no CMS, e não precisa existir. Um sensor LoRaWAN não fala IP: ele transmite por rádio, o gateway repassa o pacote, e quem decifra, deduplica e entrega o dado é o Network Server — ChirpStack, The Things Stack (TTN), Actility, Loriot, Kerlink. O CMS conversa com o Network Server, e todos eles publicam o dado em MQTT ou por webhook HTTP, que o CMS já recebe.
Sensor ──rádio──▶ Gateway ──▶ Network Server ──MQTT──▶ CMS (Coleta MQTT_TOPIC_SUBSCRIBER)
▲
└──MQTT── CMS (Entrega MQTT_PUBLISH, downlink)Uplink — Coleta MQTT
- Cadastre o broker do Network Server em Conexões Externas,
tipo
MQTT_BROKER, e use-o no Keep Alive MQTT da Aplicação. - Crie uma Coleta
MQTT_TOPIC_SUBSCRIBERno tópico de uplink:
| Network Server | Tópico de uplink | Broker |
|---|---|---|
| ChirpStack v4 | application/{applicationId}/device/+/event/up | O Mosquitto do próprio ChirpStack |
| The Things Stack v3 | v3/{app-id}@{tenant}/devices/+/up | {região}.cloud.thethings.network:8883 (TLS), usuário app-id@tenant, senha = API key |
MQTT é o caminho preferido em planta: é o CMS que abre a conexão, então funciona atrás de firewall. Webhook HTTP do Network Server para a API dinâmica de Coleta também serve, quando o Network Server está na nuvem e o CMS é alcançável de fora.
O payload
O sensor manda poucos bytes. O Network Server os entrega em base64 — data no ChirpStack,
frm_payload no TTS — e, se houver codec configurado para o modelo do dispositivo, também já
decodificados — object no ChirpStack, decoded_payload no TTS.
- Com codec no Network Server, o Transformador só mapeia campos. É o caminho mais simples: o codec do fabricante costuma vir pronto.
- Sem codec, o Transformador decodifica os bytes. O sandbox do Transformador não tem
atobnemBuffer, então o base64 é decodificado no próprio script — o cenário de exemplo do repositório (scripts/cenario-lorawan/transformador-normaliza-uplink.js) traz o decodificador pronto.
O Transformador vai no encaminhamento da Coleta (ou na Entrega de destino), não na Coleta: a
Coleta em si entrega o JSON cru. E o {{alias}} do tópico de uma Entrega MQTT_PUBLISH lê o
payload antes do Transformador — para montar um tópico por dispositivo, use os campos do JSON
original (deviceInfo.devEui no ChirpStack, end_device_ids.device_id no TTS).
Guarde também os metadados de rádio: rssi, snr, o gateway que ouviu e o fCnt. Um fCnt que
pula é pacote perdido; um que volta a zero é rejoin — e os dois são diagnóstico de campo que não
aparece em nenhum outro lugar.
Downlink — Entrega MQTT_PUBLISH
Para mandar comando ao sensor, a Entrega publica no tópico de downlink do Network Server:
| Network Server | Tópico | Corpo |
|---|---|---|
| ChirpStack v4 | application/{app}/device/{devEui}/command/down | { "devEui": "…", "fPort": 10, "confirmed": true, "data": "<base64>" } |
| The Things Stack v3 | v3/{app}@{tenant}/devices/{device-id}/down/push | { "downlinks": [{ "f_port": 10, "frm_payload": "<base64>", "confirmed": true }] } |
A Entrega dá certo quando o Network Server aceita o comando, não quando ele chega no sensor. Um
dispositivo classe A só abre a janela de recepção depois de transmitir: o downlink espera o
próximo uplink, que pode levar minutos ou horas. Para saber se chegou, assine também
…/event/txack e …/event/ack (ChirpStack) ou …/down/sent e …/down/ack (TTS) — o ack só
existe para downlink com confirmed: true.
Testar sem rede LoRaWAN
O LoRaWAN Simulator sobe um broker dentro do CMS e
publica nele o que o ChirpStack v4 ou o TTS v3 publicaria, com sensores que mandam uplink sozinhos e
aceitam downlink classe A. O script scripts/seed-cenario-lorawan.mjs monta o cenário completo em
cima dele: Aplicação LORAWANSIM, Coletas dos dois formatos, Transformador de normalização e as
Entregas de downlink LW_DOWN_CS e LW_DOWN_TTS, acionadas por
curl -k -X POST https://localhost/api/LW_ENTREGA/LW_DOWN_CS \
-H 'Content-Type: application/json' -H 'x-api-token: <token da Aplicação LORAWANSIM>' \
-d '{"devEui":"70b3d5e75e000101","aplicacaoNs":"5f2b7c1e-8d4a-4b6f-9c3e-1a2b3c4d5e6f","intervaloSegundos":20}'