Add modbus sensor string data_type (#35269)

* modbus sensor: string data_type

Adds support for a string data_type. This allows the reading of holding registers that contain ascii string data

* Add modbus sensor string data_type #35269

Fingers crossed that I am putting these file in the correct location this time

* Delete const.py

* Delete sensor.py

* Add files via upload

* modbus sensor - add string support. Upload from local dev environment

* fix executable stauts

* fix flake8 failure
This commit is contained in:
Brad Keifer 2020-05-08 19:30:05 +10:00 committed by GitHub
parent e696c08db0
commit 4663845ebc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 9 deletions

View File

@ -25,6 +25,7 @@ DATA_TYPE_CUSTOM = "custom"
DATA_TYPE_FLOAT = "float"
DATA_TYPE_INT = "int"
DATA_TYPE_UINT = "uint"
DATA_TYPE_STRING = "string"
# call types
CALL_TYPE_COIL = "coil"

View File

@ -34,6 +34,7 @@ from .const import (
DATA_TYPE_CUSTOM,
DATA_TYPE_FLOAT,
DATA_TYPE_INT,
DATA_TYPE_STRING,
DATA_TYPE_UINT,
DEFAULT_HUB,
MODBUS_DOMAIN,
@ -69,7 +70,13 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
vol.Required(CONF_REGISTER): cv.positive_int,
vol.Optional(CONF_COUNT, default=1): cv.positive_int,
vol.Optional(CONF_DATA_TYPE, default=DATA_TYPE_INT): vol.In(
[DATA_TYPE_INT, DATA_TYPE_UINT, DATA_TYPE_FLOAT, DATA_TYPE_CUSTOM]
[
DATA_TYPE_INT,
DATA_TYPE_UINT,
DATA_TYPE_FLOAT,
DATA_TYPE_STRING,
DATA_TYPE_CUSTOM,
]
),
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_HUB, default=DEFAULT_HUB): cv.string,
@ -98,7 +105,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
for register in config[CONF_REGISTERS]:
structure = ">i"
if register[CONF_DATA_TYPE] != DATA_TYPE_CUSTOM:
if register[CONF_DATA_TYPE] == DATA_TYPE_STRING:
structure = str(register[CONF_COUNT] * 2) + "s"
elif register[CONF_DATA_TYPE] != DATA_TYPE_CUSTOM:
try:
structure = (
f">{data_types[register[CONF_DATA_TYPE]][register[CONF_COUNT]]}"
@ -142,6 +151,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
register[CONF_OFFSET],
structure,
register[CONF_PRECISION],
register[CONF_DATA_TYPE],
register.get(CONF_DEVICE_CLASS),
)
)
@ -168,6 +178,7 @@ class ModbusRegisterSensor(RestoreEntity):
offset,
structure,
precision,
data_type,
device_class,
):
"""Initialize the modbus register sensor."""
@ -183,6 +194,7 @@ class ModbusRegisterSensor(RestoreEntity):
self._offset = offset
self._precision = precision
self._structure = structure
self._data_type = data_type
self._device_class = device_class
self._value = None
self._available = True
@ -243,13 +255,16 @@ class ModbusRegisterSensor(RestoreEntity):
registers.reverse()
byte_string = b"".join([x.to_bytes(2, byteorder="big") for x in registers])
val = struct.unpack(self._structure, byte_string)[0]
val = self._scale * val + self._offset
if isinstance(val, int):
self._value = str(val)
if self._precision > 0:
self._value += "." + "0" * self._precision
if self._data_type != DATA_TYPE_STRING:
val = struct.unpack(self._structure, byte_string)[0]
val = self._scale * val + self._offset
if isinstance(val, int):
self._value = str(val)
if self._precision > 0:
self._value += "." + "0" * self._precision
else:
self._value = f"{val:.{self._precision}f}"
else:
self._value = f"{val:.{self._precision}f}"
self._value = byte_string.decode()
self._available = True

View File

@ -13,6 +13,7 @@ from homeassistant.components.modbus.const import (
CONF_SCALE,
DATA_TYPE_FLOAT,
DATA_TYPE_INT,
DATA_TYPE_STRING,
DATA_TYPE_UINT,
)
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
@ -357,3 +358,23 @@ async def test_float_data_type(hass, mock_hub):
register_words=[16286, 1617],
expected="1.23457",
)
async def test_string_data_type(hass, mock_hub):
"""Test byte string register data type."""
register_config = {
CONF_COUNT: 8,
CONF_REGISTER_TYPE: CALL_TYPE_REGISTER_HOLDING,
CONF_DATA_TYPE: DATA_TYPE_STRING,
CONF_SCALE: 1,
CONF_OFFSET: 0,
CONF_PRECISION: 0,
}
await run_test(
hass,
mock_hub,
register_config,
SENSOR_DOMAIN,
register_words=[0x3037, 0x2D30, 0x352D, 0x3230, 0x3230, 0x2031, 0x343A, 0x3335],
expected="07-05-2020 14:35",
)