From 1b3a45aba9aba980c7d31a9003e9885e271c7a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Esp=C3=ADndola?= Date: Wed, 29 Jul 2015 14:04:32 -0300 Subject: [PATCH] Modbus coil support --- homeassistant/components/sensor/modbus.py | 72 ++++++++++-------- homeassistant/components/switch/modbus.py | 91 ++++++++++++++--------- 2 files changed, 100 insertions(+), 63 deletions(-) diff --git a/homeassistant/components/sensor/modbus.py b/homeassistant/components/sensor/modbus.py index 90593875a54..7893ee5935e 100644 --- a/homeassistant/components/sensor/modbus.py +++ b/homeassistant/components/sensor/modbus.py @@ -18,6 +18,9 @@ sensor: name: My boolean sensor 2: name: My other boolean sensor + coils: + 0: + name: My coil switch VARIABLES: @@ -25,6 +28,7 @@ VARIABLES: - "unit" = unit to attach to value (optional, ignored for boolean sensors) - "registers" contains a list of relevant registers to read from it can contain a "bits" section, listing relevant bits + - "coils" contains a list of relevant coils to read from - each named register will create an integer sensor - each named bit will create a boolean sensor @@ -49,21 +53,30 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error("No slave number provided for serial Modbus") return False registers = config.get("registers") - for regnum, register in registers.items(): - if register.get("name"): - sensors.append(ModbusSensor(register.get("name"), + if registers: + for regnum, register in registers.items(): + if register.get("name"): + sensors.append(ModbusSensor(register.get("name"), + slave, + regnum, + None, + register.get("unit"))) + if register.get("bits"): + bits = register.get("bits") + for bitnum, bit in bits.items(): + if bit.get("name"): + sensors.append(ModbusSensor(bit.get("name"), + slave, + regnum, + bitnum)) + coils = config.get("coils") + if coils: + for coilnum, coil in coils.items(): + sensors.append(ModbusSensor(coil.get("name"), slave, - regnum, - None, - register.get("unit"))) - if register.get("bits"): - bits = register.get("bits") - for bitnum, bit in bits.items(): - if bit.get("name"): - sensors.append(ModbusSensor(bit.get("name"), - slave, - regnum, - bitnum)) + coilnum, + coil=True)) + add_devices(sensors) @@ -71,13 +84,14 @@ class ModbusSensor(Entity): # pylint: disable=too-many-arguments """ Represents a Modbus Sensor """ - def __init__(self, name, slave, register, bit=None, unit=None): + def __init__(self, name, slave, register, bit=None, unit=None, coil=False): self._name = name self.slave = int(slave) if slave else 1 self.register = int(register) self.bit = int(bit) if bit else None self._value = None self._unit = unit + self._coil = coil def __str__(self): return "%s: %s" % (self.name, self.state) @@ -118,19 +132,19 @@ class ModbusSensor(Entity): else: return self._unit - @property - def state_attributes(self): - attr = super().state_attributes - return attr - def update(self): - result = modbus.NETWORK.read_holding_registers(unit=self.slave, - address=self.register, - count=1) - val = 0 - for i, res in enumerate(result.registers): - val += res * (2**(i*16)) - if self.bit: - self._value = val & (0x0001 << self.bit) + """ Update the state of the sensor. """ + if self._coil: + result = modbus.NETWORK.read_coils(self.register, 1) + self._value = result.bits[0] else: - self._value = val + result = modbus.NETWORK.read_holding_registers( + unit=self.slave, address=self.register, + count=1) + val = 0 + for i, res in enumerate(result.registers): + val += res * (2**(i*16)) + if self.bit: + self._value = val & (0x0001 << self.bit) + else: + self._value = val diff --git a/homeassistant/components/switch/modbus.py b/homeassistant/components/switch/modbus.py index 6513ba71f4a..21a4e0087c2 100644 --- a/homeassistant/components/switch/modbus.py +++ b/homeassistant/components/switch/modbus.py @@ -18,12 +18,16 @@ sensor: name: My switch 2: name: My other switch + coils: + 0: + name: My coil switch VARIABLES: - "slave" = slave number (ignored and can be omitted if not serial Modbus) - "registers" contains a list of relevant registers to read from - it must contain a "bits" section, listing relevant bits + - "coils" contains a list of relevant coils to read from/write to - each named bit will create a switch """ @@ -44,25 +48,35 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error("No slave number provided for serial Modbus") return False registers = config.get("registers") - for regnum, register in registers.items(): - bits = register.get("bits") - for bitnum, bit in bits.items(): - if bit.get("name"): - switches.append(ModbusSwitch(bit.get("name"), - slave, - regnum, - bitnum)) + if registers: + for regnum, register in registers.items(): + bits = register.get("bits") + for bitnum, bit in bits.items(): + if bit.get("name"): + switches.append(ModbusSwitch(bit.get("name"), + slave, + regnum, + bitnum)) + coils = config.get("coils") + if coils: + for coilnum, coil in coils.items(): + switches.append(ModbusSwitch(coil.get("name"), + slave, + coilnum, + 0, + coil=True)) add_devices(switches) class ModbusSwitch(ToggleEntity): """ Represents a Modbus switch. """ - def __init__(self, name, slave, register, bit): + def __init__(self, name, slave, register, bit, coil=False): self._name = name self.slave = int(slave) if slave else 1 self.register = int(register) self.bit = int(bit) + self._coil = coil self._is_on = None self.register_value = None @@ -92,33 +106,42 @@ class ModbusSwitch(ToggleEntity): """ Get the name of the switch. """ return self._name - @property - def state_attributes(self): - attr = super().state_attributes - return attr - def turn_on(self, **kwargs): - if self.register_value is None: - self.update() - val = self.register_value | (0x0001 << self.bit) - modbus.NETWORK.write_register(unit=self.slave, - address=self.register, - value=val) + """ Set switch on. """ + if self._coil: + modbus.NETWORK.write_coil(self.register, True) + else: + if self.register_value is None: + self.update() + val = self.register_value | (0x0001 << self.bit) + modbus.NETWORK.write_register(unit=self.slave, + address=self.register, + value=val) def turn_off(self, **kwargs): - if self.register_value is None: - self.update() - val = self.register_value & ~(0x0001 << self.bit) - modbus.NETWORK.write_register(unit=self.slave, - address=self.register, - value=val) + """ Set switch off. """ + if self._coil: + modbus.NETWORK.write_coil(self.register, False) + else: + if self.register_value is None: + self.update() + val = self.register_value & ~(0x0001 << self.bit) + modbus.NETWORK.write_register(unit=self.slave, + address=self.register, + value=val) def update(self): - result = modbus.NETWORK.read_holding_registers(unit=self.slave, - address=self.register, - count=1) - val = 0 - for i, res in enumerate(result.registers): - val += res * (2**(i*16)) - self.register_value = val - self._is_on = (val & (0x0001 << self.bit) > 0) + """ Update the state of the switch. """ + if self._coil: + result = modbus.NETWORK.read_coils(self.register, 1) + self.register_value = result.bits[0] + self._is_on = self.register_value + else: + result = modbus.NETWORK.read_holding_registers( + unit=self.slave, address=self.register, + count=1) + val = 0 + for i, res in enumerate(result.registers): + val += res * (2**(i*16)) + self.register_value = val + self._is_on = (val & (0x0001 << self.bit) > 0)