mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 22:27:07 +00:00
Add pymodbus exception handling and isolate pymodbus to class modbusHub (#49052)
This commit is contained in:
parent
05755c27f2
commit
eb9ba527d0
@ -4,8 +4,6 @@ from __future__ import annotations
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from pymodbus.exceptions import ConnectionException, ModbusException
|
|
||||||
from pymodbus.pdu import ExceptionResponse
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import (
|
from homeassistant.components.binary_sensor import (
|
||||||
@ -165,16 +163,11 @@ class ModbusBinarySensor(BinarySensorEntity):
|
|||||||
|
|
||||||
def _update(self):
|
def _update(self):
|
||||||
"""Update the state of the sensor."""
|
"""Update the state of the sensor."""
|
||||||
try:
|
if self._input_type == CALL_TYPE_COIL:
|
||||||
if self._input_type == CALL_TYPE_COIL:
|
result = self._hub.read_coils(self._slave, self._address, 1)
|
||||||
result = self._hub.read_coils(self._slave, self._address, 1)
|
else:
|
||||||
else:
|
result = self._hub.read_discrete_inputs(self._slave, self._address, 1)
|
||||||
result = self._hub.read_discrete_inputs(self._slave, self._address, 1)
|
if result is None:
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
if isinstance(result, (ModbusException, ExceptionResponse)):
|
|
||||||
self._available = False
|
self._available = False
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -6,9 +6,6 @@ import logging
|
|||||||
import struct
|
import struct
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pymodbus.exceptions import ConnectionException, ModbusException
|
|
||||||
from pymodbus.pdu import ExceptionResponse
|
|
||||||
|
|
||||||
from homeassistant.components.climate import ClimateEntity
|
from homeassistant.components.climate import ClimateEntity
|
||||||
from homeassistant.components.climate.const import (
|
from homeassistant.components.climate.const import (
|
||||||
HVAC_MODE_AUTO,
|
HVAC_MODE_AUTO,
|
||||||
@ -212,7 +209,11 @@ class ModbusThermostat(ClimateEntity):
|
|||||||
)
|
)
|
||||||
byte_string = struct.pack(self._structure, target_temperature)
|
byte_string = struct.pack(self._structure, target_temperature)
|
||||||
register_value = struct.unpack(">h", byte_string[0:2])[0]
|
register_value = struct.unpack(">h", byte_string[0:2])[0]
|
||||||
self._write_register(self._target_temperature_register, register_value)
|
self._available = self._hub.write_registers(
|
||||||
|
self._slave,
|
||||||
|
self._target_temperature_register,
|
||||||
|
register_value,
|
||||||
|
)
|
||||||
self._update()
|
self._update()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -233,20 +234,13 @@ class ModbusThermostat(ClimateEntity):
|
|||||||
|
|
||||||
def _read_register(self, register_type, register) -> float | None:
|
def _read_register(self, register_type, register) -> float | None:
|
||||||
"""Read register using the Modbus hub slave."""
|
"""Read register using the Modbus hub slave."""
|
||||||
try:
|
if register_type == CALL_TYPE_REGISTER_INPUT:
|
||||||
if register_type == CALL_TYPE_REGISTER_INPUT:
|
result = self._hub.read_input_registers(self._slave, register, self._count)
|
||||||
result = self._hub.read_input_registers(
|
else:
|
||||||
self._slave, register, self._count
|
result = self._hub.read_holding_registers(
|
||||||
)
|
self._slave, register, self._count
|
||||||
else:
|
)
|
||||||
result = self._hub.read_holding_registers(
|
if result is None:
|
||||||
self._slave, register, self._count
|
|
||||||
)
|
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
if isinstance(result, (ModbusException, ExceptionResponse)):
|
|
||||||
self._available = False
|
self._available = False
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -269,13 +263,3 @@ class ModbusThermostat(ClimateEntity):
|
|||||||
self._available = True
|
self._available = True
|
||||||
|
|
||||||
return register_value
|
return register_value
|
||||||
|
|
||||||
def _write_register(self, register, value):
|
|
||||||
"""Write holding register using the Modbus hub slave."""
|
|
||||||
try:
|
|
||||||
self._hub.write_registers(self._slave, register, value)
|
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
self._available = True
|
|
||||||
|
@ -5,9 +5,6 @@ from datetime import timedelta
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pymodbus.exceptions import ConnectionException, ModbusException
|
|
||||||
from pymodbus.pdu import ExceptionResponse
|
|
||||||
|
|
||||||
from homeassistant.components.cover import SUPPORT_CLOSE, SUPPORT_OPEN, CoverEntity
|
from homeassistant.components.cover import SUPPORT_CLOSE, SUPPORT_OPEN, CoverEntity
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_COVERS,
|
CONF_COVERS,
|
||||||
@ -187,22 +184,17 @@ class ModbusCover(CoverEntity, RestoreEntity):
|
|||||||
|
|
||||||
def _read_status_register(self) -> int | None:
|
def _read_status_register(self) -> int | None:
|
||||||
"""Read status register using the Modbus hub slave."""
|
"""Read status register using the Modbus hub slave."""
|
||||||
try:
|
if self._status_register_type == CALL_TYPE_REGISTER_INPUT:
|
||||||
if self._status_register_type == CALL_TYPE_REGISTER_INPUT:
|
result = self._hub.read_input_registers(
|
||||||
result = self._hub.read_input_registers(
|
self._slave, self._status_register, 1
|
||||||
self._slave, self._status_register, 1
|
)
|
||||||
)
|
else:
|
||||||
else:
|
result = self._hub.read_holding_registers(
|
||||||
result = self._hub.read_holding_registers(
|
self._slave, self._status_register, 1
|
||||||
self._slave, self._status_register, 1
|
)
|
||||||
)
|
if result is None:
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
self._available = False
|
||||||
return
|
return None
|
||||||
|
|
||||||
if isinstance(result, (ModbusException, ExceptionResponse)):
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
value = int(result.registers[0])
|
value = int(result.registers[0])
|
||||||
self._available = True
|
self._available = True
|
||||||
@ -211,37 +203,18 @@ class ModbusCover(CoverEntity, RestoreEntity):
|
|||||||
|
|
||||||
def _write_register(self, value):
|
def _write_register(self, value):
|
||||||
"""Write holding register using the Modbus hub slave."""
|
"""Write holding register using the Modbus hub slave."""
|
||||||
try:
|
self._available = self._hub.write_register(self._slave, self._register, value)
|
||||||
self._hub.write_register(self._slave, self._register, value)
|
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
self._available = True
|
|
||||||
|
|
||||||
def _read_coil(self) -> bool | None:
|
def _read_coil(self) -> bool | None:
|
||||||
"""Read coil using the Modbus hub slave."""
|
"""Read coil using the Modbus hub slave."""
|
||||||
try:
|
result = self._hub.read_coils(self._slave, self._coil, 1)
|
||||||
result = self._hub.read_coils(self._slave, self._coil, 1)
|
if result is None:
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
self._available = False
|
||||||
return
|
return None
|
||||||
|
|
||||||
if isinstance(result, (ModbusException, ExceptionResponse)):
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
value = bool(result.bits[0] & 1)
|
value = bool(result.bits[0] & 1)
|
||||||
self._available = True
|
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def _write_coil(self, value):
|
def _write_coil(self, value):
|
||||||
"""Write coil using the Modbus hub slave."""
|
"""Write coil using the Modbus hub slave."""
|
||||||
try:
|
self._available = self._hub.write_coil(self._slave, self._coil, value)
|
||||||
self._hub.write_coil(self._slave, self._coil, value)
|
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
self._available = True
|
|
||||||
|
@ -3,6 +3,7 @@ import logging
|
|||||||
import threading
|
import threading
|
||||||
|
|
||||||
from pymodbus.client.sync import ModbusSerialClient, ModbusTcpClient, ModbusUdpClient
|
from pymodbus.client.sync import ModbusSerialClient, ModbusTcpClient, ModbusUdpClient
|
||||||
|
from pymodbus.exceptions import ModbusException
|
||||||
from pymodbus.transaction import ModbusRtuFramer
|
from pymodbus.transaction import ModbusRtuFramer
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -37,6 +38,7 @@ from .const import (
|
|||||||
CONF_SENSOR,
|
CONF_SENSOR,
|
||||||
CONF_STOPBITS,
|
CONF_STOPBITS,
|
||||||
CONF_SWITCH,
|
CONF_SWITCH,
|
||||||
|
DEFAULT_HUB,
|
||||||
MODBUS_DOMAIN as DOMAIN,
|
MODBUS_DOMAIN as DOMAIN,
|
||||||
SERVICE_WRITE_COIL,
|
SERVICE_WRITE_COIL,
|
||||||
SERVICE_WRITE_REGISTER,
|
SERVICE_WRITE_REGISTER,
|
||||||
@ -49,8 +51,8 @@ def modbus_setup(
|
|||||||
hass, config, service_write_register_schema, service_write_coil_schema
|
hass, config, service_write_register_schema, service_write_coil_schema
|
||||||
):
|
):
|
||||||
"""Set up Modbus component."""
|
"""Set up Modbus component."""
|
||||||
hass.data[DOMAIN] = hub_collect = {}
|
|
||||||
|
|
||||||
|
hass.data[DOMAIN] = hub_collect = {}
|
||||||
for conf_hub in config[DOMAIN]:
|
for conf_hub in config[DOMAIN]:
|
||||||
hub_collect[conf_hub[CONF_NAME]] = ModbusHub(conf_hub)
|
hub_collect[conf_hub[CONF_NAME]] = ModbusHub(conf_hub)
|
||||||
|
|
||||||
@ -71,15 +73,19 @@ def modbus_setup(
|
|||||||
|
|
||||||
def stop_modbus(event):
|
def stop_modbus(event):
|
||||||
"""Stop Modbus service."""
|
"""Stop Modbus service."""
|
||||||
|
|
||||||
for client in hub_collect.values():
|
for client in hub_collect.values():
|
||||||
client.close()
|
client.close()
|
||||||
|
del client
|
||||||
|
|
||||||
def write_register(service):
|
def write_register(service):
|
||||||
"""Write Modbus registers."""
|
"""Write Modbus registers."""
|
||||||
unit = int(float(service.data[ATTR_UNIT]))
|
unit = int(float(service.data[ATTR_UNIT]))
|
||||||
address = int(float(service.data[ATTR_ADDRESS]))
|
address = int(float(service.data[ATTR_ADDRESS]))
|
||||||
value = service.data[ATTR_VALUE]
|
value = service.data[ATTR_VALUE]
|
||||||
client_name = service.data[ATTR_HUB]
|
client_name = (
|
||||||
|
service.data[ATTR_HUB] if ATTR_HUB in service.data else DEFAULT_HUB
|
||||||
|
)
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
hub_collect[client_name].write_registers(
|
hub_collect[client_name].write_registers(
|
||||||
unit, address, [int(float(i)) for i in value]
|
unit, address, [int(float(i)) for i in value]
|
||||||
@ -92,7 +98,9 @@ def modbus_setup(
|
|||||||
unit = service.data[ATTR_UNIT]
|
unit = service.data[ATTR_UNIT]
|
||||||
address = service.data[ATTR_ADDRESS]
|
address = service.data[ATTR_ADDRESS]
|
||||||
state = service.data[ATTR_STATE]
|
state = service.data[ATTR_STATE]
|
||||||
client_name = service.data[ATTR_HUB]
|
client_name = (
|
||||||
|
service.data[ATTR_HUB] if ATTR_HUB in service.data else DEFAULT_HUB
|
||||||
|
)
|
||||||
if isinstance(state, list):
|
if isinstance(state, list):
|
||||||
hub_collect[client_name].write_coils(unit, address, state)
|
hub_collect[client_name].write_coils(unit, address, state)
|
||||||
else:
|
else:
|
||||||
@ -122,6 +130,7 @@ class ModbusHub:
|
|||||||
|
|
||||||
# generic configuration
|
# generic configuration
|
||||||
self._client = None
|
self._client = None
|
||||||
|
self._in_error = False
|
||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
self._config_name = client_config[CONF_NAME]
|
self._config_name = client_config[CONF_NAME]
|
||||||
self._config_type = client_config[CONF_TYPE]
|
self._config_type = client_config[CONF_TYPE]
|
||||||
@ -140,48 +149,58 @@ class ModbusHub:
|
|||||||
# network configuration
|
# network configuration
|
||||||
self._config_host = client_config[CONF_HOST]
|
self._config_host = client_config[CONF_HOST]
|
||||||
self._config_delay = client_config[CONF_DELAY]
|
self._config_delay = client_config[CONF_DELAY]
|
||||||
if self._config_delay > 0:
|
|
||||||
_LOGGER.warning(
|
if self._config_delay > 0:
|
||||||
"Parameter delay is accepted but not used in this version"
|
_LOGGER.warning("Parameter delay is accepted but not used in this version")
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of this hub."""
|
"""Return the name of this hub."""
|
||||||
return self._config_name
|
return self._config_name
|
||||||
|
|
||||||
|
def _log_error(self, exception_error: ModbusException, error_state=True):
|
||||||
|
if self._in_error:
|
||||||
|
_LOGGER.debug(str(exception_error))
|
||||||
|
else:
|
||||||
|
_LOGGER.error(str(exception_error))
|
||||||
|
self._in_error = error_state
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
"""Set up pymodbus client."""
|
"""Set up pymodbus client."""
|
||||||
if self._config_type == "serial":
|
try:
|
||||||
self._client = ModbusSerialClient(
|
if self._config_type == "serial":
|
||||||
method=self._config_method,
|
self._client = ModbusSerialClient(
|
||||||
port=self._config_port,
|
method=self._config_method,
|
||||||
baudrate=self._config_baudrate,
|
port=self._config_port,
|
||||||
stopbits=self._config_stopbits,
|
baudrate=self._config_baudrate,
|
||||||
bytesize=self._config_bytesize,
|
stopbits=self._config_stopbits,
|
||||||
parity=self._config_parity,
|
bytesize=self._config_bytesize,
|
||||||
timeout=self._config_timeout,
|
parity=self._config_parity,
|
||||||
retry_on_empty=True,
|
timeout=self._config_timeout,
|
||||||
)
|
retry_on_empty=True,
|
||||||
elif self._config_type == "rtuovertcp":
|
)
|
||||||
self._client = ModbusTcpClient(
|
elif self._config_type == "rtuovertcp":
|
||||||
host=self._config_host,
|
self._client = ModbusTcpClient(
|
||||||
port=self._config_port,
|
host=self._config_host,
|
||||||
framer=ModbusRtuFramer,
|
port=self._config_port,
|
||||||
timeout=self._config_timeout,
|
framer=ModbusRtuFramer,
|
||||||
)
|
timeout=self._config_timeout,
|
||||||
elif self._config_type == "tcp":
|
)
|
||||||
self._client = ModbusTcpClient(
|
elif self._config_type == "tcp":
|
||||||
host=self._config_host,
|
self._client = ModbusTcpClient(
|
||||||
port=self._config_port,
|
host=self._config_host,
|
||||||
timeout=self._config_timeout,
|
port=self._config_port,
|
||||||
)
|
timeout=self._config_timeout,
|
||||||
elif self._config_type == "udp":
|
)
|
||||||
self._client = ModbusUdpClient(
|
elif self._config_type == "udp":
|
||||||
host=self._config_host,
|
self._client = ModbusUdpClient(
|
||||||
port=self._config_port,
|
host=self._config_host,
|
||||||
timeout=self._config_timeout,
|
port=self._config_port,
|
||||||
)
|
timeout=self._config_timeout,
|
||||||
|
)
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error, error_state=False)
|
||||||
|
return
|
||||||
|
|
||||||
# Connect device
|
# Connect device
|
||||||
self.connect()
|
self.connect()
|
||||||
@ -189,57 +208,115 @@ class ModbusHub:
|
|||||||
def close(self):
|
def close(self):
|
||||||
"""Disconnect client."""
|
"""Disconnect client."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._client.close()
|
try:
|
||||||
|
self._client.close()
|
||||||
|
del self._client
|
||||||
|
self._client = None
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error, error_state=False)
|
||||||
|
return
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
"""Connect client."""
|
"""Connect client."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._client.connect()
|
try:
|
||||||
|
self._client.connect()
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error, error_state=False)
|
||||||
|
return
|
||||||
|
|
||||||
def read_coils(self, unit, address, count):
|
def read_coils(self, unit, address, count):
|
||||||
"""Read coils."""
|
"""Read coils."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
kwargs = {"unit": unit} if unit else {}
|
kwargs = {"unit": unit} if unit else {}
|
||||||
return self._client.read_coils(address, count, **kwargs)
|
try:
|
||||||
|
result = self._client.read_coils(address, count, **kwargs)
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error)
|
||||||
|
return None
|
||||||
|
self._in_error = False
|
||||||
|
return result
|
||||||
|
|
||||||
def read_discrete_inputs(self, unit, address, count):
|
def read_discrete_inputs(self, unit, address, count):
|
||||||
"""Read discrete inputs."""
|
"""Read discrete inputs."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
kwargs = {"unit": unit} if unit else {}
|
kwargs = {"unit": unit} if unit else {}
|
||||||
return self._client.read_discrete_inputs(address, count, **kwargs)
|
try:
|
||||||
|
result = self._client.read_discrete_inputs(address, count, **kwargs)
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error)
|
||||||
|
return None
|
||||||
|
self._in_error = False
|
||||||
|
return result
|
||||||
|
|
||||||
def read_input_registers(self, unit, address, count):
|
def read_input_registers(self, unit, address, count):
|
||||||
"""Read input registers."""
|
"""Read input registers."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
kwargs = {"unit": unit} if unit else {}
|
kwargs = {"unit": unit} if unit else {}
|
||||||
return self._client.read_input_registers(address, count, **kwargs)
|
try:
|
||||||
|
result = self._client.read_input_registers(address, count, **kwargs)
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error)
|
||||||
|
return None
|
||||||
|
self._in_error = False
|
||||||
|
return result
|
||||||
|
|
||||||
def read_holding_registers(self, unit, address, count):
|
def read_holding_registers(self, unit, address, count):
|
||||||
"""Read holding registers."""
|
"""Read holding registers."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
kwargs = {"unit": unit} if unit else {}
|
kwargs = {"unit": unit} if unit else {}
|
||||||
return self._client.read_holding_registers(address, count, **kwargs)
|
try:
|
||||||
|
result = self._client.read_holding_registers(address, count, **kwargs)
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error)
|
||||||
|
return None
|
||||||
|
self._in_error = False
|
||||||
|
return result
|
||||||
|
|
||||||
def write_coil(self, unit, address, value):
|
def write_coil(self, unit, address, value) -> bool:
|
||||||
"""Write coil."""
|
"""Write coil."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
kwargs = {"unit": unit} if unit else {}
|
kwargs = {"unit": unit} if unit else {}
|
||||||
self._client.write_coil(address, value, **kwargs)
|
try:
|
||||||
|
self._client.write_coil(address, value, **kwargs)
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error)
|
||||||
|
return False
|
||||||
|
self._in_error = False
|
||||||
|
return True
|
||||||
|
|
||||||
def write_coils(self, unit, address, value):
|
def write_coils(self, unit, address, values) -> bool:
|
||||||
"""Write coil."""
|
"""Write coil."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
kwargs = {"unit": unit} if unit else {}
|
kwargs = {"unit": unit} if unit else {}
|
||||||
self._client.write_coils(address, value, **kwargs)
|
try:
|
||||||
|
self._client.write_coils(address, values, **kwargs)
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error)
|
||||||
|
return False
|
||||||
|
self._in_error = False
|
||||||
|
return True
|
||||||
|
|
||||||
def write_register(self, unit, address, value):
|
def write_register(self, unit, address, value) -> bool:
|
||||||
"""Write register."""
|
"""Write register."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
kwargs = {"unit": unit} if unit else {}
|
kwargs = {"unit": unit} if unit else {}
|
||||||
self._client.write_register(address, value, **kwargs)
|
try:
|
||||||
|
self._client.write_register(address, value, **kwargs)
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error)
|
||||||
|
return False
|
||||||
|
self._in_error = False
|
||||||
|
return True
|
||||||
|
|
||||||
def write_registers(self, unit, address, values):
|
def write_registers(self, unit, address, values) -> bool:
|
||||||
"""Write registers."""
|
"""Write registers."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
kwargs = {"unit": unit} if unit else {}
|
kwargs = {"unit": unit} if unit else {}
|
||||||
self._client.write_registers(address, values, **kwargs)
|
try:
|
||||||
|
self._client.write_registers(address, values, **kwargs)
|
||||||
|
except ModbusException as exception_error:
|
||||||
|
self._log_error(exception_error)
|
||||||
|
return False
|
||||||
|
self._in_error = False
|
||||||
|
return True
|
||||||
|
@ -6,8 +6,6 @@ import logging
|
|||||||
import struct
|
import struct
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pymodbus.exceptions import ConnectionException, ModbusException
|
|
||||||
from pymodbus.pdu import ExceptionResponse
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
@ -285,20 +283,15 @@ class ModbusRegisterSensor(RestoreEntity, SensorEntity):
|
|||||||
|
|
||||||
def _update(self):
|
def _update(self):
|
||||||
"""Update the state of the sensor."""
|
"""Update the state of the sensor."""
|
||||||
try:
|
if self._register_type == CALL_TYPE_REGISTER_INPUT:
|
||||||
if self._register_type == CALL_TYPE_REGISTER_INPUT:
|
result = self._hub.read_input_registers(
|
||||||
result = self._hub.read_input_registers(
|
self._slave, self._register, self._count
|
||||||
self._slave, self._register, self._count
|
)
|
||||||
)
|
else:
|
||||||
else:
|
result = self._hub.read_holding_registers(
|
||||||
result = self._hub.read_holding_registers(
|
self._slave, self._register, self._count
|
||||||
self._slave, self._register, self._count
|
)
|
||||||
)
|
if result is None:
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
if isinstance(result, (ModbusException, ExceptionResponse)):
|
|
||||||
self._available = False
|
self._available = False
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -6,8 +6,6 @@ from datetime import timedelta
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pymodbus.exceptions import ConnectionException, ModbusException
|
|
||||||
from pymodbus.pdu import ExceptionResponse
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity
|
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity
|
||||||
@ -213,13 +211,8 @@ class ModbusCoilSwitch(ModbusBaseSwitch, SwitchEntity):
|
|||||||
|
|
||||||
def _read_coil(self, coil) -> bool:
|
def _read_coil(self, coil) -> bool:
|
||||||
"""Read coil using the Modbus hub slave."""
|
"""Read coil using the Modbus hub slave."""
|
||||||
try:
|
result = self._hub.read_coils(self._slave, coil, 1)
|
||||||
result = self._hub.read_coils(self._slave, coil, 1)
|
if result is None:
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
|
||||||
return False
|
|
||||||
|
|
||||||
if isinstance(result, (ModbusException, ExceptionResponse)):
|
|
||||||
self._available = False
|
self._available = False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -231,13 +224,7 @@ class ModbusCoilSwitch(ModbusBaseSwitch, SwitchEntity):
|
|||||||
|
|
||||||
def _write_coil(self, coil, value):
|
def _write_coil(self, coil, value):
|
||||||
"""Write coil using the Modbus hub slave."""
|
"""Write coil using the Modbus hub slave."""
|
||||||
try:
|
self._available = self._hub.write_coil(self._slave, coil, value)
|
||||||
self._hub.write_coil(self._slave, coil, value)
|
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
self._available = True
|
|
||||||
|
|
||||||
|
|
||||||
class ModbusRegisterSwitch(ModbusBaseSwitch, SwitchEntity):
|
class ModbusRegisterSwitch(ModbusBaseSwitch, SwitchEntity):
|
||||||
@ -301,33 +288,21 @@ class ModbusRegisterSwitch(ModbusBaseSwitch, SwitchEntity):
|
|||||||
self.schedule_update_ha_state()
|
self.schedule_update_ha_state()
|
||||||
|
|
||||||
def _read_register(self) -> int | None:
|
def _read_register(self) -> int | None:
|
||||||
try:
|
if self._register_type == CALL_TYPE_REGISTER_INPUT:
|
||||||
if self._register_type == CALL_TYPE_REGISTER_INPUT:
|
result = self._hub.read_input_registers(
|
||||||
result = self._hub.read_input_registers(
|
self._slave, self._verify_register, 1
|
||||||
self._slave, self._verify_register, 1
|
)
|
||||||
)
|
else:
|
||||||
else:
|
result = self._hub.read_holding_registers(
|
||||||
result = self._hub.read_holding_registers(
|
self._slave, self._verify_register, 1
|
||||||
self._slave, self._verify_register, 1
|
)
|
||||||
)
|
if result is None:
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
self._available = False
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(result, (ModbusException, ExceptionResponse)):
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
self._available = True
|
self._available = True
|
||||||
|
|
||||||
return int(result.registers[0])
|
return int(result.registers[0])
|
||||||
|
|
||||||
def _write_register(self, value):
|
def _write_register(self, value):
|
||||||
"""Write holding register using the Modbus hub slave."""
|
"""Write holding register using the Modbus hub slave."""
|
||||||
try:
|
self._available = self._hub.write_register(self._slave, self._register, value)
|
||||||
self._hub.write_register(self._slave, self._register, value)
|
|
||||||
except ConnectionException:
|
|
||||||
self._available = False
|
|
||||||
return
|
|
||||||
|
|
||||||
self._available = True
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user