Aparência
MQTT sem mistério
Objetivo desta página: entender o que viaja entre o coletor e o banco, antes de acompanhar uma medição completa. Não é preciso conhecer redes de computadores.
Por que existe uma etapa no meio?
O coletor sabe conversar com o inversor. O serviço mqtt-to-db sabe validar e gravar medições. Se um enviasse dados diretamente ao outro, os dois precisariam conhecer a conexão e o funcionamento interno um do outro. Com MQTT, o coletor publica uma mensagem em um broker; o serviço de ingestão assina as mensagens que lhe interessam.
text
inverter-to-mqtt ── publica ──▶ Mosquitto ── entrega ──▶ mqtt-to-db
publicador broker assinanteO Mosquitto é o programa que distribui as mensagens. O pacote @campus/mqtt, em packages/mqtt/, é outra coisa: código compartilhado que define e valida o formato usado pelas aplicações. O broker não substitui o PostgreSQL como histórico de medições.
Uma distinção importante
MQTT não elimina a leitura periódica do inversor. Neste projeto, o coletor ainda consulta o hardware; depois publica o resultado pelo broker. “Ler do inversor” e “enviar a medição ao restante do sistema” são duas etapas diferentes.
Endereço e conteúdo
Uma mensagem de telemetria tem duas partes que você pode imaginar como envelope e carta:
| Parte | Pergunta que responde | Exemplo fictício |
|---|---|---|
| Tópico | “Que tipo de dispositivo enviou? Qual deles?” | telemetry/solis-inverter/exemplo-01 |
| Payload | “Quando e o que foi medido?” | JSON com ts e metrics |
json
{
"ts": "2026-09-30T12:00:00Z",
"metrics": {
"power_w": 1234.5
}
}O tópico segue telemetry/{deviceType}/{externalId}. As duas partes variáveis precisam ser segmentos não vazios em kebab-case, como solis-inverter e exemplo-01. No JSON, ts é opcional; metrics é obrigatório, não pode estar vazio e associa nomes em snake_case a números finitos. Esses nomes e valores são apenas exemplos, não dados do campus.
O coletor chama publishTelemetry() em packages/mqtt/src/publisher.ts. Antes de enviar, essa função monta e valida o tópico e o payload. Na chegada, subscribeTelemetry() em subscriber.ts valida novamente. Assim, o lado que grava não precisa confiar cegamente em quem publicou.
E se a mensagem chegar duas vezes?
A publicação e a assinatura usam QoS 1, uma modalidade de entrega que pode repetir uma mensagem em certas situações. O pacote MQTT não deduplica, e a persistência atual não deve ser interpretada como garantia de uma única medição por publicação. “Entregue” também não significa, por si só, “já gravado no PostgreSQL”.
Teste rápido
Se alguém disser “o pacote @campus/mqtt é o servidor de mensagens”, o que você responderia?
Resposta: não. O servidor (broker) é o Mosquitto; @campus/mqtt é a biblioteca usada pelas aplicações para falar o mesmo contrato. Agora você pode seguir uma medição.
Base revista no código em 2026-10-06: packages/mqtt/src/contract.ts, publisher.ts, subscriber.ts; apps/inverter-to-mqtt/src/runtime.ts e apps/mqtt-to-db/src/runtime.ts.