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:
parent
9bc5cd2d4b
commit
c48c2b00a8
5 changed files with 69 additions and 10 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
Loading…
Add table
Reference in a new issue