Add device_info to onewire sensors (#42309)

* Add device info

* Cleanup log
This commit is contained in:
epenet 2020-10-25 18:05:02 +01:00 committed by GitHub
parent 9a970cfe3d
commit c157a582b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 193 additions and 27 deletions

View File

@ -186,10 +186,12 @@ def get_entities(config):
for device in devices:
_LOGGER.debug("Found device: %s", device)
family = owproxy.read(f"{device}family").decode()
device_type = owproxy.read(f"{device}type").decode()
sensor_id = os.path.split(os.path.split(device)[0])[1]
dev_type = "std"
if "EF" in family:
dev_type = "HobbyBoard"
family = owproxy.read(f"{device}type").decode()
family = device_type
if family not in hb_info_from_type(dev_type):
_LOGGER.warning(
@ -198,6 +200,12 @@ def get_entities(config):
device,
)
continue
device_info = {
"identifiers": {(DOMAIN, sensor_id)},
"manufacturer": "Maxim Integrated",
"model": device_type,
"name": sensor_id,
}
for sensor_key, sensor_value in hb_info_from_type(dev_type)[family].items():
if "moisture" in sensor_key:
s_id = sensor_key.split("_")[1]
@ -206,13 +214,13 @@ def get_entities(config):
)
if is_leaf:
sensor_key = f"wetness_{s_id}"
sensor_id = os.path.split(os.path.split(device)[0])[1]
device_file = os.path.join(os.path.split(device)[0], sensor_value)
entities.append(
OneWireProxy(
device_names.get(sensor_id, sensor_id),
device_file,
sensor_key,
device_info,
owproxy,
)
)
@ -232,12 +240,19 @@ def get_entities(config):
)
continue
device_info = {
"identifiers": {(DOMAIN, sensor_id)},
"manufacturer": "Maxim Integrated",
"model": family,
"name": sensor_id,
}
device_file = f"/sys/bus/w1/devices/{sensor_id}/w1_slave"
entities.append(
OneWireDirect(
device_names.get(sensor_id, sensor_id),
device_file,
"temperature",
device_info,
p1sensor,
)
)
@ -286,12 +301,13 @@ def get_entities(config):
class OneWire(Entity):
"""Implementation of a 1-Wire sensor."""
def __init__(self, name, device_file, sensor_type):
def __init__(self, name, device_file, sensor_type, device_info=None):
"""Initialize the sensor."""
self._name = f"{name} {sensor_type.capitalize()}"
self._device_file = device_file
self._device_class = SENSOR_TYPES[sensor_type][2]
self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self._device_info = device_info
self._state = None
self._value_raw = None
@ -327,13 +343,18 @@ class OneWire(Entity):
"""Return a unique ID."""
return self._device_file
@property
def device_info(self) -> Optional[Dict[str, Any]]:
"""Return device specific attributes."""
return self._device_info
class OneWireProxy(OneWire):
"""Implementation of a 1-Wire sensor through owserver."""
def __init__(self, name, device_file, sensor_type, owproxy):
def __init__(self, name, device_file, sensor_type, device_info, owproxy):
"""Initialize the sensor."""
super().__init__(name, device_file, sensor_type)
super().__init__(name, device_file, sensor_type, device_info)
self._owproxy = owproxy
def _read_value_ownet(self):
@ -358,9 +379,9 @@ class OneWireProxy(OneWire):
class OneWireDirect(OneWire):
"""Implementation of a 1-Wire sensor directly connected to RPI GPIO."""
def __init__(self, name, device_file, sensor_type, owsensor):
def __init__(self, name, device_file, sensor_type, device_info, owsensor):
"""Initialize the sensor."""
super().__init__(name, device_file, sensor_type)
super().__init__(name, device_file, sensor_type, device_info)
self._owsensor = owsensor
def update(self):

View File

@ -25,7 +25,7 @@ from homeassistant.const import (
from homeassistant.setup import async_setup_component
from tests.async_mock import patch
from tests.common import mock_registry
from tests.common import mock_device_registry, mock_registry
MOCK_CONFIG = {
SENSOR_DOMAIN: {
@ -39,8 +39,22 @@ MOCK_CONFIG = {
}
MOCK_DEVICE_SENSORS = {
"00.111111111111": {"sensors": []},
"00.111111111111": {
"inject_reads": [
b"", # read device type
],
"sensors": [],
},
"10.111111111111": {
"inject_reads": [
b"DS18S20", # read device type
],
"device_info": {
"identifiers": {(DOMAIN, "10.111111111111")},
"manufacturer": "Maxim Integrated",
"model": "DS18S20",
"name": "10.111111111111",
},
"sensors": [
{
"entity_id": "sensor.my_ds18b20_temperature",
@ -50,9 +64,18 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"12.111111111111": {
"inject_reads": [
b"DS2406", # read device type
],
"device_info": {
"identifiers": {(DOMAIN, "12.111111111111")},
"manufacturer": "Maxim Integrated",
"model": "DS2406",
"name": "12.111111111111",
},
"sensors": [
{
"entity_id": "sensor.12_111111111111_temperature",
@ -70,9 +93,18 @@ MOCK_DEVICE_SENSORS = {
"unit": PRESSURE_MBAR,
"class": DEVICE_CLASS_PRESSURE,
},
]
],
},
"1D.111111111111": {
"inject_reads": [
b"DS2423", # read device type
],
"device_info": {
"identifiers": {(DOMAIN, "1D.111111111111")},
"manufacturer": "Maxim Integrated",
"model": "DS2423",
"name": "1D.111111111111",
},
"sensors": [
{
"entity_id": "sensor.1d_111111111111_counter_a",
@ -90,9 +122,18 @@ MOCK_DEVICE_SENSORS = {
"unit": "count",
"class": None,
},
]
],
},
"22.111111111111": {
"inject_reads": [
b"DS1822", # read device type
],
"device_info": {
"identifiers": {(DOMAIN, "22.111111111111")},
"manufacturer": "Maxim Integrated",
"model": "DS1822",
"name": "22.111111111111",
},
"sensors": [
{
"entity_id": "sensor.22_111111111111_temperature",
@ -102,9 +143,18 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"26.111111111111": {
"inject_reads": [
b"DS2438", # read device type
],
"device_info": {
"identifiers": {(DOMAIN, "26.111111111111")},
"manufacturer": "Maxim Integrated",
"model": "DS2438",
"name": "26.111111111111",
},
"sensors": [
{
"entity_id": "sensor.26_111111111111_temperature",
@ -194,9 +244,18 @@ MOCK_DEVICE_SENSORS = {
"unit": ELECTRICAL_CURRENT_AMPERE,
"class": DEVICE_CLASS_CURRENT,
},
]
],
},
"28.111111111111": {
"inject_reads": [
b"DS18B20", # read device type
],
"device_info": {
"identifiers": {(DOMAIN, "28.111111111111")},
"manufacturer": "Maxim Integrated",
"model": "DS18B20",
"name": "28.111111111111",
},
"sensors": [
{
"entity_id": "sensor.28_111111111111_temperature",
@ -206,9 +265,18 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"3B.111111111111": {
"inject_reads": [
b"DS1825", # read device type
],
"device_info": {
"identifiers": {(DOMAIN, "3B.111111111111")},
"manufacturer": "Maxim Integrated",
"model": "DS1825",
"name": "3B.111111111111",
},
"sensors": [
{
"entity_id": "sensor.3b_111111111111_temperature",
@ -218,9 +286,18 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"42.111111111111": {
"inject_reads": [
b"DS28EA00", # read device type
],
"device_info": {
"identifiers": {(DOMAIN, "42.111111111111")},
"manufacturer": "Maxim Integrated",
"model": "DS28EA00",
"name": "42.111111111111",
},
"sensors": [
{
"entity_id": "sensor.42_111111111111_temperature",
@ -230,12 +307,18 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"EF.111111111111": {
"inject_reads": [
b"HobbyBoards_EF", # read type
],
"device_info": {
"identifiers": {(DOMAIN, "EF.111111111111")},
"manufacturer": "Maxim Integrated",
"model": "HobbyBoards_EF",
"name": "EF.111111111111",
},
"sensors": [
{
"entity_id": "sensor.ef_111111111111_humidity",
@ -271,6 +354,12 @@ MOCK_DEVICE_SENSORS = {
b" 0", # read is_leaf_2
b" 0", # read is_leaf_3
],
"device_info": {
"identifiers": {(DOMAIN, "EF.111111111112")},
"manufacturer": "Maxim Integrated",
"model": "HB_MOISTURE_METER",
"name": "EF.111111111112",
},
"sensors": [
{
"entity_id": "sensor.ef_111111111112_wetness_0",
@ -313,13 +402,16 @@ MOCK_DEVICE_SENSORS = {
async def test_owserver_setup_valid_device(hass, device_id):
"""Test for 1-Wire device."""
entity_registry = mock_registry(hass)
device_registry = mock_device_registry(hass)
mock_device_sensor = MOCK_DEVICE_SENSORS[device_id]
dir_return_value = [f"/{device_id}/"]
read_side_effect = [device_id[0:2].encode()]
if "inject_reads" in MOCK_DEVICE_SENSORS[device_id]:
read_side_effect += MOCK_DEVICE_SENSORS[device_id]["inject_reads"]
if "inject_reads" in mock_device_sensor:
read_side_effect += mock_device_sensor["inject_reads"]
expected_sensors = MOCK_DEVICE_SENSORS[device_id]["sensors"]
expected_sensors = mock_device_sensor["sensors"]
for expected_sensor in expected_sensors:
read_side_effect.append(expected_sensor["injected_value"])
@ -335,6 +427,16 @@ async def test_owserver_setup_valid_device(hass, device_id):
assert len(entity_registry.entities) == len(expected_sensors)
if len(expected_sensors) > 0:
device_info = mock_device_sensor["device_info"]
assert len(device_registry.devices) == 1
registry_entry = device_registry.async_get_device({(DOMAIN, device_id)}, set())
assert registry_entry is not None
assert registry_entry.identifiers == {(DOMAIN, device_id)}
assert registry_entry.manufacturer == device_info["manufacturer"]
assert registry_entry.name == device_info["name"]
assert registry_entry.model == device_info["model"]
for expected_sensor in expected_sensors:
entity_id = expected_sensor["entity_id"]
registry_entry = entity_registry.entities.get(entity_id)

View File

@ -8,7 +8,7 @@ from homeassistant.const import DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS
from homeassistant.setup import async_setup_component
from tests.async_mock import patch
from tests.common import mock_registry
from tests.common import mock_device_registry, mock_registry
MOCK_CONFIG = {
SENSOR_DOMAIN: {
@ -23,6 +23,12 @@ MOCK_CONFIG = {
MOCK_DEVICE_SENSORS = {
"00-111111111111": {"sensors": []},
"10-111111111111": {
"device_info": {
"identifiers": {(DOMAIN, "10-111111111111")},
"manufacturer": "Maxim Integrated",
"model": "10",
"name": "10-111111111111",
},
"sensors": [
{
"entity_id": "sensor.my_ds18b20_temperature",
@ -32,11 +38,17 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"12-111111111111": {"sensors": []},
"1D-111111111111": {"sensors": []},
"22-111111111111": {
"device_info": {
"identifiers": {(DOMAIN, "22-111111111111")},
"manufacturer": "Maxim Integrated",
"model": "22",
"name": "22-111111111111",
},
"sensors": [
{
"entity_id": "sensor.22_111111111111_temperature",
@ -46,10 +58,16 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"26-111111111111": {"sensors": []},
"28-111111111111": {
"device_info": {
"identifiers": {(DOMAIN, "28-111111111111")},
"manufacturer": "Maxim Integrated",
"model": "28",
"name": "28-111111111111",
},
"sensors": [
{
"entity_id": "sensor.28_111111111111_temperature",
@ -59,9 +77,15 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"3B-111111111111": {
"device_info": {
"identifiers": {(DOMAIN, "3B-111111111111")},
"manufacturer": "Maxim Integrated",
"model": "3B",
"name": "3B-111111111111",
},
"sensors": [
{
"entity_id": "sensor.3b_111111111111_temperature",
@ -71,9 +95,15 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"42-111111111111": {
"device_info": {
"identifiers": {(DOMAIN, "42-111111111111")},
"manufacturer": "Maxim Integrated",
"model": "42",
"name": "42-111111111111",
},
"sensors": [
{
"entity_id": "sensor.42_111111111111_temperature",
@ -83,7 +113,7 @@ MOCK_DEVICE_SENSORS = {
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
},
]
],
},
"EF-111111111111": {
"sensors": [],
@ -98,10 +128,13 @@ MOCK_DEVICE_SENSORS = {
async def test_onewiredirect_setup_valid_device(hass, device_id):
"""Test that sysbus config entry works correctly."""
entity_registry = mock_registry(hass)
device_registry = mock_device_registry(hass)
mock_device_sensor = MOCK_DEVICE_SENSORS[device_id]
glob_result = [f"/{DEFAULT_SYSBUS_MOUNT_DIR}/{device_id}"]
read_side_effect = []
expected_sensors = MOCK_DEVICE_SENSORS[device_id]["sensors"]
expected_sensors = mock_device_sensor["sensors"]
for expected_sensor in expected_sensors:
read_side_effect.append(expected_sensor["injected_value"])
@ -119,6 +152,16 @@ async def test_onewiredirect_setup_valid_device(hass, device_id):
assert len(entity_registry.entities) == len(expected_sensors)
if len(expected_sensors) > 0:
device_info = mock_device_sensor["device_info"]
assert len(device_registry.devices) == 1
registry_entry = device_registry.async_get_device({(DOMAIN, device_id)}, set())
assert registry_entry is not None
assert registry_entry.identifiers == {(DOMAIN, device_id)}
assert registry_entry.manufacturer == device_info["manufacturer"]
assert registry_entry.name == device_info["name"]
assert registry_entry.model == device_info["model"]
for expected_sensor in expected_sensors:
entity_id = expected_sensor["entity_id"]
registry_entry = entity_registry.entities.get(entity_id)