O monitoramento de inversor solar via MQTT liberta seus dados de produção do app do fabricante e os torna disponíveis em tempo real para dashboards, automação residencial e lógicas de deslocamento de carga. Neste tutorial você vai ler potência, energia e status de um inversor usando o padrão SunSpec Modbus TCP com Python, publicar um JSON limpo em um broker a cada poucos segundos e entender as armadilhas que derrubam a maioria das primeiras tentativas. Rotas alternativas por APIs HTTP locais e RS485 também são abordadas.
Três Formas de Extrair Dados de um Inversor
Os portais dos fabricantes servem para uma olhada mensal, mas costumam atualizar devagar e dependem da internet. O acesso local é mais rápido, funciona offline e é o que você quer para automações como ligar uma bomba de calor com o excedente.
| Método | Inversores típicos | Vantagens | Desvantagens |
|---|---|---|---|
| SunSpec Modbus TCP | Muitos inversores string das principais marcas | Mapa de registradores padronizado, apenas na LAN, rápido | Muitas vezes precisa ser ativado nas configurações do instalador |
| API HTTP local do fabricante | Algumas marcas expõem JSON na LAN | Fácil de ler com qualquer cliente HTTP | Diferente para cada fabricante, pode exigir tokens |
| Modbus RTU via RS485 | Muitos inversores híbridos e de baixo custo | Funciona sem porta de rede | Exige um adaptador RS485 e o mapa de registradores do fabricante |
O SunSpec é o melhor ponto de partida quando o seu inversor o suporta, porque o mesmo código funciona entre marcas. A SunSpec Alliance define "modelos": blocos de registradores com layout fixo. Os modelos de inversor 101 (monofásico), 102 (fase dividida) e 103 (trifásico) compartilham o mesmo layout de campos, e é nisso que o código abaixo se apoia.
Ativando o Modbus TCP no Inversor
Cada marca esconde essa configuração de um jeito, mas o padrão é o mesmo:
- Dê ao inversor um IP fixo com uma reserva de DHCP.
- No menu do instalador ou de comissionamento, ative o Modbus TCP (às vezes chamado de "SunSpec" ou "Modbus slave").
- Anote a porta (quase sempre 502) e o unit ID (geralmente 1, às vezes 126 ou outro valor).
- Escolha o formato de registradores SunSpec / float ou int+SF se o inversor perguntar; este guia usa o formato inteiro com fator de escala, que é o mais amplamente suportado.
- Se o inversor tiver uma opção "somente leitura" para o Modbus, ative-a. Você só precisa ler.
Alguns inversores aceitam apenas um cliente Modbus TCP por vez. Se um gerenciador de energia ou um controlador de wallbox já estiver conectado, seu script pode ser recusado ou pode derrubar o outro cliente, então defina qual sistema é dono da conexão.
Como Funcionam os Registradores SunSpec
Um dispositivo SunSpec começa com o marcador SunS em um endereço base, geralmente 40000. Depois do marcador vem uma cadeia de modelos, cada um começando com um ID de modelo e um comprimento. Você percorre a cadeia até encontrar o modelo 101, 102 ou 103 e então lê os campos em offsets fixos:
| Offset no modelo | Campo | Tipo | Significado |
|---|---|---|---|
| 2 | A | uint16 | Corrente CA, escalada por A_SF (offset 6) |
| 10 | PhVphA | uint16 | Tensão da fase A, escalada por V_SF (offset 13) |
| 14 | W | int16 | Potência CA, escalada por W_SF (offset 15) |
| 16 | Hz | uint16 | Frequência, escalada por Hz_SF (offset 17) |
| 24–25 | WH | acc32 | Energia acumulada em Wh, escalada por WH_SF (offset 26) |
| 31 | DCW | int16 | Potência CC, escalada por DCW_SF (offset 32) |
| 33 | TmpCab | int16 | Temperatura do gabinete, escalada por Tmp_SF (offset 37) |
| 38 | St | enum16 | Estado de operação (4 = MPPT, produzindo) |
Os offsets contam a partir do registrador do ID do modelo. Cada valor é multiplicado por 10 elevado ao seu fator de escala com sinal, então um W bruto de 51234 com W_SF igual a -1 significa 5123,4 W. Registradores não implementados retornam 0x8000 (com sinal) ou 0xFFFF (sem sinal) e devem ser ignorados.
O Publicador em Python
Instale as bibliotecas:
pip install "paho-mqtt>=2.0" "pymodbus>=3.7"
O script encontra a base SunSpec, percorre os modelos, lê o bloco do inversor e publica JSON. Ele usa primeiro o servidor MQTT público (gratuito), com um prefixo aleatório, porque essa área pode ser lida por todos e serve apenas para testes.
import json
import time
import uuid
import paho.mqtt.client as mqtt
from pymodbus.client import ModbusTcpClient
INVERTER_IP = "192.168.1.60"
INVERTER_PORT = 502
POLL_SECONDS = 10
PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:8]}/solar/inverter1"
STATE_NAMES = {1: "off", 2: "sleeping", 3: "starting", 4: "mppt",
5: "throttled", 6: "shutting_down", 7: "fault", 8: "standby"}
def s16(v):
return None if v == 0x8000 else (v - 0x10000 if v & 0x8000 else v)
def u16(v):
return None if v == 0xFFFF else v
def scaled(value, sf):
if value is None or sf is None:
return None
return round(value * (10 ** sf), 3)
def kwh(wh_raw, sf):
if not wh_raw or sf is None: # valor acc32 igual a 0 significa não implementado
return None
return round(wh_raw * (10 ** sf) / 1000, 3)
def find_inverter_model(client):
for base in (40000, 39999, 50000, 0):
rr = client.read_holding_registers(base, count=2)
if rr.isError() or rr.registers != [0x5375, 0x6E53]: # "SunS"
continue
addr = base + 2
for _ in range(30):
rr = client.read_holding_registers(addr, count=2)
if rr.isError():
break
model_id, length = rr.registers
if model_id == 0xFFFF:
break
if model_id in (101, 102, 103):
return addr, length, model_id
addr += 2 + length
raise RuntimeError("No SunSpec inverter model found - check Modbus settings and unit ID")
def read_inverter(client, addr, length):
rr = client.read_holding_registers(addr, count=length + 2)
if rr.isError():
raise IOError(rr)
r = rr.registers
wh_raw = (r[24] << 16) | r[25]
return {
"ac_power_w": scaled(s16(r[14]), s16(r[15])),
"ac_current_a": scaled(u16(r[2]), s16(r[6])),
"ac_voltage_v": scaled(u16(r[10]), s16(r[13])),
"frequency_hz": scaled(u16(r[16]), s16(r[17])),
"energy_total_kwh": kwh(wh_raw, s16(r[26])),
"dc_power_w": scaled(s16(r[31]), s16(r[32])),
"temp_c": scaled(s16(r[33]), s16(r[37])),
"state": STATE_NAMES.get(r[38], str(r[38])),
}
mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"solar-{uuid.uuid4().hex[:6]}")
mq.will_set(f"{PREFIX}/status", "offline", qos=1, retain=True)
mq.connect("broker.connectmq.com", 1883, keepalive=60)
mq.loop_start()
mq.publish(f"{PREFIX}/status", "online", qos=1, retain=True)
print("Publishing to", PREFIX)
mb = ModbusTcpClient(INVERTER_IP, port=INVERTER_PORT, timeout=3)
model_addr = model_len = None
while True:
try:
if not mb.connected:
mb.connect()
if model_addr is None:
model_addr, model_len, model_id = find_inverter_model(mb)
print(f"Found SunSpec model {model_id} at {model_addr}")
data = read_inverter(mb, model_addr, model_len)
data["ts"] = int(time.time())
mq.publish(f"{PREFIX}/telemetry", json.dumps(data), qos=1, retain=True)
print(data)
except Exception as exc:
print("Read failed:", exc)
mb.close()
model_addr = None
time.sleep(POLL_SECONDS)
Se o seu inversor usa um unit ID diferente de 1, passe-o em cada leitura com o parâmetro device_id (chamado slave em versões mais antigas do pymodbus). Acompanhe a saída de outra máquina:
mosquitto_sub -h broker.connectmq.com -p 1883 -i solar-viewer-2290 -t "connectmq/demo/+/solar/#" -v
Uma mensagem típica fica assim:
{"ac_power_w": 4183.0, "ac_current_a": 6.05, "ac_voltage_v": 231.4, "frequency_hz": 50.01,
"energy_total_kwh": 18342.611, "dc_power_w": 4301.0, "temp_c": 41.2, "state": "mppt", "ts": 1760603520}
Armadilhas do Monitoramento de Inversor Solar
A maioria dos problemas vem de poucas causas:
- Endereços deslocados em um. A documentação mistura numeração de registradores começando em 0 e em 1. Por isso o script tenta tanto 40000 quanto 39999.
- Fatores de escala mudam. Alguns inversores alteram o
W_SFdinamicamente. Sempre leia o fator de escala na mesma requisição do valor, como o código faz ao ler o bloco inteiro. - Período noturno. Muitos inversores desligam a placa de comunicação à noite ou informam o estado "sleeping" com valores vazios. Trate timeouts depois do pôr do sol como normais e mantenha o último valor retido.
- Taxa de leitura. A cada 5 a 10 segundos é mais que suficiente para dashboards e controle de excedente. Ler várias vezes por segundo não traz ganho e pode perturbar alguns inversores.
- Medidor versus inversor. O inversor conhece a produção, não o consumo nem a injeção na rede. Para lógica de autoconsumo você também precisa de um medidor da rede; o guia de monitor de energia residencial cobre essa metade.
- Inversores híbridos com baterias frequentemente expõem os dados da bateria em modelos específicos do fabricante, e não nos modelos SunSpec padrão. Veja monitoramento de bateria residencial para publicar valores do BMS.
Usando os Dados
Com a produção no MQTT, qualquer consumidor pode usá-la sem tocar no inversor de novo. O Home Assistant pode mapear o JSON para sensores pela integração MQTT, o Node-RED pode acionar uma tomada inteligente quando a produção passar de um limite e o Telegraf pode armazenar tudo em um banco de dados de séries temporais para relatórios mensais de geração. Como a mensagem de telemetria é retida, um dashboard aberto ao meio-dia vê a produção atual imediatamente.
As integrações funcionam assim de propósito: o broker é o hub, e cada ferramenta se conecta a ele como cliente MQTT. Se a ideia for nova para você, a visão geral sobre o que faz um broker MQTT explica o modelo publish/subscribe por trás disso.
Indo para Produção com um Broker Privado
Dados solares não são secretos como senhas, mas revelam padrões de ocupação e detalhes do sistema, e o servidor MQTT público é compartilhado. Em uma instalação permanente, rode o publicador em um Raspberry Pi ou servidor doméstico e envie os dados a um broker MQTT na nuvem via TLS. Com o ConnectMQ, crie um broker no portal, copie as credenciais geradas e substitua as linhas de conexão:
mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="YOUR_CLIENT_ID")
mq.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
mq.tls_set()
mq.will_set("home/solar/inverter1/status", "offline", qos=1, retain=True)
mq.connect("broker.connectmq.com", 8883, keepalive=60)
Um broker MQTT gerenciado na nuvem também permite ver a produção pelo celular sem expor nada na sua rede doméstica, porque o Raspberry Pi só faz uma conexão de saída. Em um telhado industrial com vários inversores, como o de um galpão em Joinville ou de uma usina de geração distribuída, o mesmo fluxo de telemetria alimenta um gêmeo digital da planta solar. O guia de automação com IoT, mais amplo, mostra como os dados solares se encaixam nos fluxos de energia da casa inteira.
Monitore sua Produção Solar com o ConnectMQ
O ConnectMQ é um broker MQTT gerenciado com TLS na porta 8883, acesso via WebSocket para dashboards no navegador, explorador de topics ao vivo e regras de alerta por limite, por exemplo para avisar quando um inversor informar estado de falha durante o dia. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito.
Perguntas frequentes
Todo inversor suporta SunSpec Modbus?
Não. Muitas marcas consolidadas de inversores string suportam, muitas vezes depois de ativar a opção nas configurações do instalador, enquanto alguns inversores híbridos e de baixo custo oferecem apenas mapas Modbus RTU específicos do fabricante ou APIs na nuvem. Procure "SunSpec" na documentação do seu modelo.
Com que frequência devo ler o inversor?
A cada 5 a 10 segundos basta para dashboards ao vivo e automações baseadas em excedente. Leituras mais rápidas raramente agregam valor, e alguns inversores reagem mal a elas.
Por que meu script falha à noite?
Muitos inversores desligam a interface de comunicação quando não há entrada fotovoltaica. Trate os timeouts noturnos como esperados e conte com a última mensagem MQTT retida.
Posso controlar o inversor via MQTT?
Alguns inversores aceitam registradores de controle SunSpec para limitação de potência, mas escrever em um inversor pode violar as regras de conexão à rede. Mantenha este tutorial somente leitura, a menos que seu instalador confirme o que é permitido.



