From f82b63483a1e460a9838bd43735de72184757217 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 | 64 ++++++++++------- homeassistant/components/switch/modbus.py | 83 +++++++++++++++-------- 2 files changed, 94 insertions(+), 53 deletions(-) diff --git a/homeassistant/components/sensor/modbus.py b/homeassistant/components/sensor/modbus.py index 90593875a54..b7b122d8d66 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) @@ -124,13 +138,17 @@ class ModbusSensor(Entity): return attr def update(self): - result = modbus.NETWORK.read_holding_registers(unit=self.slave, + if self._coil: + result = modbus.NETWORK.read_coils(self.register, 1) + self._value = result.bits[0] + 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)) - if self.bit: - self._value = val & (0x0001 << self.bit) - else: - self._value = val + 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..41c45597de4 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,28 +48,38 @@ 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 - + def __str__(self): return "%s: %s" % (self.name, self.state) @@ -98,27 +112,36 @@ class ModbusSwitch(ToggleEntity): 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) + 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) + if self._coil: + r = 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) + 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)