Modbus

Modbus is a widely-used industrial communication protocol for connecting electronic devices. energy2mqtt supports Modbus TCP and RTU-over-TCP for reading data from smart meters, heat pumps, solar inverters, and other devices that expose their data via Modbus registers.

Details

Modbus was originally developed in 1979 and remains one of the most common protocols for industrial equipment. If your device has a “Modbus” port or option, it likely works with energy2mqtt.

How Modbus Works

Modbus uses a master/slave architecture (also called client/server). energy2mqtt acts as the master and requests data from your devices (slaves). Each device has a unique slave ID and exposes its data through numbered registers.

Typical Setup

[energy2mqtt] ---(TCP/IP)---> [Modbus Gateway] ---(RS485)---> [Meter 1]
                                                          └---> [Meter 2]
                                                          └---> [Heat Pump]

Or for devices with built-in Ethernet:

[energy2mqtt] ---(TCP/IP)---> [Smart Meter with Modbus TCP]

Supported Protocols

Protocol Description Use Case
Modbus TCP Native TCP/IP Devices with Ethernet port
RTU-over-TCP Serial frames over TCP RS485 devices via gateway

Concepts

Hubs and Devices

energy2mqtt organizes Modbus connections in two levels:

  1. Hub: A network endpoint (IP address + port) that you connect to
  2. Device: A meter or equipment on that hub, identified by its slave ID

Multiple devices can share one hub if they’re connected to the same Modbus gateway.

Register Types

Modbus defines different register types for different purposes:

Type Function Code Description Typical Use
Holding 03 Read/Write registers Configuration, setpoints
Input 04 Read-only registers Measurements, status
Coil 01 Read/Write bits On/Off states

Most meters use Holding or Input registers for their measurements.

Data Formats

Values in Modbus registers can be encoded in different formats:

Format Size Range Example
UInt16 1 register 0 to 65,535 Status codes
Int16 1 register -32,768 to 32,767 Temperature
UInt32 2 registers 0 to 4,294,967,295 Energy counters
Int32 2 registers ±2.1 billion Power (with sign)
Details

Check your device’s manual for the register map. It tells you which register numbers to read and what format the values use.

Configuration

Basic Structure

Modbus is configured in your e2m.yaml file under the modbus section:

modbus:
  hubs:
    - name: "main_hub"
      host: "192.168.1.100"
      port: 502
      proto: TCP
      devices:
        - name: "electricity_meter"
          meter: "dzg"
          slave_id: 1
          read_interval: 60

Hub Configuration

Parameter Required Description Default
name Yes Friendly name for the hub -
host Yes IP address or hostname -
port Yes TCP port number -
proto Yes Protocol: TCP or RTU -
devices Yes List of devices on this hub -

Device Configuration

Parameter Required Description Default
name Yes Friendly name for the device -
meter Yes Reference to definition file -
slave_id Yes Modbus slave address (1-247) -
read_interval Yes Seconds between reads -

Complete Example

modbus:
  hubs:
    - name: "basement_gateway"
      host: "192.168.1.50"
      port: 502
      proto: TCP
      devices:
        - name: "Main Electricity Meter"
          meter: "dzg"
          slave_id: 1
          read_interval: 30

        - name: "Solar Inverter"
          meter: "fronius"
          slave_id: 2
          read_interval: 10

    - name: "heating_room"
      host: "192.168.1.51"
      port: 502
      proto: RTU
      devices:
        - name: "Heat Pump"
          meter: "weishaupt"
          slave_id: 1
          read_interval: 60

Meter Definition Files

The meter parameter in your device configuration references a definition file. These files describe which registers to read and how to interpret the values.

Definition File Locations

energy2mqtt looks for definition files in this order:

  1. config/modbus/{meter}.yaml (your custom definitions)
  2. defs/modbus/{meter}.yaml (built-in definitions)
Details

To customize a built-in definition, copy it to config/modbus/ and modify it there. Your version takes priority.

Definition File Structure

manufacturer: DZG
model: DVH4013
registers:
  - name: positive_power
    input_type: Holding
    register: 0
    length: 2
    format: UInt32
    scaler: 0.1
    unit_of_measurement: W
    device_class: power
    state_class: measurement

  - name: total_energy
    input_type: Holding
    register: 2
    length: 2
    format: UInt32
    scaler: 0.001
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing

Register Definition Parameters

Parameter Required Description Example
name Yes Field name in output positive_power
input_type Yes Register type Holding, Input, Coil
register Yes Starting register address 0
length Yes Number of 16-bit registers 2 for 32-bit
format Yes Data format UInt16, Int32, etc.
scaler No Multiply raw value by this 0.1
unit_of_measurement No Unit for Home Assistant W, kWh, °C
device_class No Home Assistant device class power, energy
state_class No Home Assistant state class measurement

Value Mapping

For registers that represent states or modes, you can map values to meaningful names:

registers:
  - name: operating_mode
    input_type: Holding
    register: 100
    length: 1
    format: UInt16
    mappings:
      0: "Off"
      1: "Heating"
      2: "Cooling"
      3: "Hot Water"
      _: "Unknown"   # Default for unmapped values

Calculated Values (Templates)

You can create calculated values that use other register values:

registers:
  - name: power_l1
    input_type: Holding
    register: 10
    length: 1
    format: Int16
    unit_of_measurement: W

  - name: power_l2
    input_type: Holding
    register: 11
    length: 1
    format: Int16
    unit_of_measurement: W

  - name: power_l3
    input_type: Holding
    register: 12
    length: 1
    format: Int16
    unit_of_measurement: W

  # Calculated total power
  - name: total_power
    value: "power_l1 + power_l2 + power_l3"
    unit_of_measurement: W
    device_class: power
    state_class: measurement
Details

Template expressions can use basic math (+, -, *, /) and reference any previously defined register by name.

Creating Your Own Definition

If your device isn’t supported yet, you can create your own definition file:

Step 1: Get the Register Map

Find the Modbus register documentation for your device. This is usually in:

  • The device manual
  • A separate “Modbus documentation” PDF
  • The manufacturer’s website

Step 2: Create the Definition File

Create a new YAML file in config/modbus/:

# config/modbus/my_meter.yaml
manufacturer: My Manufacturer
model: My Model

registers:
  - name: voltage
    input_type: Input
    register: 0
    length: 1
    format: UInt16
    scaler: 0.1
    unit_of_measurement: V
    device_class: voltage
    state_class: measurement

Step 3: Reference in Configuration

modbus:
  hubs:
    - name: "my_hub"
      host: "192.168.1.100"
      port: 502
      proto: TCP
      devices:
        - name: "My Meter"
          meter: "my_meter"    # matches filename
          slave_id: 1
          read_interval: 30

Home Assistant Integration

energy2mqtt automatically creates Home Assistant entities for each register with device_class or unit_of_measurement defined. The entities appear under a device named after your device configuration.

Device Classes

Common device classes for metering:

Class Use For Units
power Current power W, kW
energy Energy consumption Wh, kWh
voltage Voltage V
current Current A
temperature Temperature °C
frequency Frequency Hz

State Classes

Class Description
measurement Instantaneous values (power, temperature)
total Running totals that can reset
total_increasing Running totals that only increase (energy)

Troubleshooting

Connection Issues

“Connection refused”

  • Check if the device is reachable: ping 192.168.1.100
  • Verify the port number (usually 502)
  • Check firewall settings

“Connection timeout”

  • The device might be busy or offline
  • Try increasing the read_interval
  • Check if another system is polling the same device

Data Issues

“Wrong values” or “Value out of range”

  • Verify the register address (0-based vs 1-based)
  • Check the data format (signed vs unsigned, byte order)
  • Verify the scaler value

“Always returns 0”

  • Check if you’re using the correct register type (Holding vs Input)
  • Verify the slave ID
  • Some devices need to be “enabled” for Modbus first

Register Address Notes

Details

Modbus documentation uses different conventions:

  • 0-based: Register 0 is the first register
  • 1-based: Register 1 is the first register (address 0)

energy2mqtt uses 0-based addressing. If your manual says “register 40001”, try address 0.