Add Onewire diagnostic and config switches and binary_sensors (#59309)

* Onewire: Add diagnostic and config switches and binary_sensors
This commit adds diagnostic and config switches and binary_sensors to
the HobbyBoards devices.  With these, the user will be able to configure
those devices, without having to run owwrite/owread commands outside
of HA.

* Address review from @epenet

* Add HB_HUB to DEVICE_SUPPORT_OWSERVER

* Device class and entity category enums

* Fixup merge breakage

* Remove duplicate lines
This commit is contained in:
Tim Rightnour 2021-12-07 05:59:43 -07:00 committed by GitHub
parent 45c463b61c
commit 489d85d862
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 241 additions and 7 deletions

View file

@ -6,6 +6,7 @@ import os
from typing import TYPE_CHECKING
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
@ -13,10 +14,12 @@ from homeassistant.components.onewire.model import OWServerDeviceDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_TYPE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import (
CONF_TYPE_OWSERVER,
DEVICE_KEYS_0_3,
DEVICE_KEYS_0_7,
DEVICE_KEYS_A_B,
DOMAIN,
@ -61,8 +64,33 @@ DEVICE_BINARY_SENSORS: dict[str, tuple[OneWireBinarySensorEntityDescription, ...
)
for id in DEVICE_KEYS_A_B
),
"EF": (), # "HobbyBoard": special
}
# EF sensors are usually hobbyboards specialized sensors.
HOBBYBOARD_EF: dict[str, tuple[OneWireBinarySensorEntityDescription, ...]] = {
"HB_HUB": tuple(
OneWireBinarySensorEntityDescription(
key=f"hub/short.{id}",
entity_registry_enabled_default=False,
name=f"Hub Short on Branch {id}",
read_mode=READ_MODE_BOOL,
entity_category=EntityCategory.DIAGNOSTIC,
device_class=BinarySensorDeviceClass.PROBLEM,
)
for id in DEVICE_KEYS_0_3
),
}
def get_sensor_types(
device_sub_type: str,
) -> dict[str, tuple[OneWireBinarySensorEntityDescription, ...]]:
"""Return the proper info array for the device type."""
if "HobbyBoard" in device_sub_type:
return HOBBYBOARD_EF
return DEVICE_BINARY_SENSORS
async def async_setup_entry(
hass: HomeAssistant,
@ -89,11 +117,16 @@ def get_entities(onewirehub: OneWireHub) -> list[BinarySensorEntity]:
assert isinstance(device, OWServerDeviceDescription)
family = device.family
device_id = device.id
device_type = device.type
device_info = device.device_info
device_sub_type = "std"
if "EF" in family:
device_sub_type = "HobbyBoard"
family = device_type
if family not in DEVICE_BINARY_SENSORS:
if family not in get_sensor_types(device_sub_type):
continue
for description in DEVICE_BINARY_SENSORS[family]:
for description in get_sensor_types(device_sub_type)[family]:
device_file = os.path.join(os.path.split(device.path)[0], description.key)
name = f"{device_id} {description.name}"
entities.append(

View file

@ -15,6 +15,7 @@ DEFAULT_SYSBUS_MOUNT_DIR = "/sys/bus/w1/devices/"
DOMAIN = "onewire"
DEVICE_KEYS_0_3 = range(4)
DEVICE_KEYS_0_7 = range(8)
DEVICE_KEYS_A_B = ("A", "B")
@ -32,7 +33,7 @@ DEVICE_SUPPORT_OWSERVER = {
"3B": (),
"42": (),
"7E": ("EDS0066", "EDS0068"),
"EF": ("HB_MOISTURE_METER", "HobbyBoards_EF"),
"EF": ("HB_HUB", "HB_MOISTURE_METER", "HobbyBoards_EF"),
}
DEVICE_SUPPORT_SYSBUS = ["10", "22", "28", "3B", "42"]

View file

@ -2,7 +2,6 @@
from __future__ import annotations
from dataclasses import dataclass
import logging
import os
from typing import TYPE_CHECKING, Any
@ -16,6 +15,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import (
CONF_TYPE_OWSERVER,
DEVICE_KEYS_0_3,
DEVICE_KEYS_0_7,
DEVICE_KEYS_A_B,
DOMAIN,
@ -97,9 +97,54 @@ DEVICE_SWITCHES: dict[str, tuple[OneWireEntityDescription, ...]] = {
)
for id in DEVICE_KEYS_A_B
),
"EF": (), # "HobbyBoard": special
}
LOGGER = logging.getLogger(__name__)
# EF sensors are usually hobbyboards specialized sensors.
HOBBYBOARD_EF: dict[str, tuple[OneWireEntityDescription, ...]] = {
"HB_HUB": tuple(
OneWireSwitchEntityDescription(
key=f"hub/branch.{id}",
entity_registry_enabled_default=False,
name=f"Hub Branch {id} Enable",
read_mode=READ_MODE_BOOL,
entity_category=EntityCategory.CONFIG,
)
for id in DEVICE_KEYS_0_3
),
"HB_MOISTURE_METER": tuple(
[
OneWireSwitchEntityDescription(
key=f"moisture/is_leaf.{id}",
entity_registry_enabled_default=False,
name=f"Leaf Sensor {id} Enable",
read_mode=READ_MODE_BOOL,
entity_category=EntityCategory.CONFIG,
)
for id in DEVICE_KEYS_0_3
]
+ [
OneWireSwitchEntityDescription(
key=f"moisture/is_moisture.{id}",
entity_registry_enabled_default=False,
name=f"Moisture Sensor {id} Enable",
read_mode=READ_MODE_BOOL,
entity_category=EntityCategory.CONFIG,
)
for id in DEVICE_KEYS_0_3
]
),
}
def get_sensor_types(
device_sub_type: str,
) -> dict[str, tuple[OneWireEntityDescription, ...]]:
"""Return the proper info array for the device type."""
if "HobbyBoard" in device_sub_type:
return HOBBYBOARD_EF
return DEVICE_SWITCHES
async def async_setup_entry(
@ -127,12 +172,17 @@ def get_entities(onewirehub: OneWireHub) -> list[SwitchEntity]:
if TYPE_CHECKING:
assert isinstance(device, OWServerDeviceDescription)
family = device.family
device_type = device.type
device_id = device.id
device_info = device.device_info
device_sub_type = "std"
if "EF" in family:
device_sub_type = "HobbyBoard"
family = device_type
if family not in DEVICE_SWITCHES:
if family not in get_sensor_types(device_sub_type):
continue
for description in DEVICE_SWITCHES[family]:
for description in get_sensor_types(device_sub_type)[family]:
device_file = os.path.join(os.path.split(device.path)[0], description.key)
name = f"{device_id} {description.name}"
entities.append(

View file

@ -2,6 +2,7 @@
from pi1wire import InvalidCRCException, UnsupportResponseException
from pyownet.protocol import Error as ProtocolError
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.onewire.const import (
DOMAIN,
MANUFACTURER_EDS,
@ -796,6 +797,155 @@ MOCK_OWPROXY_DEVICES = {
ATTR_UNIT_OF_MEASUREMENT: PRESSURE_CBAR,
},
],
Platform.SWITCH: [
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111112_leaf_sensor_0_enable",
ATTR_INJECT_READS: b"1",
ATTR_STATE: STATE_ON,
ATTR_UNIQUE_ID: "/EF.111111111112/moisture/is_leaf.0",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111112_leaf_sensor_1_enable",
ATTR_INJECT_READS: b"1",
ATTR_STATE: STATE_ON,
ATTR_UNIQUE_ID: "/EF.111111111112/moisture/is_leaf.1",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111112_leaf_sensor_2_enable",
ATTR_INJECT_READS: b"0",
ATTR_STATE: STATE_OFF,
ATTR_UNIQUE_ID: "/EF.111111111112/moisture/is_leaf.2",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111112_leaf_sensor_3_enable",
ATTR_INJECT_READS: b"0",
ATTR_STATE: STATE_OFF,
ATTR_UNIQUE_ID: "/EF.111111111112/moisture/is_leaf.3",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111112_moisture_sensor_0_enable",
ATTR_INJECT_READS: b"1",
ATTR_STATE: STATE_ON,
ATTR_UNIQUE_ID: "/EF.111111111112/moisture/is_moisture.0",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111112_moisture_sensor_1_enable",
ATTR_INJECT_READS: b"1",
ATTR_STATE: STATE_ON,
ATTR_UNIQUE_ID: "/EF.111111111112/moisture/is_moisture.1",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111112_moisture_sensor_2_enable",
ATTR_INJECT_READS: b"0",
ATTR_STATE: STATE_OFF,
ATTR_UNIQUE_ID: "/EF.111111111112/moisture/is_moisture.2",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111112_moisture_sensor_3_enable",
ATTR_INJECT_READS: b"0",
ATTR_STATE: STATE_OFF,
ATTR_UNIQUE_ID: "/EF.111111111112/moisture/is_moisture.3",
},
],
},
"EF.111111111113": {
ATTR_INJECT_READS: [
b"HB_HUB", # read type
],
ATTR_DEVICE_INFO: {
ATTR_IDENTIFIERS: {(DOMAIN, "EF.111111111113")},
ATTR_MANUFACTURER: MANUFACTURER_HOBBYBOARDS,
ATTR_MODEL: "HB_HUB",
ATTR_NAME: "EF.111111111113",
},
Platform.BINARY_SENSOR: [
{
ATTR_DEFAULT_DISABLED: True,
ATTR_DEVICE_CLASS: BinarySensorDeviceClass.PROBLEM,
ATTR_ENTITY_CATEGORY: EntityCategory.DIAGNOSTIC,
ATTR_ENTITY_ID: "binary_sensor.ef_111111111113_hub_short_on_branch_0",
ATTR_INJECT_READS: b"1",
ATTR_STATE: STATE_ON,
ATTR_UNIQUE_ID: "/EF.111111111113/hub/short.0",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_DEVICE_CLASS: BinarySensorDeviceClass.PROBLEM,
ATTR_ENTITY_CATEGORY: EntityCategory.DIAGNOSTIC,
ATTR_ENTITY_ID: "binary_sensor.ef_111111111113_hub_short_on_branch_1",
ATTR_INJECT_READS: b"0",
ATTR_STATE: STATE_OFF,
ATTR_UNIQUE_ID: "/EF.111111111113/hub/short.1",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_DEVICE_CLASS: BinarySensorDeviceClass.PROBLEM,
ATTR_ENTITY_CATEGORY: EntityCategory.DIAGNOSTIC,
ATTR_ENTITY_ID: "binary_sensor.ef_111111111113_hub_short_on_branch_2",
ATTR_INJECT_READS: b"1",
ATTR_STATE: STATE_ON,
ATTR_UNIQUE_ID: "/EF.111111111113/hub/short.2",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_DEVICE_CLASS: BinarySensorDeviceClass.PROBLEM,
ATTR_ENTITY_CATEGORY: EntityCategory.DIAGNOSTIC,
ATTR_ENTITY_ID: "binary_sensor.ef_111111111113_hub_short_on_branch_3",
ATTR_INJECT_READS: b"0",
ATTR_STATE: STATE_OFF,
ATTR_UNIQUE_ID: "/EF.111111111113/hub/short.3",
},
],
Platform.SWITCH: [
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111113_hub_branch_0_enable",
ATTR_INJECT_READS: b"1",
ATTR_STATE: STATE_ON,
ATTR_UNIQUE_ID: "/EF.111111111113/hub/branch.0",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111113_hub_branch_1_enable",
ATTR_INJECT_READS: b"0",
ATTR_STATE: STATE_OFF,
ATTR_UNIQUE_ID: "/EF.111111111113/hub/branch.1",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111113_hub_branch_2_enable",
ATTR_INJECT_READS: b"1",
ATTR_STATE: STATE_ON,
ATTR_UNIQUE_ID: "/EF.111111111113/hub/branch.2",
},
{
ATTR_DEFAULT_DISABLED: True,
ATTR_ENTITY_CATEGORY: EntityCategory.CONFIG,
ATTR_ENTITY_ID: "switch.ef_111111111113_hub_branch_3_enable",
ATTR_INJECT_READS: b"0",
ATTR_STATE: STATE_OFF,
ATTR_UNIQUE_ID: "/EF.111111111113/hub/branch.3",
},
],
},
"7E.111111111111": {
ATTR_INJECT_READS: [