mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
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:
parent
45c463b61c
commit
489d85d862
@ -6,6 +6,7 @@ import os
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import (
|
from homeassistant.components.binary_sensor import (
|
||||||
|
BinarySensorDeviceClass,
|
||||||
BinarySensorEntity,
|
BinarySensorEntity,
|
||||||
BinarySensorEntityDescription,
|
BinarySensorEntityDescription,
|
||||||
)
|
)
|
||||||
@ -13,10 +14,12 @@ from homeassistant.components.onewire.model import OWServerDeviceDescription
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_TYPE
|
from homeassistant.const import CONF_TYPE
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_TYPE_OWSERVER,
|
CONF_TYPE_OWSERVER,
|
||||||
|
DEVICE_KEYS_0_3,
|
||||||
DEVICE_KEYS_0_7,
|
DEVICE_KEYS_0_7,
|
||||||
DEVICE_KEYS_A_B,
|
DEVICE_KEYS_A_B,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -61,8 +64,33 @@ DEVICE_BINARY_SENSORS: dict[str, tuple[OneWireBinarySensorEntityDescription, ...
|
|||||||
)
|
)
|
||||||
for id in DEVICE_KEYS_A_B
|
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(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -89,11 +117,16 @@ def get_entities(onewirehub: OneWireHub) -> list[BinarySensorEntity]:
|
|||||||
assert isinstance(device, OWServerDeviceDescription)
|
assert isinstance(device, OWServerDeviceDescription)
|
||||||
family = device.family
|
family = device.family
|
||||||
device_id = device.id
|
device_id = device.id
|
||||||
|
device_type = device.type
|
||||||
device_info = device.device_info
|
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
|
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)
|
device_file = os.path.join(os.path.split(device.path)[0], description.key)
|
||||||
name = f"{device_id} {description.name}"
|
name = f"{device_id} {description.name}"
|
||||||
entities.append(
|
entities.append(
|
||||||
|
@ -15,6 +15,7 @@ DEFAULT_SYSBUS_MOUNT_DIR = "/sys/bus/w1/devices/"
|
|||||||
|
|
||||||
DOMAIN = "onewire"
|
DOMAIN = "onewire"
|
||||||
|
|
||||||
|
DEVICE_KEYS_0_3 = range(4)
|
||||||
DEVICE_KEYS_0_7 = range(8)
|
DEVICE_KEYS_0_7 = range(8)
|
||||||
DEVICE_KEYS_A_B = ("A", "B")
|
DEVICE_KEYS_A_B = ("A", "B")
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ DEVICE_SUPPORT_OWSERVER = {
|
|||||||
"3B": (),
|
"3B": (),
|
||||||
"42": (),
|
"42": (),
|
||||||
"7E": ("EDS0066", "EDS0068"),
|
"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"]
|
DEVICE_SUPPORT_SYSBUS = ["10", "22", "28", "3B", "42"]
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
@ -16,6 +15,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_TYPE_OWSERVER,
|
CONF_TYPE_OWSERVER,
|
||||||
|
DEVICE_KEYS_0_3,
|
||||||
DEVICE_KEYS_0_7,
|
DEVICE_KEYS_0_7,
|
||||||
DEVICE_KEYS_A_B,
|
DEVICE_KEYS_A_B,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -97,9 +97,54 @@ DEVICE_SWITCHES: dict[str, tuple[OneWireEntityDescription, ...]] = {
|
|||||||
)
|
)
|
||||||
for id in DEVICE_KEYS_A_B
|
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(
|
async def async_setup_entry(
|
||||||
@ -127,12 +172,17 @@ def get_entities(onewirehub: OneWireHub) -> list[SwitchEntity]:
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
assert isinstance(device, OWServerDeviceDescription)
|
assert isinstance(device, OWServerDeviceDescription)
|
||||||
family = device.family
|
family = device.family
|
||||||
|
device_type = device.type
|
||||||
device_id = device.id
|
device_id = device.id
|
||||||
device_info = device.device_info
|
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
|
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)
|
device_file = os.path.join(os.path.split(device.path)[0], description.key)
|
||||||
name = f"{device_id} {description.name}"
|
name = f"{device_id} {description.name}"
|
||||||
entities.append(
|
entities.append(
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
from pi1wire import InvalidCRCException, UnsupportResponseException
|
from pi1wire import InvalidCRCException, UnsupportResponseException
|
||||||
from pyownet.protocol import Error as ProtocolError
|
from pyownet.protocol import Error as ProtocolError
|
||||||
|
|
||||||
|
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||||
from homeassistant.components.onewire.const import (
|
from homeassistant.components.onewire.const import (
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
MANUFACTURER_EDS,
|
MANUFACTURER_EDS,
|
||||||
@ -796,6 +797,155 @@ MOCK_OWPROXY_DEVICES = {
|
|||||||
ATTR_UNIT_OF_MEASUREMENT: PRESSURE_CBAR,
|
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": {
|
"7E.111111111111": {
|
||||||
ATTR_INJECT_READS: [
|
ATTR_INJECT_READS: [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user