Skip to main content

Modbus TCP smart home integration, free and open source

Modbus TCP integration for Gladys Assistant

Read and write Modbus TCP registers: energy meters, inverters, heat pumps, PLCs.

Reads, and on request writes, the registers of Modbus TCP devices: energy meters, solar inverters, batteries, heat pumps, ventilation units, PLCs. Ready profiles cover the most common devices; for the others, you describe the registers in one line each, without editing any file.

Developed without the hardware: feedback welcome. The profiles follow the manufacturers' published register tables and are tested against simulated devices, not against real ones. If a value looks wrong on your device, open an issue on GitHub with the output of the Test a read button.

What it does​

  • Up to four Modbus devices, each one a Gladys device with its features (power, energy, voltage, temperature, state...), refreshed every 5 seconds to 5 minutes.
  • Ready profiles: Eastron SDM630 and SDM120 meters, SunSpec inverters and meters (SMA, SolarEdge, Fronius, Kostal and many others), Huawei SUN2000 inverters (with their meter and battery), Victron GX systems.
  • Custom registers for everything else: holding and input registers, coils, discrete inputs, 16 to 64-bit integers and floats in any word order, scale, offset, unit, kind.
  • Energy indexes in kWh: Gladys adds its energy tracking (30-minute consumption and cost) to them.
  • Writing, off by default, only for the registers you declare as a switch or a bounded setpoint.
  • A Test a read button to find the type of an unknown register, a widget, and two scene triggers (a device stops answering, answers again).

Requirements​

  • Gladys Assistant 5.1 or later.
  • A device that speaks Modbus TCP on your network, or an RS-485 device behind a Modbus TCP gateway (USR-TCP232, Waveshare RS485-to-ETH, Elfin EW11/EE11...). The gateway works either as a Modbus TCP gateway ("Modbus TCP to RTU" mode) or in transparent mode ("RTU over TCP" in this integration).
  • Modbus TCP enabled on the device: on an SMA inverter (Sunny Portal or the local interface, "Modbus" server), on a Victron GX (Settings > Services > Modbus TCP), on a SolarEdge inverter (SetApp, Modbus TCP), on a Fronius inverter (Communication > Modbus, "SunSpec" model type), on a Huawei inverter (SDongle, Modbus TCP "Enable (unrestricted)").
  • A fixed IP address for the device or the gateway (DHCP reservation in your router): Gladys identifies the device by its address, port and unit id.

Configuration​

General settings​

  • Language of the feature names: Gladys keeps the names given when a device is added.
  • Read every: 5 seconds to 5 minutes. Gladys accepts 300 values a minute per integration: with many registers and a short interval, the integration slows down by itself to stay below (one warning in the logs).
  • Answer timeout: 3 seconds by default; raise it for a slow RS-485 bus.
  • Allow writing: see Writing registers.

Devices​

Each of the four device blocks has:

  • IP address or host name of the device or of its gateway. Empty: the block is not used.
  • TCP port: 502 almost always.
  • Unit id: 1 most of the time. SMA: 126 for SunSpec (3 for SMA's own registers). Victron GX: 100 for the system values. Fronius Smart Meter: 240. Eastron meters: the Modbus address set on the meter (001 by default).
  • Profile: a ready profile, or none.
  • Framing: Modbus TCP, or RTU over TCP for a gateway in transparent mode.
  • Custom registers: see below. They add to the profile's features.

Several RS-485 devices behind one gateway: one block per device, with the same address and port and their own unit id. They share one connection, and their requests are sent one at a time, as the bus requires.

Profiles​

ProfileDeviceUsual unit id
Eastron SDM630three-phase meter (through a gateway)1
Eastron SDM120single-phase meter (through a gateway)1
SunSpecinverters and meters that follow SunSpec1, 126 (SMA)
Huawei SUN2000Huawei inverter, its meter and its battery1
Victron GXCerbo GX, Venus GX, Ekrano: system values100

The SunSpec profile reads the list of SunSpec models the device announces (at register 40000, or 0, or 50000) and publishes the inverters and meters it finds. The Huawei profile looks once for a power meter and a battery. What a device has is kept in /data, so a device asleep at restart (an inverter at night) is still published.

Custom registers​

One entry per register, entries separated by semicolons (the configuration field is a single line):

Flow temperature: holding 100 int16 scale=0.1 temperature; Pump: coil 5 switch

An entry is name: table address, then, in any order, a data type, a kind and options.

  • name: the name of the feature in Gladys (40 characters at most).
  • table: holding (holding register, function 3), input (input register, function 4), coil (function 1), discrete (discrete input, function 2).
  • address: the register address as sent on the wire, from 0 to 65535, in decimal or in hexadecimal (0x0034). Some documents count from 1, or add 30001 or 40001: subtract it.
  • data type (registers only): int16 (default), uint16, int32, uint32, float32, int64, uint64, float64, or bit0 to bit15 for one bit of a register.
  • kind: what the value is.
KindGladys featureUnits (first = default)
temperaturetemperature°C, °F, K
humidityhumidity%
pressurepressurebar, mbar, hPa, kPa, Pa, psi
powerpower (energy sensor)W, kW
energyenergy index, energy trackingkWh, Wh, MWh (published in kWh)
productionproduction indexkWh, Wh, MWh (published in kWh)
solar_powerproduction powerW, kW
grid_powergrid power (import +, export −)W, kW
voltagevoltageV, mV
currentcurrentA, mA
batterybattery level%
volumevolumeL, mL, m3
durationdurations, ms, min, h, d
valuea number shown as is (default)any of the above, or none
binaryon/off, read-only
switchon/off, writable
setpointbounded temperature setpoint°C, °F
  • options:
    • scale=0.1 multiplies the raw value, offset=-40 adds to it (after the scale). A decimal comma works too (scale=0,1).
    • unit=kW picks another unit of the kind.
    • swap=word (registers in reverse order, "CDAB"), swap=byte ("BADC"), swap=word_byte ("DCBA"). Without it: most significant register first ("ABCD"). The names are the ones of Home Assistant's modbus integration.
    • min= and max=: the display bounds; for a setpoint, the bounds outside which nothing is written (mandatory).
    • precision=2: decimals kept (from the scale by default, 2 for floats).
    • on= and off=: the values a register switch writes (1 and 0 by default).

Every mistake is listed under the configuration status (red "Disconnected" badge) and in red by the Check the configuration button, with the device, the entry number, its name and the word at fault, for example Device 1, entry 2 "Pump": a coil is one bit: it takes no data type. The other entries keep working.

Devices and features​

Every device is polled by the integration itself, at the chosen interval; only the values that changed are sent to Gladys, plus every value once every 6 hours.

Eastron SDM630 and SDM120​

Total power, energy imported (energy index, with energy tracking), energy exported, and per phase (SDM630) or for the line (SDM120) voltage, current and power. The meters count the power positive when importing.

SunSpec​

Per inverter model (101-103, 111-113): AC power, total yield (index in kWh), DC power, AC current, AC voltage (phase A), internal (cabinet) temperature, operating state (off, sleeping, starting, producing, limited, shutting down, fault, standby). Per meter model (201-204, 211-214): meter power (with the manufacturer's sign), current, voltage, energy imported and exported. The device is named after its manufacturer and model, its serial number is in the device parameters. A value the device does not implement is not published.

Huawei SUN2000​

AC power, total yield, DC input power, AC voltage and current (phase A), internal temperature, operating state. With a power meter: grid power (positive when importing, as Gladys counts it), grid import and grid export indexes. With a LUNA2000 battery: battery level, charge power and discharge power.

Victron GX​

Grid power (sum of the phases, positive when importing), house consumption, solar power (PV on the AC side and DC side). With a battery: battery level, charge and discharge power, battery voltage.

Custom registers​

One feature per entry, of the category its kind gives.

Writing registers​

Writing is off by default. Only the entries you declare as switch or setpoint are controls in Gladys, nothing else; while Allow writing is off, they refuse every change (the configuration status says so). Turn it on in the configuration when you are sure of the registers.

  • switch: on a coil, writes 1 or 0; on a holding register, writes the on or off value (Heating: holding 111 switch on=1 off=0). It is shown as an on/off toggle, outside the voice assistants.
  • setpoint: a temperature written to a holding register (DHW setpoint: holding 110 uint16 setpoint min=40 max=55). min and max are mandatory: a value outside them is refused and nothing is written. The scale is applied backwards (with scale=0.1, 42.5 °C writes 425).

Writing the wrong register can damage an installation (a heat pump, an inverter, a boiler): check every address, data type and value in the manufacturer's documentation, start with a value you can undo, and keep writing off when you do not need it. Each write is logged with its register and value. One bit of a register cannot be written (that would rewrite the 15 others), nor a 64-bit value.

Actions​

  • Test a read: pick a saved device, type a register in the custom registers syntax without the name (holding 100 int16 scale=0.1), and the raw words are shown in hexadecimal and decimal, with the converted value and what the same registers read as in every data type and word order. Add count=10 to read ten registers from that address. Type sunspec to list the SunSpec models of the device. Works even when the device has no register declared yet.
  • Check the configuration: the mistakes entry by entry (in red), then each device with its profile, its number of features, and whether it answers.

Dashboard widget​

Modbus device: choose a device; the widget shows its main values as live tiles (power and yield of an inverter, power and indexes of a meter, grid, house, solar and battery of a Victron system) and the state of its link: answering or not, time of the last read, operating state of an inverter, last error.

Scene triggers​

  • A Modbus device stops answering: two reads in a row failed. Variables: the device name and the error. Filter: one device, or any.
  • A Modbus device answers again: a device that had stopped answering is read again.

Scene examples​

  • Notify me when the heat pump gateway stops answering for more than two read cycles: trigger A Modbus device stops answering on the heat pump, action "Send a message" with {{triggerEvent.data.error}}.
  • Start the dishwasher plug when the solar power exceeds 2000 W: trigger "a device value changes" on Solar power (Victron) or AC power (inverter), condition above 2000, action "turn on".
  • Lower the hot water setpoint at night: scheduled trigger at 22:00, action "set the value" of DHW setpoint to 45 (writing allowed, setpoint declared with its bounds).

Troubleshooting​

  • "Cannot connect ... ECONNREFUSED": nothing listens on that address and port, or Modbus TCP is not enabled on the device. "No answer ... within 3000 ms": wrong address, a device asleep (inverters at night), a gateway whose serial settings (baud rate, parity) do not match the device, or the wrong framing.
  • "Modbus exception 11": the gateway answers, but not the device behind it: check the unit id and the RS-485 wiring (A/B).
  • "refuses every register" / exception 2: the profile or the addresses do not match the device. Use Test a read with count= around the address, and check whether the document counts from 1 or adds 30001/40001.
  • A value 10 or 100 times too big: add scale=0.1 or scale=0.01. A huge or absurd value: try another data type or swap=word with Test a read, which shows all the readings at once.
  • A Huawei inverter that does not answer: it accepts one Modbus TCP client at a time (close the other ones), and needs Modbus TCP set to "Enable (unrestricted)" on the SDongle.
  • Logs: set LOG_LEVEL=debug on the integration to see every read.

Limits​

  • Four devices at most, 40 custom registers per device.
  • Modbus TCP and RTU over TCP only: no serial port (the container has none), no Modbus UDP, no ASCII.
  • No automatic discovery: Modbus has none, the addresses are typed.
  • The SunSpec profile reads the inverter and meter models only (no battery model 802, no MPPT model 160).
  • Writing: switches and temperature setpoints only; no bit of a register, no 64-bit value, no other numeric setpoint (Gladys has no neutral numeric control).
  • Feature names are frozen when a device is added (Gladys rule).
  • Developed without the hardware: the profiles are tested against simulated devices built from the manufacturers' tables.

Eastron, SMA, SolarEdge, Fronius, Kostal, Huawei, Victron Energy and SunSpec are trademarks of their owners. This integration is not affiliated with, nor endorsed by, any of them.

Configuration settings​

These are the settings Modbus TCP asks for in its configuration screen in Gladys.

SettingTypeRequiredDescription
Getting startedsectionNoDescribe up to four Modbus devices below: the address of the device or of its Modbus TCP gateway, its unit id, then a ready-made profile or your own registers. Save, then add the devices from the Discovery tab. The "Test a read" button reads one register to find its type before declaring it.
Language of the feature namesselectNoGladys keeps the names given when a device is added.
Read everyselectNoGladys accepts 300 values a minute: with many registers, the reads slow down to stay below.
Answer timeout (s)numberNoRaise it for a slow RS-485 bus (9600 baud and below).
Allow writingbooleanNoOff by default. When on, only the registers you declared as switch or setpoint can be changed from Gladys. Writing a wrong register can damage an installation: check each address in the manufacturer's documentation.
Device 1sectionNoA device and its Modbus TCP gateway, if any. Several devices behind one RS-485 gateway share its address and port, with different unit ids. Give the device (or the gateway) a fixed IP address: Gladys identifies the device by it.
IP address or host namestringNo
TCP portnumberNo502 for Modbus TCP. Huawei: 502 through the SDongle, 6607 on some inverters.
Unit id (slave)numberNoUsually 1. SMA: 126 (SunSpec) or 3. Victron GX: 100. Fronius meter: 240. Eastron meters: the address set on the meter.
ProfileselectNoA profile knows the registers of the device. SunSpec covers many inverters and meters (SMA, SolarEdge, Fronius, Kostal...): its models are detected.
FramingselectNoRTU over TCP for an RS-485 gateway in transparent mode (USR, Waveshare, Elfin set to "none" / "transparent").
Custom registersstringNoEntries separated by semicolons: name: table address, then type, kind and options. Tables: holding, input, coil, discrete. Types: int16 (default), uint16, int32, uint32, float32, int64, uint64, float64, bit0-bit15. Kinds: temperature, humidity, pressure, power, energy, production, solar_power, grid_power, voltage, current, battery, volume, duration, value (default), binary, switch, setpoint. Options: scale=0.1 offset= unit= swap=word min= max= precision= on= off=.
Device 2sectionNoLeave the address empty if you do not use this device.
IP address or host namestringNo
TCP portnumberNo
Unit id (slave)numberNo
ProfileselectNo
FramingselectNo
Custom registersstringNo
Device 3sectionNoLeave the address empty if you do not use this device.
IP address or host namestringNo
TCP portnumberNo
Unit id (slave)numberNo
ProfileselectNo
FramingselectNo
Custom registersstringNo
Device 4sectionNoLeave the address empty if you do not use this device.
IP address or host namestringNo
TCP portnumberNo
Unit id (slave)numberNo
ProfileselectNo
FramingselectNo
Custom registersstringNo

How to install Modbus TCP in Gladys​

  1. In Gladys, open Integrations: Modbus TCP appears in the catalog, next to the native integrations, with a community badge.
  2. Click Install. Gladys pulls the Docker image (ghcr.io/guim31/gladys-modbus:1.0.1), starts it in a sandbox isolated from the core, and generates the integration's interface (devices, discovery and configuration).
  3. Open the Configuration screen of the integration, fill in the settings, and save.
  4. You can also install it directly from its repository URL: https://github.com/guim31/gladys-modbus.

Modbus TCP requires Gladys >=5.1.0. The catalog inside Gladys refreshes every hour, so a new version becomes available at most one hour after its release.

Not running Gladys yet? It is free and open source: follow the installation guide to get started.

About external integrations​

Modbus TCP is an external integration: a community integration packaged as a Docker container and published on GitHub, that Gladys installs in one click and runs in a sandbox isolated from its core. It is published and maintained by guim31, not by the Gladys core team.

Subscribe to the Gladys Assistant newsletter

A few emails per month about new releases and project news. Sent by Pierre-Gilles Leymarie, founder of the project. Unsubscribe anytime 🙂