diff --git a/homeassistant/components/binary_sensor/modbus.py b/homeassistant/components/binary_sensor/modbus.py index fb6f84c318d..00dc588a468 100644 --- a/homeassistant/components/binary_sensor/modbus.py +++ b/homeassistant/components/binary_sensor/modbus.py @@ -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) diff --git a/homeassistant/components/modbus.py b/homeassistant/components/modbus.py index aa958715a48..9075eab2cdd 100644 --- a/homeassistant/components/modbus.py +++ b/homeassistant/components/modbus.py @@ -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 diff --git a/homeassistant/components/sensor/modbus.py b/homeassistant/components/sensor/modbus.py index d8a5be9ab49..9453daea413 100644 --- a/homeassistant/components/sensor/modbus.py +++ b/homeassistant/components/sensor/modbus.py @@ -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)) diff --git a/homeassistant/components/services.yaml b/homeassistant/components/services.yaml index db71b2322fa..97e947fff06 100644 --- a/homeassistant/components/services.yaml +++ b/homeassistant/components/services.yaml @@ -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 diff --git a/homeassistant/components/switch/modbus.py b/homeassistant/components/switch/modbus.py index 95168d5b830..e6342617f28 100644 --- a/homeassistant/components/switch/modbus.py +++ b/homeassistant/components/switch/modbus.py @@ -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])