Convert if/elif chains to dicts in modbus (#51962)

pull/51977/head
jan iversen 2021-06-18 11:20:44 +02:00 committed by GitHub
parent c149ecf2cc
commit bc329cb602
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 112 deletions

View File

@ -69,7 +69,9 @@ from .const import (
CONF_RETRIES,
CONF_RETRY_ON_EMPTY,
CONF_REVERSE_ORDER,
CONF_RTUOVERTCP,
CONF_SCALE,
CONF_SERIAL,
CONF_STATE_CLOSED,
CONF_STATE_CLOSING,
CONF_STATE_OFF,
@ -86,6 +88,8 @@ from .const import (
CONF_SWAP_WORD,
CONF_SWAP_WORD_BYTE,
CONF_TARGET_TEMP,
CONF_TCP,
CONF_UDP,
CONF_VERIFY,
CONF_WRITE_TYPE,
DATA_TYPE_CUSTOM,
@ -292,7 +296,7 @@ MODBUS_SCHEMA = vol.Schema(
SERIAL_SCHEMA = MODBUS_SCHEMA.extend(
{
vol.Required(CONF_TYPE): "serial",
vol.Required(CONF_TYPE): CONF_SERIAL,
vol.Required(CONF_BAUDRATE): cv.positive_int,
vol.Required(CONF_BYTESIZE): vol.Any(5, 6, 7, 8),
vol.Required(CONF_METHOD): vol.Any("rtu", "ascii"),
@ -306,7 +310,7 @@ ETHERNET_SCHEMA = MODBUS_SCHEMA.extend(
{
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PORT): cv.port,
vol.Required(CONF_TYPE): vol.Any("tcp", "udp", "rtuovertcp"),
vol.Required(CONF_TYPE): vol.Any(CONF_TCP, CONF_UDP, CONF_RTUOVERTCP),
}
)

View File

@ -39,7 +39,9 @@ CONF_RETRIES = "retries"
CONF_RETRY_ON_EMPTY = "retry_on_empty"
CONF_REVERSE_ORDER = "reverse_order"
CONF_PRECISION = "precision"
CONF_RTUOVERTCP = "rtuovertcp"
CONF_SCALE = "scale"
CONF_SERIAL = "serial"
CONF_STATE_CLOSED = "state_closed"
CONF_STATE_CLOSING = "state_closing"
CONF_STATE_OFF = "state_off"
@ -56,6 +58,8 @@ CONF_SWAP_NONE = "none"
CONF_SWAP_WORD = "word"
CONF_SWAP_WORD_BYTE = "word_byte"
CONF_TARGET_TEMP = "target_temp_register"
CONF_TCP = "tcp"
CONF_UDP = "udp"
CONF_VERIFY = "verify"
CONF_VERIFY_REGISTER = "verify_register"
CONF_VERIFY_STATE = "verify_state"

View File

@ -5,7 +5,6 @@ import logging
from pymodbus.client.sync import ModbusSerialClient, ModbusTcpClient, ModbusUdpClient
from pymodbus.constants import Defaults
from pymodbus.exceptions import ModbusException
from pymodbus.transaction import ModbusRtuFramer
from homeassistant.const import (
CONF_DELAY,
@ -41,7 +40,11 @@ from .const import (
CONF_PARITY,
CONF_RETRIES,
CONF_RETRY_ON_EMPTY,
CONF_RTUOVERTCP,
CONF_SERIAL,
CONF_STOPBITS,
CONF_TCP,
CONF_UDP,
DEFAULT_HUB,
MODBUS_DOMAIN as DOMAIN,
PLATFORMS,
@ -51,9 +54,53 @@ from .const import (
ENTRY_FUNC = "func"
ENTRY_ATTR = "attr"
ENTRY_NAME = "name"
_LOGGER = logging.getLogger(__name__)
PYMODBUS_CALL = {
CALL_TYPE_COIL: {
ENTRY_ATTR: "bits",
ENTRY_NAME: "read_coils",
ENTRY_FUNC: None,
},
CALL_TYPE_DISCRETE: {
ENTRY_ATTR: "bits",
ENTRY_NAME: "read_discrete_inputs",
ENTRY_FUNC: None,
},
CALL_TYPE_REGISTER_HOLDING: {
ENTRY_ATTR: "registers",
ENTRY_NAME: "read_holding_registers",
ENTRY_FUNC: None,
},
CALL_TYPE_REGISTER_INPUT: {
ENTRY_ATTR: "registers",
ENTRY_NAME: "read_input_registers",
ENTRY_FUNC: None,
},
CALL_TYPE_WRITE_COIL: {
ENTRY_ATTR: "value",
ENTRY_NAME: "write_coil",
ENTRY_FUNC: None,
},
CALL_TYPE_WRITE_COILS: {
ENTRY_ATTR: "count",
ENTRY_NAME: "write_coils",
ENTRY_FUNC: None,
},
CALL_TYPE_WRITE_REGISTER: {
ENTRY_ATTR: "value",
ENTRY_NAME: "write_register",
ENTRY_FUNC: None,
},
CALL_TYPE_WRITE_REGISTERS: {
ENTRY_ATTR: "count",
ENTRY_NAME: "write_registers",
ENTRY_FUNC: None,
},
}
async def async_modbus_setup(
hass, config, service_write_register_schema, service_write_coil_schema
@ -147,58 +194,39 @@ class ModbusHub:
self.hass = hass
self._config_name = client_config[CONF_NAME]
self._config_type = client_config[CONF_TYPE]
self._config_port = client_config[CONF_PORT]
self._config_timeout = client_config[CONF_TIMEOUT]
self._config_delay = client_config[CONF_DELAY]
self._config_reset_socket = client_config[CONF_CLOSE_COMM_ON_ERROR]
self._config_retries = client_config[CONF_RETRIES]
self._config_retry_on_empty = client_config[CONF_RETRY_ON_EMPTY]
Defaults.Timeout = client_config[CONF_TIMEOUT]
if self._config_type == "serial":
self._pb_call = PYMODBUS_CALL.copy()
self._pb_class = {
CONF_SERIAL: ModbusSerialClient,
CONF_TCP: ModbusTcpClient,
CONF_UDP: ModbusUdpClient,
CONF_RTUOVERTCP: ModbusTcpClient,
}
self._pb_params = {
"port": client_config[CONF_PORT],
"timeout": client_config[CONF_TIMEOUT],
"reset_socket": client_config[CONF_CLOSE_COMM_ON_ERROR],
"retries": client_config[CONF_RETRIES],
"retry_on_empty": client_config[CONF_RETRY_ON_EMPTY],
}
if self._config_type == CONF_SERIAL:
# serial configuration
self._config_method = client_config[CONF_METHOD]
self._config_baudrate = client_config[CONF_BAUDRATE]
self._config_stopbits = client_config[CONF_STOPBITS]
self._config_bytesize = client_config[CONF_BYTESIZE]
self._config_parity = client_config[CONF_PARITY]
self._pb_params.update(
{
"method": client_config[CONF_METHOD],
"baudrate": client_config[CONF_BAUDRATE],
"stopbits": client_config[CONF_STOPBITS],
"bytesize": client_config[CONF_BYTESIZE],
"parity": client_config[CONF_PARITY],
}
)
else:
# network configuration
self._config_host = client_config[CONF_HOST]
self._pb_params["host"] = client_config[CONF_HOST]
if self._config_type == CONF_RTUOVERTCP:
self._pb_params["host"] = "ModbusRtuFramer"
self._call_type = {
CALL_TYPE_COIL: {
ENTRY_ATTR: "bits",
ENTRY_FUNC: None,
},
CALL_TYPE_DISCRETE: {
ENTRY_ATTR: "bits",
ENTRY_FUNC: None,
},
CALL_TYPE_REGISTER_HOLDING: {
ENTRY_ATTR: "registers",
ENTRY_FUNC: None,
},
CALL_TYPE_REGISTER_INPUT: {
ENTRY_ATTR: "registers",
ENTRY_FUNC: None,
},
CALL_TYPE_WRITE_COIL: {
ENTRY_ATTR: "value",
ENTRY_FUNC: None,
},
CALL_TYPE_WRITE_COILS: {
ENTRY_ATTR: "count",
ENTRY_FUNC: None,
},
CALL_TYPE_WRITE_REGISTER: {
ENTRY_ATTR: "value",
ENTRY_FUNC: None,
},
CALL_TYPE_WRITE_REGISTERS: {
ENTRY_ATTR: "count",
ENTRY_FUNC: None,
},
}
Defaults.Timeout = client_config[CONF_TIMEOUT]
def _log_error(self, text: str, error_state=True):
log_text = f"Pymodbus: {text}"
@ -211,75 +239,19 @@ class ModbusHub:
async def async_setup(self):
"""Set up pymodbus client."""
try:
if self._config_type == "serial":
self._client = ModbusSerialClient(
method=self._config_method,
port=self._config_port,
baudrate=self._config_baudrate,
stopbits=self._config_stopbits,
bytesize=self._config_bytesize,
parity=self._config_parity,
timeout=self._config_timeout,
retries=self._config_retries,
retry_on_empty=self._config_retry_on_empty,
reset_socket=self._config_reset_socket,
)
elif self._config_type == "rtuovertcp":
self._client = ModbusTcpClient(
host=self._config_host,
port=self._config_port,
framer=ModbusRtuFramer,
timeout=self._config_timeout,
retries=self._config_retries,
retry_on_empty=self._config_retry_on_empty,
reset_socket=self._config_reset_socket,
)
elif self._config_type == "tcp":
self._client = ModbusTcpClient(
host=self._config_host,
port=self._config_port,
timeout=self._config_timeout,
retries=self._config_retries,
retry_on_empty=self._config_retry_on_empty,
reset_socket=self._config_reset_socket,
)
elif self._config_type == "udp":
self._client = ModbusUdpClient(
host=self._config_host,
port=self._config_port,
timeout=self._config_timeout,
retries=self._config_retries,
retry_on_empty=self._config_retry_on_empty,
reset_socket=self._config_reset_socket,
)
self._client = self._pb_class[self._config_type](**self._pb_params)
except ModbusException as exception_error:
self._log_error(str(exception_error), error_state=False)
return False
for entry in self._pb_call.values():
entry[ENTRY_FUNC] = getattr(self._client, entry[ENTRY_NAME])
async with self._lock:
if not await self.hass.async_add_executor_job(self._pymodbus_connect):
self._log_error("initial connect failed, no retry", error_state=False)
return False
self._call_type[CALL_TYPE_COIL][ENTRY_FUNC] = self._client.read_coils
self._call_type[CALL_TYPE_DISCRETE][
ENTRY_FUNC
] = self._client.read_discrete_inputs
self._call_type[CALL_TYPE_REGISTER_HOLDING][
ENTRY_FUNC
] = self._client.read_holding_registers
self._call_type[CALL_TYPE_REGISTER_INPUT][
ENTRY_FUNC
] = self._client.read_input_registers
self._call_type[CALL_TYPE_WRITE_COIL][ENTRY_FUNC] = self._client.write_coil
self._call_type[CALL_TYPE_WRITE_COILS][ENTRY_FUNC] = self._client.write_coils
self._call_type[CALL_TYPE_WRITE_REGISTER][
ENTRY_FUNC
] = self._client.write_register
self._call_type[CALL_TYPE_WRITE_REGISTERS][
ENTRY_FUNC
] = self._client.write_registers
# Start counting down to allow modbus requests.
if self._config_delay:
self._async_cancel_listener = async_call_later(
@ -323,11 +295,11 @@ class ModbusHub:
"""Call sync. pymodbus."""
kwargs = {"unit": unit} if unit else {}
try:
result = self._call_type[use_call][ENTRY_FUNC](address, value, **kwargs)
result = self._pb_call[use_call][ENTRY_FUNC](address, value, **kwargs)
except ModbusException as exception_error:
self._log_error(str(exception_error))
return None
if not hasattr(result, self._call_type[use_call][ENTRY_ATTR]):
if not hasattr(result, self._pb_call[use_call][ENTRY_ATTR]):
self._log_error(str(result))
return None
self._in_error = False