Integration new device using modbus tcp

Hi, someone can help me to realize an integration of a modbus device to read the energy meter?
Using modbus via configuration.yaml it’s very easy, but i need to integrate this for my company and must be an integration.
This is yaml file and it works very well:
modbus:

  • name: device
    type: tcp
    host: 192.168.1.227
    port: 502
    sensors:
  • name: Potenza Attiva Prelevata Istantanea
    device_class: power
    unit_of_measurement: W
    state_class: measurement
    data_type: uint16
    address: 2
    count: 1

But how can i convert it in an integration?
How can i create sensor.py in my platform that do the same thing?
Can I use modbus function stored in HA?
Someone can help me with an example?
I’m ready with developer ambient
Thanks

pymodbus


#!/usr/bin/env python
"""
Pymodbus Synchronous Client Examples
--------------------------------------------------------------------------

The following is an example of how to use the synchronous modbus client
implementation from pymodbus.

It should be noted that the client can also be used with
the guard construct that is available in python 2.5 and up::

    with ModbusClient('127.0.0.1') as client:
        result = client.read_coils(1,10)
        print result
"""
# --------------------------------------------------------------------------- #
# import the various client implementations
# --------------------------------------------------------------------------- #
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
# from pymodbus.client.sync import ModbusUdpClient as ModbusClient
# from pymodbus.client.sync import ModbusSerialClient as ModbusClient

# --------------------------------------------------------------------------- #
# configure the client logging
# --------------------------------------------------------------------------- #
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s '
          '%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)

UNIT = 0x1


def run_sync_client():
    # ------------------------------------------------------------------------#
    # choose the client you want
    # ------------------------------------------------------------------------#
    # make sure to start an implementation to hit against. For this
    # you can use an existing device, the reference implementation in the tools
    # directory, or start a pymodbus server.
    #
    # If you use the UDP or TCP clients, you can override the framer being used
    # to use a custom implementation (say RTU over TCP). By default they use
    # the socket framer::
    #
    #    client = ModbusClient('localhost', port=5020, framer=ModbusRtuFramer)
    #
    # It should be noted that you can supply an ipv4 or an ipv6 host address
    # for both the UDP and TCP clients.
    #
    # There are also other options that can be set on the client that controls
    # how transactions are performed. The current ones are:
    #
    # * retries - Specify how many retries to allow per transaction (default=3)
    # * retry_on_empty - Is an empty response a retry (default = False)
    # * source_address - Specifies the TCP source address to bind to
    # * strict - Applicable only for Modbus RTU clients.
    #            Adheres to modbus protocol for timing restrictions
    #            (default = True).
    #            Setting this to False would disable the inter char timeout
    #            restriction (t1.5) for Modbus RTU
    #
    #
    # Here is an example of using these options::
    #
    #    client = ModbusClient('localhost', retries=3, retry_on_empty=True)
    # ------------------------------------------------------------------------#
    client = ModbusClient('192.168.1.227', port=502)
    # from pymodbus.transaction import ModbusRtuFramer
    # client = ModbusClient('localhost', port=5020, framer=ModbusRtuFramer)
    # client = ModbusClient(method='binary', port='/dev/ptyp0', timeout=1)
    # client = ModbusClient(method='ascii', port='/dev/ptyp0', timeout=1)
    # client = ModbusClient(method='rtu', port='/dev/ptyp0', timeout=1,
    #                       baudrate=9600)
    client.connect()


    log.debug("Read input registers")
    rr = client.read_input_registers(2, 1, unit=UNIT)
    assert(not rr.isError())     # test that we are not an error

    
    # ----------------------------------------------------------------------- #
    # close the client
    # ----------------------------------------------------------------------- #
    client.close()


if __name__ == "__main__":
    run_sync_client()

Hi @nikito7 ,
i have the same problem of @warrenriccio, i try to explain what is my problem… When i try to use an external library the client told me that can’t find the module. how i can fix this issue?

Thanks so much

Thank you my friend.
Like Marco, now and ever, I have this problem (with every python library)
‘’’
/config/custom_components/example_sensor/init.py
Traceback (most recent call last):
File “/config/custom_components/example_sensor/init.py”, line 1, in
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
ModuleNotFoundError: No module named ‘pymodbus’ ’
‘’’

Maybe the error can be in manifest?

Thanks in advance

Maybe

  "requirements": ["pymodbus==2.5.3"],

If outside HA, pip install pymodbus

Hi, You think it works if i’m testing this solution via config custom ?
In developer ambient it’s not working, it seems like if it didn’t download anything. The module is never present.
I don’t know if you have some other suggest for me, but you are very kindle.

Thanks

Simone

If you installed outside virtualenv, you need install again

I programmed in different ways but no way to work…
Maybe i’m not be able to do this. The main problem is that i can’t use any python library not present in HA. And i can’t understand why i can’t integrate a new device using a configuration file in device domain. It would be easy for all in this case.
I thought it was simpler, like programming in python.
I am discouraged, but thanks for your time: you were the only one who tried to help me…

HA is more hard that a simple .py

You need know how HA works

Maybe using a dumb modbus: yaml install it for you

Anyway check github modbus from HA

You want something with a Logo without any user configuration

Just click

Something like this, I think

Yes, but like you see, this modbusTCP it’s in a custom component , it’s not builted in HA.
And have functions to decode data (not need this)
My company has made a device that will be installed in many home to receive data from fiscal meter.
And it will be possible to get data from this device via modbus TCP. The configuration.yaml is like this:
modbus:

  • name: DeviceTCP

    type: tcp

    host: 192.168.1.227

    port: 502

    sensors:

    - name: Potenza Attiva Prelevata Istantanea
    
      device_class: power
    
      unit_of_measurement: W
    
      state_class: measurement
    
      data_type: uint16
    
      address: 2
    
      count: 1
    

(and more sensors)

And i have created a new sensor (calculated from other DeviceTCP sensor, for power break advise):
sensor:

  • platform: template

    sensors:

    distacco:

    friendly_name: "Avviso distacco"
    
    value_template: >
    
      {% if (states('sensor.data_evento') | int ) > 4294967294 %} Nessun avviso
    
      {% else %} {{ (states('sensor.data_evento') | int + (states('sensor.tempo_residuo_distacco') | int))  | timestamp_local }}
    
      {% endif %}
    

And it works like a charm. :smiley:
I wanted only avoid to our customers to modify the configuration file, finding automatically the deviceTCP on the network (via hostname or mac address) with the sensors in.
A builted integration in the end…

From the devices integration builted in HA i haven’t found anything, only example for custom component folder. So i thought it’s not possible to do this, but it’s possible to integrate a new device only via api.
Like you see, i have many doubts :laughing:

I use packages or !include

Need user edit yaml anyway

You can do “something” to:

  • check if modbus exist in yaml
  • discovery ip
  • append new yaml
  • restart

Custom components need user intervention anyway.
If a user knows how to use custom components, will know edit yaml.

To be easy for client. Your “solution” need to be added to HA. And that may be hard…

Hi my friend, i have a last question for you: if i made a python script file that make a yaml file, included the ip address of this device (put it on from customer via input config). You think it could be an integration in HA?

Let me know what you think…

Thnks

There is no easy way.

Just share yaml with clients

Clients will need to know how to edit configuration.yaml

So:

  • external program, needs some access ssh etc
  • custom_component needs user be smart and above
  • hacs same
  • all options need user intervention

Add to HA official you can try. If someone aprove your PR…

some sort of “Meter X Easy Setup”

( ahaha I almost said same thing in last post :joy: )

ahahah, no way!!

Frank has rejected every code (code that worked in develop ambient via splitting yaml file :wink: )
For now i will write a guide for my customers to edit yaml file.
Many thanks for your help!

Bye

1 Like

Hi @warrenriccio could you share a list of all modbus address/count with explanation? I used this but I’m sure there are more informations that we can get. Thanks a lot!

modbus:
  - name: Alfa
    type: tcp
    host: <AlfaIP>
    port: 502
    sensors:
        - name: Potenza Attiva Prelevata Istantanea
          device_class: power
          unit_of_measurement: W
          state_class: measurement
          data_type: uint16
          address: 2
          count: 1
        - name: Potenza Attiva Immessa Istantanea
          device_class: power
          unit_of_measurement: W
          state_class: measurement
          data_type: uint16
          address: 12
          count: 1
        - name: Potenza Attiva Prodotta Istantanea
          device_class: power
          unit_of_measurement: W
          state_class: measurement
          data_type: uint16
          address: 921
          count: 1
        - name: Energia Attiva Prelevata Totale
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 5
          count: 2
        - name: Energia Attiva Immessa Totale
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 15
          count: 2
        - name: Energia Attiva Prodotta Totale
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 924
          count: 2
        - name: Pot Att Prel Quart Media
          device_class: power
          unit_of_measurement: W
          state_class: measurement
          data_type: uint16
          address: 9
          count: 1
        - name: Pot Att Imm Quart Media
          device_class: power
          unit_of_measurement: W
          state_class: measurement
          data_type: uint16
          address: 19
          count: 1
        - name: Tot Energ Att Prel Giorno-1 F1
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 30
          count: 2
        - name: Tot Energ Att Prel Giorno-1 F2
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 32
          count: 2
        - name: Tot Energ Att Prel Giorno-1 F3
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 34
          count: 2
        - name: Tot Energ Att Prel Giorno-1 F4
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 36
          count: 2
        - name: Tot Energ Att Prel Giorno-1 F5
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 38
          count: 2
        - name: Tot Energ Att Prel Giorno-1 F6
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 40
          count: 2
        - name: Tot Energ Att Imm Giorno-1 F1
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 54
          count: 2
        - name: Tot Energ Att Imm Giorno-1 F2
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 56
          count: 2
        - name: Tot Energ Att Imm Giorno-1 F3
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 58
          count: 2
        - name: Tot Energ Att Imm Giorno-1 F4
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 60
          count: 2
        - name: Tot Energ Att Imm Giorno-1 F5
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 62
          count: 2
        - name: Tot Energ Att Imm Giorno-1 F6
          device_class: energy
          unit_of_measurement: Wh
          state_class: total_increasing
          data_type: uint32
          address: 64
          count: 2
        - name: Fascia oraria corrente
          data_type: uint16
          address: 203
          count: 1
        - name: Data evento
          data_type: uint32
          address: 780
          count: 2
        - name: Tempo residuo distacco
          data_type: uint16
          address: 782
          count: 1

1 Like

Hi.
What about program modbus using Node-Red

Hi,
regarding this list I have a question.
I would like to put inside a folder “modbus” a subfolder “sensor” and inside this various files “alpha.yaml”, “beta.yaml”, ect.

Now in “configuration.yaml” I put:

modbus:
  - name: alpha
    type: tcp
    host: <alpha_IP>
    port: 502
    sensors: !include modbus/sensor/alpha.yaml

and inside the file “alpha.yaml” I put all the sensors:

       - name: Active Power Taken Instantaneous
          device_class: power
          unit_of_measurement: w
          class_state: measurement
          data_type: uint16
          address: 2
          count: 1
        - name: instant active power input
          device_class: power
          unit_of_measure: W
          class_state: measurement
          data_type: uint16
          address: 12
          count: 1
        - name: Instantaneous Active Power Produced
          device_class: power
          unit_of_measure: W
          class_state: measurement
          data_type: uint16
          address: 921
          count: 1
        - name: total active energy drawn
          device_class: energy
          unit_of_measure: wh
          class_state: total_increase
          data_type: uint32
          address: 5
          count: 2
          .... 
          etc

can this work in your opinion?
Also if I have to insert more modbus devices what syntax should I use?
inserting the second one like this gives me error:

 modbus:
  - name: alpha
    type: tcp
    host: <alpha_IP>
    port: 502
    sensors: !include modbus/sensor/alpha.yaml
  - name: beta
    type: tcp
    host: <beta_IP>
    port: 503
    sensors: !.include modbus/sensor/beta.yaml

but i have the error message:

Invalid config for ‘modbus’ at configuration.yaml, line 34: required key ‘address’ not provided
Invalid config for ‘modbus’ at configuration.yaml, line 34: required key ‘name’ not provided

Line 34 il the line:

sensors: !.include modbus/sensor/beta.yaml

ideas to make this work?

1 Like