Modbus fixes to work with pymodbus 1.3.1 (#8365)

* Fixed a bug where changing fan speed was not possible

* Bump pymodbus version to 1.3.1 to fix issue #8285

* Changed all modbus components so that they use CONF_SLAVE from const.py

* Fix checking result from a modbus transaction

* Add missing decorator

* Added modbus write coil service and added descriptions

* Removed a hiding debug print
This commit is contained in:
Sabesto 2017-07-07 07:30:23 +02:00 committed by Paulus Schoutsen
parent 9bc5cd2d4b
commit c48c2b00a8
5 changed files with 69 additions and 10 deletions

View file

@ -49,6 +49,7 @@ class ModbusCoilSensor(BinarySensorDevice):
self._coil = int(coil)
self._value = None
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@ -61,4 +62,10 @@ class ModbusCoilSensor(BinarySensorDevice):
def update(self):
"""Update the state of the sensor."""
result = modbus.HUB.read_coils(self._slave, self._coil, 1)
self._value = result.bits[0]
try:
self._value = result.bits[0]
except AttributeError:
_LOGGER.error(
'No response from modbus slave %s coil %s',
self._slave,
self._coil)

View file

@ -6,13 +6,15 @@ https://home-assistant.io/components/modbus/
"""
import logging
import threading
import os
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.config import load_yaml_config_file
from homeassistant.const import (
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
CONF_HOST, CONF_METHOD, CONF_PORT)
CONF_HOST, CONF_METHOD, CONF_PORT, ATTR_STATE)
DOMAIN = 'modbus'
@ -50,6 +52,7 @@ CONFIG_SCHEMA = vol.Schema({
_LOGGER = logging.getLogger(__name__)
SERVICE_WRITE_REGISTER = 'write_register'
SERVICE_WRITE_COIL = 'write_coil'
ATTR_ADDRESS = 'address'
ATTR_UNIT = 'unit'
@ -61,6 +64,11 @@ SERVICE_WRITE_REGISTER_SCHEMA = vol.Schema({
vol.Required(ATTR_VALUE): vol.All(cv.ensure_list, [cv.positive_int])
})
SERVICE_WRITE_COIL_SCHEMA = vol.Schema({
vol.Required(ATTR_UNIT): cv.positive_int,
vol.Required(ATTR_ADDRESS): cv.positive_int,
vol.Required(ATTR_STATE): cv.boolean
})
HUB = None
@ -105,9 +113,18 @@ def setup(hass, config):
HUB.connect()
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_modbus)
descriptions = load_yaml_config_file(os.path.join(
os.path.dirname(__file__), 'services.yaml')).get(DOMAIN)
# Register services for modbus
hass.services.register(DOMAIN, SERVICE_WRITE_REGISTER, write_register,
schema=SERVICE_WRITE_REGISTER_SCHEMA)
hass.services.register(
DOMAIN, SERVICE_WRITE_REGISTER, write_register,
descriptions.get(SERVICE_WRITE_REGISTER),
schema=SERVICE_WRITE_REGISTER_SCHEMA)
hass.services.register(
DOMAIN, SERVICE_WRITE_COIL, write_coil,
descriptions.get(SERVICE_WRITE_COIL),
schema=SERVICE_WRITE_COIL_SCHEMA)
def write_register(service):
"""Write modbus registers."""
@ -125,6 +142,13 @@ def setup(hass, config):
address,
int(float(value)))
def write_coil(service):
"""Write modbus coil."""
unit = service.data.get(ATTR_UNIT)
address = service.data.get(ATTR_ADDRESS)
state = service.data.get(ATTR_STATE)
HUB.write_coil(unit, address, state)
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_modbus)
return True

View file

@ -117,17 +117,20 @@ class ModbusRegisterSensor(Entity):
self._register,
self._count)
val = 0
if not result:
try:
registers = result.registers
except AttributeError:
_LOGGER.error("No response from modbus slave %s register %s",
self._slave, self._register)
return
if self._data_type == DATA_TYPE_FLOAT:
byte_string = b''.join(
[x.to_bytes(2, byteorder='big') for x in result.registers]
[x.to_bytes(2, byteorder='big') for x in registers]
)
val = struct.unpack(">f", byte_string)[0]
elif self._data_type == DATA_TYPE_INT:
for i, res in enumerate(result.registers):
for i, res in enumerate(registers):
val += res * (2**(i*16))
self._value = format(
self._scale * val + self._offset, '.{}f'.format(self._precision))

View file

@ -483,3 +483,28 @@ apple_tv:
apple_tv_scan:
description: Scan for Apple TV devices.
modbus:
write_register:
description: Write to a modbus holding register
fields:
unit:
description: Address of the modbus unit
example: 21
address:
description: Address of the holding register to write to
example: 0
value:
description: Value to write
example: 0
write_coil:
description: Write to a modbus coil
fields:
unit:
description: Address of the modbus unit
example: 21
address:
description: Address of the register to read
example: 0
state:
description: State to write
example: false

View file

@ -70,10 +70,10 @@ class ModbusCoilSwitch(ToggleEntity):
def update(self):
"""Update the state of the switch."""
result = modbus.HUB.read_coils(self._slave, self._coil, 1)
if not result:
try:
self._is_on = bool(result.bits[0])
except AttributeError:
_LOGGER.error(
'No response from modbus slave %s coil %s',
self._slave,
self._coil)
return
self._is_on = bool(result.bits[0])