From 9131fb39fe64f77f12447678ab2b7d29278ec74b Mon Sep 17 00:00:00 2001 From: jan iversen Date: Thu, 24 Feb 2022 13:35:45 +0100 Subject: [PATCH] Allow "slave" parameter in modbus service calls (#66874) * Allow "slave" parameter in modbus service calls. --- homeassistant/components/modbus/const.py | 1 + homeassistant/components/modbus/modbus.py | 16 +++++++++++++--- homeassistant/components/modbus/services.yaml | 18 +++++++++--------- tests/components/modbus/test_init.py | 12 ++++++++++-- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/modbus/const.py b/homeassistant/components/modbus/const.py index 934d14012f8..82c5245da80 100644 --- a/homeassistant/components/modbus/const.py +++ b/homeassistant/components/modbus/const.py @@ -69,6 +69,7 @@ UDP = "udp" ATTR_ADDRESS = "address" ATTR_HUB = "hub" ATTR_UNIT = "unit" +ATTR_SLAVE = "slave" ATTR_VALUE = "value" ATTR_STATE = "state" ATTR_TEMPERATURE = "temperature" diff --git a/homeassistant/components/modbus/modbus.py b/homeassistant/components/modbus/modbus.py index 20083bb3d1c..9d73f0afcc3 100644 --- a/homeassistant/components/modbus/modbus.py +++ b/homeassistant/components/modbus/modbus.py @@ -39,6 +39,7 @@ from homeassistant.helpers.typing import ConfigType from .const import ( ATTR_ADDRESS, ATTR_HUB, + ATTR_SLAVE, ATTR_STATE, ATTR_UNIT, ATTR_VALUE, @@ -156,7 +157,11 @@ async def async_modbus_setup( async def async_write_register(service: ServiceCall) -> None: """Write Modbus registers.""" - unit = int(float(service.data[ATTR_UNIT])) + unit = 0 + if ATTR_UNIT in service.data: + unit = int(float(service.data[ATTR_UNIT])) + if ATTR_SLAVE in service.data: + unit = int(float(service.data[ATTR_SLAVE])) address = int(float(service.data[ATTR_ADDRESS])) value = service.data[ATTR_VALUE] hub = hub_collect[ @@ -173,7 +178,11 @@ async def async_modbus_setup( async def async_write_coil(service: ServiceCall) -> None: """Write Modbus coil.""" - unit = service.data[ATTR_UNIT] + unit = 0 + if ATTR_UNIT in service.data: + unit = int(float(service.data[ATTR_UNIT])) + if ATTR_SLAVE in service.data: + unit = int(float(service.data[ATTR_SLAVE])) address = service.data[ATTR_ADDRESS] state = service.data[ATTR_STATE] hub = hub_collect[ @@ -195,7 +204,8 @@ async def async_modbus_setup( schema=vol.Schema( { vol.Optional(ATTR_HUB, default=DEFAULT_HUB): cv.string, - vol.Required(ATTR_UNIT): cv.positive_int, + vol.Exclusive(ATTR_SLAVE, "unit"): cv.positive_int, + vol.Exclusive(ATTR_UNIT, "unit"): cv.positive_int, vol.Required(ATTR_ADDRESS): cv.positive_int, vol.Required(x_write[2]): vol.Any( cv.positive_int, vol.All(cv.ensure_list, [x_write[3]]) diff --git a/homeassistant/components/modbus/services.yaml b/homeassistant/components/modbus/services.yaml index 87e8b98fa21..373954e25df 100644 --- a/homeassistant/components/modbus/services.yaml +++ b/homeassistant/components/modbus/services.yaml @@ -14,13 +14,13 @@ write_coil: name: State description: State to write. required: true - example: false + example: "0 or [1,0]" selector: object: - unit: - name: Unit - description: Address of the modbus unit. - required: true + slave: + name: Slave + description: Address of the modbus unit/slave. + required: false selector: number: min: 1 @@ -44,10 +44,10 @@ write_register: number: min: 0 max: 65535 - unit: - name: Unit - description: Address of the modbus unit. - required: true + slave: + name: Slave + description: Address of the modbus unit/slave. + required: false selector: number: min: 1 diff --git a/tests/components/modbus/test_init.py b/tests/components/modbus/test_init.py index 9bd0a2caa6d..ba5a9291d81 100644 --- a/tests/components/modbus/test_init.py +++ b/tests/components/modbus/test_init.py @@ -25,6 +25,7 @@ from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAI from homeassistant.components.modbus.const import ( ATTR_ADDRESS, ATTR_HUB, + ATTR_SLAVE, ATTR_STATE, ATTR_UNIT, ATTR_VALUE, @@ -484,8 +485,15 @@ SERVICE = "service" {VALUE: ModbusException("fail write_"), DATA: "Pymodbus:"}, ], ) +@pytest.mark.parametrize( + "do_unit", + [ + ATTR_UNIT, + ATTR_SLAVE, + ], +) async def test_pb_service_write( - hass, do_write, do_return, caplog, mock_modbus_with_pymodbus + hass, do_write, do_return, do_unit, caplog, mock_modbus_with_pymodbus ): """Run test for service write_register.""" @@ -498,7 +506,7 @@ async def test_pb_service_write( data = { ATTR_HUB: TEST_MODBUS_NAME, - ATTR_UNIT: 17, + do_unit: 17, ATTR_ADDRESS: 16, do_write[DATA]: do_write[VALUE], }