Modbus sensor

Hello,

I am currently using modbus switch successfully in my config.
But when I try to get the sensors to work I am out of luck.

Binary sensor gives me always “state off” and binary_sensor.unnamed_device always unnamed device although I have a name for the device configured. Nothing weird in the homeassistant log. However I only see a modbus entry when I start homeassistant…afterwards no entry on modbus again.

The modbus sensor has always a state of “unkown”. In the homeassistant log I see
File “/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/components/sensor/modbus.py”, line 100, in update.

I am using a Wago plc pfc200. It would be great if anyone could help me to read out some registers.

When using a windows program with modbus function 0x01 and function 0x02 I can readout what I need.

Thanks in advance for the help

Regards

Herbert

My binary sensors via Modbus TCP are working, however they all appear as “unnamed device”.

Is there a way to rename these with a Friendly Name?

Hi,

That was me “next issue”…
I have the same issue with the “unnamed device” and the name in the binary_sensor.yaml is correct.

We should log a “bug” report and hope that the developer can solve this.

BTW : can you elaborate on the config and devices you are using? Do you use a PLC or just sensors with the modbus protocol?

It also looks like the sensor numbering changes every time HA restarts. For example, I have a digital input that appears as unnamed binary sensor15, but if I restart HA, it may show up as sensor2.

I access my sensors via pymodbus for a “home grown” monitoring system so I know the coil positions are not changing.

I’m using an easyIO as my controller and exposing the points via modbus TCP.

I ended up writing a python script to poll the values via pymodbus and inject them into HA via the RESTful API. I added an automation to fire this script every 5 seconds.

I plan to update the script to use the Python API in the near future.

I saw you submitted an issue on github - thank you for that.

Yes indeed that is a solution also.
But it would be “nicer” if the component modbus in HA would work that is why I logged the “bug” report.
I hope the developer can solve it.

Just as interest : would you mind sharing your python script?

Thanks

Herbert

I’m not a python expert, but this seems to work…

Python script snippet - getModbusData.py

#!/usr/bin/env python
import requests
import json
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.client.sync import ModbusTcpClient as ModbusClient

#Define Modbus Target Device
client = ModbusClient('X.X.X.X',port=502)

client.connect()

controller = 0x01
address = 0x01
count2   = 19
result2  = client.read_coils(address, count2, unit=controller)

client.close()

#REPEAT THE FOLLOWING FOR EACH REGISTER 
sensorname = 'binarysensor.pump_status'
if result2.bits[0]:
    data = {"state": "On"}
else:
    data = {"state": "Off"}
url = 'http://localhost:8123/api/states/' + sensorname
data_json = json.dumps(data)
headers = {'Content-type': 'application/json'}
response = requests.post(url, data=data_json)

command_shell.yaml snippet:

getmodbusbinary: 'python /PATH_TO_SCRIPT/getModbusData.py'

automation.yaml snippet:

- alias: 'Update Binary Sensors'
  trigger:
    platform: time
    seconds: '/5'
  action:
      service: shell_command.getmodbusbinary

Thanks John,

I am not a python expert neither…but it seems I will need to learn it fast as I see more and more useful things popping up.

I will try it over the weekend.

For now…happy new-year

Regards

Herbert

Hi John,

Perhaps this can help you or somebody else.
First of…I am not a programmer and I am sure my code is terrible bad written.
But…perhaps it can bring a real programmer on good idea’s
So…I took your code… and changed it to MQTT as I had already Mqtt in place and I think it is a lot more efficient than HTTP. I also optimized the modbus communication by just polling a whole register and not bit by bit.

So here it is…without warranty :slight_smile:

#!/usr/bin/env python
import requests
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
import paho.mqtt.client as mqtt


#Define Modbus Target Device
client = ModbusClient('xxx.xxx.xxx.xxx',port=502)
client1 = mqtt.Client()


client.connect()
#MQTT server setup
client1.connect("xxx.xxx.xxx.xxx", 1883, 60)
client1.loop_start()

### ketel modbus input registers ###
result = client.read_discrete_inputs(0,15)
#print "result.bits = %s" % result.bits[4]
if result.bits[4]:
    client1.publish("modbus/ketel/","ON")
else:
    client1.publish("modbus/ketel/","OFF")

### pompvloer modbus input register 5 ###
if result.bits[5]:
    client1.publish("modbus/pompvloer/","ON")
else:
    client1.publish("modbus/pompvloer/","OFF")

### pomprad modbus input register 6 ###
if result.bits[6]:
    client1.publish("modbus/pomprad/","ON")
else:
    client1.publish("modbus/pomprad/","OFF")

client.close()
client1.disconnect()
client1.loop_stop()

I had the exact same problem, but I was able to work around it. Instead of using it as a “binary_sensor” you can use it as a “sensor”. This will give you a 0 for off or a 1 for on. You can then just use a sensor template to make it what you want and hide the original sensor. The first time I set it up the sensors were still out of order, but they fixed themselves after a reboot and have been staying in order every reboot since then.

Hi The solution is to correct
/srv/homeassistant/lib/python3.4/site-packages/homeassistant/components/binary_sensor/modbus.py

and add missing def at line 54:

def name(self):
    """Return the name of the sensor."""
    return self._name

@property

it should look like this

class ModbusCoilSensor(BinarySensorDevice):
“”“Modbus coil sensor.”""

def __init__(self, name, slave, coil):
    """Initialize the modbus coil sensor."""
    self._name = name
    self._slave = int(slave) if slave else None
    self._coil = int(coil)
    self._value = None

@property
def name(self):
    """Return the name of the sensor."""
    return self._name

@property
def is_on(self):
    """Return the state of the sensor."""
    return self._value

def update(self):
    """Update the state of the sensor."""
    result = modbus.HUB.read_coils(self._slave, self._coil, 1)
    self._value = result.bits[0]
3 Likes

Thanks pjeter for the “unnamed_device” solution!
Created pull request here: https://github.com/home-assistant/home-assistant/pull/8256

Update: will be fixed in the 0.48 release!

As you’re using a PFC200 you might wan’t to have a look at this: https://github.com/MichielVanwelsenaere/HomeAutomation.CoDeSys3

it’s an mqtt enabled home automation project that enables you to send MQTT events from the plc itself, no more Modbus polling! You can even subscribe to topics to switch outputs :slight_smile:

@hschroyen Could you please post your modbus sensor config?
Don’t forget to enclose the config in the preformatted tex (Use the </> button above).