La monitorización de un inversor solar por MQTT libera tus datos de producción de la app del fabricante y los pone a disposición de dashboards, domótica y lógica de desplazamiento de cargas en tiempo real. En este tutorial leerás la potencia, la energía y el estado de un inversor mediante el estándar SunSpec Modbus TCP con Python, publicarás JSON limpio en un broker cada pocos segundos y conocerás los errores que hacen tropezar a la mayoría de los primeros intentos. También se cubren rutas alternativas mediante API HTTP locales y RS485.
Tres formas de sacar datos de un inversor
Los portales de los fabricantes sirven para echar un vistazo mensual, pero suelen actualizarse lentamente y dependen de internet. El acceso local es más rápido, funciona sin conexión y es lo que necesitas para automatizaciones como hacer funcionar una bomba de calor con los excedentes.
| Método | Inversores típicos | Ventajas | Inconvenientes |
|---|---|---|---|
| SunSpec Modbus TCP | Muchos inversores de string de las grandes marcas | Mapa de registros estandarizado, solo LAN, rápido | A menudo hay que activarlo en los ajustes de instalador |
| API HTTP local del fabricante | Algunas marcas exponen JSON en la LAN | Fácil de leer con cualquier cliente HTTP | Distinta en cada fabricante, puede requerir tokens |
| Modbus RTU sobre RS485 | Muchos inversores híbridos y económicos | Funciona sin puerto de red | Requiere un adaptador RS485 y el mapa de registros del fabricante |
SunSpec es el mejor punto de partida si tu inversor lo admite, porque el mismo código funciona con distintas marcas. La SunSpec Alliance define "modelos": bloques de registros con una disposición fija. Los modelos de inversor 101 (monofásico), 102 (fase partida) y 103 (trifásico) comparten la misma disposición de campos, que es en lo que se basa el código siguiente.
Activar Modbus TCP en el inversor
Cada marca esconde este ajuste de forma distinta, pero el patrón es el mismo:
- Asigna al inversor una IP fija mediante una reserva DHCP.
- En el menú de instalador o de puesta en marcha, activa Modbus TCP (a veces llamado "SunSpec" o "Modbus slave").
- Anota el puerto (casi siempre 502) y el unit ID (a menudo 1, a veces 126 u otro valor).
- Elige el formato de registros SunSpec / float o int+SF si el inversor lo pregunta; esta guía usa el formato de entero más factor de escala, que es el más compatible.
- Si tu inversor tiene una opción de "solo lectura" para Modbus, actívala. Solo necesitas leer.
Algunos inversores aceptan un único cliente Modbus TCP a la vez. Si ya hay conectado un gestor energético o el controlador de un wallbox, tu script puede ser rechazado o desconectar al otro cliente, así que decide qué sistema es el dueño de la conexión.
Cómo funcionan los registros SunSpec
Un dispositivo SunSpec empieza con el marcador SunS en una dirección base, normalmente 40000. Tras el marcador viene una cadena de modelos, cada uno de los cuales comienza con un ID de modelo y una longitud. Recorres la cadena hasta encontrar el modelo 101, 102 o 103 y luego lees los campos en desplazamientos fijos:
| Desplazamiento en el modelo | Campo | Tipo | Significado |
|---|---|---|---|
| 2 | A | uint16 | Corriente AC, escalada por A_SF (desplazamiento 6) |
| 10 | PhVphA | uint16 | Tensión de la fase A, escalada por V_SF (desplazamiento 13) |
| 14 | W | int16 | Potencia AC, escalada por W_SF (desplazamiento 15) |
| 16 | Hz | uint16 | Frecuencia, escalada por Hz_SF (desplazamiento 17) |
| 24–25 | WH | acc32 | Energía acumulada en Wh, escalada por WH_SF (desplazamiento 26) |
| 31 | DCW | int16 | Potencia DC, escalada por DCW_SF (desplazamiento 32) |
| 33 | TmpCab | int16 | Temperatura del armario, escalada por Tmp_SF (desplazamiento 37) |
| 38 | St | enum16 | Estado de funcionamiento (4 = MPPT, produciendo) |
Los desplazamientos se cuentan desde el registro del ID de modelo. Cada valor se multiplica por 10 elevado a su factor de escala con signo, de modo que un W en bruto de 51234 con W_SF de -1 significa 5123,4 W. Los registros no implementados devuelven 0x8000 (con signo) o 0xFFFF (sin signo) y deben ignorarse.
El publicador en Python
Instala las bibliotecas:
pip install "paho-mqtt>=2.0" "pymodbus>=3.7"
El script localiza la base SunSpec, recorre los modelos, lee el bloque del inversor y publica JSON. Usa primero el servidor MQTT público gratuito, pensado solo para pruebas y no para datos de producción, con un prefijo aleatorio porque cualquiera puede leer esa zona.
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: # un valor acc32 de 0 significa no 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)
Si tu inversor usa un unit ID distinto de 1, pásalo en cada lectura con el argumento device_id (llamado slave en versiones antiguas de pymodbus). Observa la salida desde otra máquina:
mosquitto_sub -h broker.connectmq.com -p 1883 -i solar-viewer-2290 -t "connectmq/demo/+/solar/#" -v
Un mensaje típico tiene este aspecto:
{"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}
Errores habituales en la monitorización de inversores solares
La mayoría de los problemas tienen unas pocas causas:
- Direcciones desplazadas en uno. La documentación mezcla numeración de registros desde 0 y desde 1. Por eso el script prueba tanto 40000 como 39999.
- Los factores de escala cambian. Algunos inversores modifican
W_SFdinámicamente. Lee siempre el factor de escala en la misma petición que el valor, como hace el código al leer el bloque completo. - La noche. Muchos inversores apagan su placa de comunicaciones por la noche o informan del estado "sleeping" con valores vacíos. Trata los tiempos de espera agotados tras la puesta de sol como algo normal y conserva el último valor retenido.
- Frecuencia de sondeo. Cada 5 a 10 segundos es más que suficiente para dashboards y control de excedentes. Sondear varias veces por segundo no aporta nada y puede alterar a algunos inversores.
- Contador frente a inversor. El inversor conoce la producción, no el consumo ni la exportación. Para la lógica de autoconsumo también necesitas un contador de red; la guía del monitor de energía doméstica cubre esa otra mitad.
- Los inversores híbridos con baterías suelen exponer los datos de la batería en modelos propios del fabricante en lugar de los SunSpec estándar. Consulta monitorización de baterías domésticas para publicar valores del BMS.
Usar los datos
Una vez que la producción está en MQTT, cualquier consumidor puede usarla sin volver a tocar el inversor. Home Assistant puede asignar el JSON a sensores con su integración MQTT, Node-RED puede accionar un enchufe inteligente cuando la producción supera un umbral y Telegraf puede guardarlo todo en una base de datos de series temporales para informes mensuales de rendimiento. Como el mensaje de telemetría es retenido, un dashboard que se abre a mediodía ve la producción actual de inmediato.
Las integraciones funcionan así a propósito: el broker es el centro y cada herramienta se conecta a él como cliente MQTT. Si la idea es nueva para ti, la explicación de qué hace un broker MQTT describe el modelo publicación/suscripción en el que se basa.
Pasar a producción con un broker privado
Los datos solares no son secretos como las contraseñas, pero sí revelan patrones de ocupación y detalles de la instalación, y el broker público es compartido. Para una instalación permanente, ejecuta el publicador en una Raspberry Pi o un servidor doméstico y envía los datos a un broker MQTT en la nube mediante TLS. Con ConnectMQ, crea un broker en el portal, copia las credenciales generadas y sustituye las líneas de conexión:
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)
Un broker en la nube también te permite ver la producción desde el móvil sin exponer nada de tu red doméstica, porque la Raspberry Pi solo establece una conexión saliente. La guía de automatización IoT, más amplia, muestra cómo encajan los datos solares en los flujos energéticos de toda la vivienda.
Monitoriza tu producción solar con ConnectMQ
ConnectMQ es un broker MQTT gestionado con TLS en el puerto 8883, acceso por WebSocket para dashboards en el navegador, un explorador de topics en vivo y reglas de alerta por umbral, por ejemplo para avisarte cuando un inversor informa de un estado de fallo durante el día. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito.
Preguntas frecuentes
¿Todos los inversores admiten SunSpec Modbus?
No. Muchas marcas consolidadas de inversores de string lo admiten, a menudo tras activarlo en los ajustes de instalador, mientras que algunos inversores híbridos y económicos solo ofrecen mapas Modbus RTU propios del fabricante o API en la nube. Busca "SunSpec" en la documentación de tu modelo.
¿Con qué frecuencia debo sondear el inversor?
Cada 5 a 10 segundos basta para dashboards en vivo y automatizaciones basadas en excedentes. Un sondeo más rápido rara vez aporta valor y algunos inversores responden mal a él.
¿Por qué falla mi script por la noche?
Muchos inversores apagan su interfaz de comunicaciones cuando no hay entrada fotovoltaica. Considera normales los tiempos de espera nocturnos y apóyate en el último mensaje MQTT retenido.
¿Puedo controlar el inversor por MQTT?
Algunos inversores aceptan registros de control SunSpec para limitar la potencia, pero escribir en un inversor puede incumplir las normas de conexión a red. Mantén este tutorial en modo solo lectura salvo que tu instalador confirme qué está permitido.



