mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Remove 1-Wire SysBus (ADR-0019) (#71232)
This commit is contained in:
parent
30fdfc454f
commit
08856cfab0
@ -3,7 +3,6 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
import os
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
@ -11,21 +10,18 @@ from homeassistant.components.binary_sensor import (
|
||||
BinarySensorEntityDescription,
|
||||
)
|
||||
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,
|
||||
READ_MODE_BOOL,
|
||||
)
|
||||
from .model import OWServerDeviceDescription
|
||||
from .onewire_entities import OneWireEntityDescription, OneWireProxyEntity
|
||||
from .onewire_entities import OneWireEntity, OneWireEntityDescription
|
||||
from .onewirehub import OneWireHub
|
||||
|
||||
|
||||
@ -98,23 +94,19 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up 1-Wire platform."""
|
||||
# Only OWServer implementation works with binary sensors
|
||||
if config_entry.data[CONF_TYPE] == CONF_TYPE_OWSERVER:
|
||||
onewirehub = hass.data[DOMAIN][config_entry.entry_id]
|
||||
onewirehub = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
entities = await hass.async_add_executor_job(get_entities, onewirehub)
|
||||
async_add_entities(entities, True)
|
||||
entities = await hass.async_add_executor_job(get_entities, onewirehub)
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
def get_entities(onewirehub: OneWireHub) -> list[BinarySensorEntity]:
|
||||
def get_entities(onewirehub: OneWireHub) -> list[OneWireBinarySensor]:
|
||||
"""Get a list of entities."""
|
||||
if not onewirehub.devices:
|
||||
return []
|
||||
|
||||
entities: list[BinarySensorEntity] = []
|
||||
entities: list[OneWireBinarySensor] = []
|
||||
for device in onewirehub.devices:
|
||||
if TYPE_CHECKING:
|
||||
assert isinstance(device, OWServerDeviceDescription)
|
||||
family = device.family
|
||||
device_id = device.id
|
||||
device_type = device.type
|
||||
@ -130,7 +122,7 @@ def get_entities(onewirehub: OneWireHub) -> list[BinarySensorEntity]:
|
||||
device_file = os.path.join(os.path.split(device.path)[0], description.key)
|
||||
name = f"{device_id} {description.name}"
|
||||
entities.append(
|
||||
OneWireProxyBinarySensor(
|
||||
OneWireBinarySensor(
|
||||
description=description,
|
||||
device_id=device_id,
|
||||
device_file=device_file,
|
||||
@ -143,7 +135,7 @@ def get_entities(onewirehub: OneWireHub) -> list[BinarySensorEntity]:
|
||||
return entities
|
||||
|
||||
|
||||
class OneWireProxyBinarySensor(OneWireProxyEntity, BinarySensorEntity):
|
||||
class OneWireBinarySensor(OneWireEntity, BinarySensorEntity):
|
||||
"""Implementation of a 1-Wire binary sensor."""
|
||||
|
||||
entity_description: OneWireBinarySensorEntityDescription
|
||||
|
@ -6,19 +6,15 @@ from typing import Any
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TYPE
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||
from homeassistant.helpers.device_registry import DeviceRegistry
|
||||
|
||||
from .const import (
|
||||
CONF_MOUNT_DIR,
|
||||
CONF_TYPE_OWSERVER,
|
||||
CONF_TYPE_SYSBUS,
|
||||
DEFAULT_OWSERVER_HOST,
|
||||
DEFAULT_OWSERVER_PORT,
|
||||
DEFAULT_SYSBUS_MOUNT_DIR,
|
||||
DEFAULT_HOST,
|
||||
DEFAULT_PORT,
|
||||
DEVICE_SUPPORT_OPTIONS,
|
||||
DOMAIN,
|
||||
INPUT_ENTRY_CLEAR_OPTIONS,
|
||||
@ -27,31 +23,21 @@ from .const import (
|
||||
OPTION_ENTRY_SENSOR_PRECISION,
|
||||
PRECISION_MAPPING_FAMILY_28,
|
||||
)
|
||||
from .model import OWServerDeviceDescription
|
||||
from .onewirehub import CannotConnect, InvalidPath, OneWireHub
|
||||
from .model import OWDeviceDescription
|
||||
from .onewirehub import CannotConnect, OneWireHub
|
||||
|
||||
DATA_SCHEMA_USER = vol.Schema(
|
||||
{vol.Required(CONF_TYPE): vol.In([CONF_TYPE_OWSERVER, CONF_TYPE_SYSBUS])}
|
||||
)
|
||||
DATA_SCHEMA_OWSERVER = vol.Schema(
|
||||
DATA_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_HOST, default=DEFAULT_OWSERVER_HOST): str,
|
||||
vol.Required(CONF_PORT, default=DEFAULT_OWSERVER_PORT): int,
|
||||
}
|
||||
)
|
||||
DATA_SCHEMA_MOUNTDIR = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_MOUNT_DIR, default=DEFAULT_SYSBUS_MOUNT_DIR): str,
|
||||
vol.Required(CONF_HOST, default=DEFAULT_HOST): str,
|
||||
vol.Required(CONF_PORT, default=DEFAULT_PORT): int,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def validate_input_owserver(
|
||||
hass: HomeAssistant, data: dict[str, Any]
|
||||
) -> dict[str, str]:
|
||||
async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str, str]:
|
||||
"""Validate the user input allows us to connect.
|
||||
|
||||
Data has the keys from DATA_SCHEMA_OWSERVER with values provided by the user.
|
||||
Data has the keys from DATA_SCHEMA with values provided by the user.
|
||||
"""
|
||||
|
||||
hub = OneWireHub(hass)
|
||||
@ -65,24 +51,6 @@ async def validate_input_owserver(
|
||||
return {"title": host}
|
||||
|
||||
|
||||
async def validate_input_mount_dir(
|
||||
hass: HomeAssistant, data: dict[str, Any]
|
||||
) -> dict[str, str]:
|
||||
"""Validate the user input allows us to connect.
|
||||
|
||||
Data has the keys from DATA_SCHEMA_MOUNTDIR with values provided by the user.
|
||||
"""
|
||||
hub = OneWireHub(hass)
|
||||
|
||||
mount_dir = data[CONF_MOUNT_DIR]
|
||||
|
||||
# Raises InvalidDir exception on failure
|
||||
await hub.check_mount_dir(mount_dir)
|
||||
|
||||
# Return info that you want to store in the config entry.
|
||||
return {"title": mount_dir}
|
||||
|
||||
|
||||
class OneWireFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle 1-Wire config flow."""
|
||||
|
||||
@ -100,29 +68,10 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
Let user manually input configuration.
|
||||
"""
|
||||
errors: dict[str, str] = {}
|
||||
if user_input is not None:
|
||||
self.onewire_config.update(user_input)
|
||||
if CONF_TYPE_OWSERVER == user_input[CONF_TYPE]:
|
||||
return await self.async_step_owserver()
|
||||
if CONF_TYPE_SYSBUS == user_input[CONF_TYPE]:
|
||||
return await self.async_step_mount_dir()
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=DATA_SCHEMA_USER,
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
async def async_step_owserver(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
"""Handle OWServer configuration."""
|
||||
errors = {}
|
||||
if user_input:
|
||||
# Prevent duplicate entries
|
||||
self._async_abort_entries_match(
|
||||
{
|
||||
CONF_TYPE: CONF_TYPE_OWSERVER,
|
||||
CONF_HOST: user_input[CONF_HOST],
|
||||
CONF_PORT: user_input[CONF_PORT],
|
||||
}
|
||||
@ -131,7 +80,7 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
self.onewire_config.update(user_input)
|
||||
|
||||
try:
|
||||
info = await validate_input_owserver(self.hass, user_input)
|
||||
info = await validate_input(self.hass, user_input)
|
||||
except CannotConnect:
|
||||
errors["base"] = "cannot_connect"
|
||||
else:
|
||||
@ -140,37 +89,8 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="owserver",
|
||||
data_schema=DATA_SCHEMA_OWSERVER,
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
async def async_step_mount_dir(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
"""Handle SysBus configuration."""
|
||||
errors = {}
|
||||
if user_input:
|
||||
# Prevent duplicate entries
|
||||
await self.async_set_unique_id(
|
||||
f"{CONF_TYPE_SYSBUS}:{user_input[CONF_MOUNT_DIR]}"
|
||||
)
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
self.onewire_config.update(user_input)
|
||||
|
||||
try:
|
||||
info = await validate_input_mount_dir(self.hass, user_input)
|
||||
except InvalidPath:
|
||||
errors["base"] = "invalid_path"
|
||||
else:
|
||||
return self.async_create_entry(
|
||||
title=info["title"], data=self.onewire_config
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="mount_dir",
|
||||
data_schema=DATA_SCHEMA_MOUNTDIR,
|
||||
step_id="user",
|
||||
data_schema=DATA_SCHEMA,
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
@ -188,8 +108,8 @@ class OnewireOptionsFlowHandler(OptionsFlow):
|
||||
"""Initialize OneWire Network options flow."""
|
||||
self.entry_id = config_entry.entry_id
|
||||
self.options = dict(config_entry.options)
|
||||
self.configurable_devices: dict[str, OWServerDeviceDescription] = {}
|
||||
self.devices_to_configure: dict[str, OWServerDeviceDescription] = {}
|
||||
self.configurable_devices: dict[str, OWDeviceDescription] = {}
|
||||
self.devices_to_configure: dict[str, OWDeviceDescription] = {}
|
||||
self.current_device: str = ""
|
||||
|
||||
async def async_step_init(
|
||||
@ -197,12 +117,7 @@ class OnewireOptionsFlowHandler(OptionsFlow):
|
||||
) -> FlowResult:
|
||||
"""Manage the options."""
|
||||
controller: OneWireHub = self.hass.data[DOMAIN][self.entry_id]
|
||||
if controller.type == CONF_TYPE_SYSBUS:
|
||||
return self.async_abort(
|
||||
reason="SysBus setup does not have any config options."
|
||||
)
|
||||
|
||||
all_devices: list[OWServerDeviceDescription] = controller.devices # type: ignore[assignment]
|
||||
all_devices: list[OWDeviceDescription] = controller.devices # type: ignore[assignment]
|
||||
if not all_devices:
|
||||
return self.async_abort(reason="No configurable devices found.")
|
||||
|
||||
|
@ -3,14 +3,8 @@ from __future__ import annotations
|
||||
|
||||
from homeassistant.const import Platform
|
||||
|
||||
CONF_MOUNT_DIR = "mount_dir"
|
||||
|
||||
CONF_TYPE_OWSERVER = "OWServer"
|
||||
CONF_TYPE_SYSBUS = "SysBus"
|
||||
|
||||
DEFAULT_OWSERVER_HOST = "localhost"
|
||||
DEFAULT_OWSERVER_PORT = 4304
|
||||
DEFAULT_SYSBUS_MOUNT_DIR = "/sys/bus/w1/devices/"
|
||||
DEFAULT_HOST = "localhost"
|
||||
DEFAULT_PORT = 4304
|
||||
|
||||
DOMAIN = "onewire"
|
||||
|
||||
@ -18,7 +12,7 @@ DEVICE_KEYS_0_3 = range(4)
|
||||
DEVICE_KEYS_0_7 = range(8)
|
||||
DEVICE_KEYS_A_B = ("A", "B")
|
||||
|
||||
DEVICE_SUPPORT_OWSERVER = {
|
||||
DEVICE_SUPPORT = {
|
||||
"05": (),
|
||||
"10": (),
|
||||
"12": (),
|
||||
@ -35,7 +29,6 @@ DEVICE_SUPPORT_OWSERVER = {
|
||||
"7E": ("EDS0066", "EDS0068"),
|
||||
"EF": ("HB_HUB", "HB_MOISTURE_METER", "HobbyBoards_EF"),
|
||||
}
|
||||
DEVICE_SUPPORT_SYSBUS = ["10", "22", "28", "3B", "42"]
|
||||
|
||||
DEVICE_SUPPORT_OPTIONS = ["28"]
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
"name": "1-Wire",
|
||||
"documentation": "https://www.home-assistant.io/integrations/onewire",
|
||||
"config_flow": true,
|
||||
"requirements": ["pyownet==0.10.0.post1", "pi1wire==0.1.0"],
|
||||
"requirements": ["pyownet==0.10.0.post1"],
|
||||
"codeowners": ["@garbled1", "@epenet"],
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["pi1wire", "pyownet"]
|
||||
"loggers": ["pyownet"]
|
||||
}
|
||||
|
@ -3,29 +3,15 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from pi1wire import OneWireInterface
|
||||
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
|
||||
|
||||
@dataclass
|
||||
class OWDeviceDescription:
|
||||
"""OWDeviceDescription device description class."""
|
||||
"""1-Wire device description class."""
|
||||
|
||||
device_info: DeviceInfo
|
||||
|
||||
|
||||
@dataclass
|
||||
class OWDirectDeviceDescription(OWDeviceDescription):
|
||||
"""SysBus device description class."""
|
||||
|
||||
interface: OneWireInterface
|
||||
|
||||
|
||||
@dataclass
|
||||
class OWServerDeviceDescription(OWDeviceDescription):
|
||||
"""OWServer device description class."""
|
||||
|
||||
family: str
|
||||
id: str
|
||||
path: str
|
||||
|
@ -23,7 +23,7 @@ class OneWireEntityDescription(EntityDescription):
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OneWireBaseEntity(Entity):
|
||||
class OneWireEntity(Entity):
|
||||
"""Implementation of a 1-Wire entity."""
|
||||
|
||||
entity_description: OneWireEntityDescription
|
||||
@ -35,6 +35,7 @@ class OneWireBaseEntity(Entity):
|
||||
device_info: DeviceInfo,
|
||||
device_file: str,
|
||||
name: str,
|
||||
owproxy: protocol._Proxy,
|
||||
) -> None:
|
||||
"""Initialize the entity."""
|
||||
self.entity_description = description
|
||||
@ -44,6 +45,7 @@ class OneWireBaseEntity(Entity):
|
||||
self._device_file = device_file
|
||||
self._state: StateType = None
|
||||
self._value_raw: float | None = None
|
||||
self._owproxy = owproxy
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any] | None:
|
||||
@ -53,44 +55,21 @@ class OneWireBaseEntity(Entity):
|
||||
"raw_value": self._value_raw,
|
||||
}
|
||||
|
||||
|
||||
class OneWireProxyEntity(OneWireBaseEntity):
|
||||
"""Implementation of a 1-Wire entity connected through owserver."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
description: OneWireEntityDescription,
|
||||
device_id: str,
|
||||
device_info: DeviceInfo,
|
||||
device_file: str,
|
||||
name: str,
|
||||
owproxy: protocol._Proxy,
|
||||
) -> None:
|
||||
"""Initialize the sensor."""
|
||||
super().__init__(
|
||||
description=description,
|
||||
device_id=device_id,
|
||||
device_info=device_info,
|
||||
device_file=device_file,
|
||||
name=name,
|
||||
)
|
||||
self._owproxy = owproxy
|
||||
|
||||
def _read_value_ownet(self) -> str:
|
||||
"""Read a value from the owserver."""
|
||||
def _read_value(self) -> str:
|
||||
"""Read a value from the server."""
|
||||
read_bytes: bytes = self._owproxy.read(self._device_file)
|
||||
return read_bytes.decode().lstrip()
|
||||
|
||||
def _write_value_ownet(self, value: bytes) -> None:
|
||||
"""Write a value to the owserver."""
|
||||
def _write_value(self, value: bytes) -> None:
|
||||
"""Write a value to the server."""
|
||||
self._owproxy.write(self._device_file, value)
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the latest data from the device."""
|
||||
try:
|
||||
self._value_raw = float(self._read_value_ownet())
|
||||
self._value_raw = float(self._read_value())
|
||||
except protocol.Error as exc:
|
||||
_LOGGER.error("Owserver failure in read(), got: %s", exc)
|
||||
_LOGGER.error("Failure to read server value, got: %s", exc)
|
||||
self._state = None
|
||||
else:
|
||||
if self.entity_description.read_mode == READ_MODE_INT:
|
||||
|
@ -5,7 +5,6 @@ import logging
|
||||
import os
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from pi1wire import Pi1Wire
|
||||
from pyownet import protocol
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -17,7 +16,6 @@ from homeassistant.const import (
|
||||
ATTR_VIA_DEVICE,
|
||||
CONF_HOST,
|
||||
CONF_PORT,
|
||||
CONF_TYPE,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
@ -25,21 +23,13 @@ from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
|
||||
from .const import (
|
||||
CONF_MOUNT_DIR,
|
||||
CONF_TYPE_OWSERVER,
|
||||
CONF_TYPE_SYSBUS,
|
||||
DEVICE_SUPPORT_OWSERVER,
|
||||
DEVICE_SUPPORT_SYSBUS,
|
||||
DEVICE_SUPPORT,
|
||||
DOMAIN,
|
||||
MANUFACTURER_EDS,
|
||||
MANUFACTURER_HOBBYBOARDS,
|
||||
MANUFACTURER_MAXIM,
|
||||
)
|
||||
from .model import (
|
||||
OWDeviceDescription,
|
||||
OWDirectDeviceDescription,
|
||||
OWServerDeviceDescription,
|
||||
)
|
||||
from .model import OWDeviceDescription
|
||||
|
||||
DEVICE_COUPLERS = {
|
||||
# Family : [branches]
|
||||
@ -54,26 +44,24 @@ DEVICE_MANUFACTURER = {
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _is_known_owserver_device(device_family: str, device_type: str) -> bool:
|
||||
def _is_known_device(device_family: str, device_type: str) -> bool:
|
||||
"""Check if device family/type is known to the library."""
|
||||
if device_family in ("7E", "EF"): # EDS or HobbyBoard
|
||||
return device_type in DEVICE_SUPPORT_OWSERVER[device_family]
|
||||
return device_family in DEVICE_SUPPORT_OWSERVER
|
||||
return device_type in DEVICE_SUPPORT[device_family]
|
||||
return device_family in DEVICE_SUPPORT
|
||||
|
||||
|
||||
class OneWireHub:
|
||||
"""Hub to communicate with SysBus or OWServer."""
|
||||
"""Hub to communicate with server."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
"""Initialize."""
|
||||
self.hass = hass
|
||||
self.type: str | None = None
|
||||
self.pi1proxy: Pi1Wire | None = None
|
||||
self.owproxy: protocol._Proxy | None = None
|
||||
self.devices: list[OWDeviceDescription] | None = None
|
||||
|
||||
async def connect(self, host: str, port: int) -> None:
|
||||
"""Connect to the owserver host."""
|
||||
"""Connect to the server."""
|
||||
try:
|
||||
self.owproxy = await self.hass.async_add_executor_job(
|
||||
protocol.proxy, host, port
|
||||
@ -81,32 +69,12 @@ class OneWireHub:
|
||||
except protocol.ConnError as exc:
|
||||
raise CannotConnect from exc
|
||||
|
||||
async def check_mount_dir(self, mount_dir: str) -> None:
|
||||
"""Test that the mount_dir is a valid path."""
|
||||
if not await self.hass.async_add_executor_job(os.path.isdir, mount_dir):
|
||||
raise InvalidPath
|
||||
self.pi1proxy = Pi1Wire(mount_dir)
|
||||
|
||||
async def initialize(self, config_entry: ConfigEntry) -> None:
|
||||
"""Initialize a config entry."""
|
||||
self.type = config_entry.data[CONF_TYPE]
|
||||
if self.type == CONF_TYPE_SYSBUS:
|
||||
mount_dir = config_entry.data[CONF_MOUNT_DIR]
|
||||
_LOGGER.debug("Initializing using SysBus %s", mount_dir)
|
||||
_LOGGER.warning(
|
||||
"Using the 1-Wire integration via SysBus is deprecated and will be removed "
|
||||
"in Home Assistant Core 2022.6; this integration is being adjusted to comply "
|
||||
"with Architectural Decision Record 0019, more information can be found here: "
|
||||
"https://github.com/home-assistant/architecture/blob/master/adr/0019-GPIO.md "
|
||||
"Access via OWServer is still supported"
|
||||
)
|
||||
|
||||
await self.check_mount_dir(mount_dir)
|
||||
elif self.type == CONF_TYPE_OWSERVER:
|
||||
host = config_entry.data[CONF_HOST]
|
||||
port = config_entry.data[CONF_PORT]
|
||||
_LOGGER.debug("Initializing using OWServer %s:%s", host, port)
|
||||
await self.connect(host, port)
|
||||
host = config_entry.data[CONF_HOST]
|
||||
port = config_entry.data[CONF_PORT]
|
||||
_LOGGER.debug("Initializing connection to %s:%s", host, port)
|
||||
await self.connect(host, port)
|
||||
await self.discover_devices()
|
||||
if TYPE_CHECKING:
|
||||
assert self.devices
|
||||
@ -126,63 +94,22 @@ class OneWireHub:
|
||||
async def discover_devices(self) -> None:
|
||||
"""Discover all devices."""
|
||||
if self.devices is None:
|
||||
if self.type == CONF_TYPE_SYSBUS:
|
||||
self.devices = await self.hass.async_add_executor_job(
|
||||
self._discover_devices_sysbus
|
||||
)
|
||||
if self.type == CONF_TYPE_OWSERVER:
|
||||
self.devices = await self.hass.async_add_executor_job(
|
||||
self._discover_devices_owserver
|
||||
)
|
||||
|
||||
def _discover_devices_sysbus(self) -> list[OWDeviceDescription]:
|
||||
"""Discover all sysbus devices."""
|
||||
devices: list[OWDeviceDescription] = []
|
||||
assert self.pi1proxy
|
||||
all_sensors = self.pi1proxy.find_all_sensors()
|
||||
if not all_sensors:
|
||||
_LOGGER.error(
|
||||
"No onewire sensor found. Check if dtoverlay=w1-gpio "
|
||||
"is in your /boot/config.txt. "
|
||||
"Check the mount_dir parameter if it's defined"
|
||||
self.devices = await self.hass.async_add_executor_job(
|
||||
self._discover_devices
|
||||
)
|
||||
for interface in all_sensors:
|
||||
device_family = interface.mac_address[:2]
|
||||
device_id = f"{device_family}-{interface.mac_address[2:]}"
|
||||
if device_family not in DEVICE_SUPPORT_SYSBUS:
|
||||
_LOGGER.warning(
|
||||
"Ignoring unknown device family (%s) found for device %s",
|
||||
device_family,
|
||||
device_id,
|
||||
)
|
||||
continue
|
||||
device_info: DeviceInfo = {
|
||||
ATTR_IDENTIFIERS: {(DOMAIN, device_id)},
|
||||
ATTR_MANUFACTURER: DEVICE_MANUFACTURER.get(
|
||||
device_family, MANUFACTURER_MAXIM
|
||||
),
|
||||
ATTR_MODEL: device_family,
|
||||
ATTR_NAME: device_id,
|
||||
}
|
||||
device = OWDirectDeviceDescription(
|
||||
device_info=device_info,
|
||||
interface=interface,
|
||||
)
|
||||
devices.append(device)
|
||||
return devices
|
||||
|
||||
def _discover_devices_owserver(
|
||||
def _discover_devices(
|
||||
self, path: str = "/", parent_id: str | None = None
|
||||
) -> list[OWDeviceDescription]:
|
||||
"""Discover all owserver devices."""
|
||||
"""Discover all server devices."""
|
||||
devices: list[OWDeviceDescription] = []
|
||||
assert self.owproxy
|
||||
for device_path in self.owproxy.dir(path):
|
||||
device_id = os.path.split(os.path.split(device_path)[0])[1]
|
||||
device_family = self.owproxy.read(f"{device_path}family").decode()
|
||||
_LOGGER.debug("read `%sfamily`: %s", device_path, device_family)
|
||||
device_type = self._get_device_type_owserver(device_path)
|
||||
if not _is_known_owserver_device(device_family, device_type):
|
||||
device_type = self._get_device_type(device_path)
|
||||
if not _is_known_device(device_family, device_type):
|
||||
_LOGGER.warning(
|
||||
"Ignoring unknown device family/type (%s/%s) found for device %s",
|
||||
device_family,
|
||||
@ -200,7 +127,7 @@ class OneWireHub:
|
||||
}
|
||||
if parent_id:
|
||||
device_info[ATTR_VIA_DEVICE] = (DOMAIN, parent_id)
|
||||
device = OWServerDeviceDescription(
|
||||
device = OWDeviceDescription(
|
||||
device_info=device_info,
|
||||
id=device_id,
|
||||
family=device_family,
|
||||
@ -210,13 +137,13 @@ class OneWireHub:
|
||||
devices.append(device)
|
||||
if device_branches := DEVICE_COUPLERS.get(device_family):
|
||||
for branch in device_branches:
|
||||
devices += self._discover_devices_owserver(
|
||||
devices += self._discover_devices(
|
||||
f"{device_path}{branch}", device_id
|
||||
)
|
||||
|
||||
return devices
|
||||
|
||||
def _get_device_type_owserver(self, device_path: str) -> str:
|
||||
def _get_device_type(self, device_path: str) -> str:
|
||||
"""Get device model."""
|
||||
if TYPE_CHECKING:
|
||||
assert self.owproxy
|
||||
|
@ -1,16 +1,13 @@
|
||||
"""Support for 1-Wire environment sensors."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Callable, Mapping
|
||||
import copy
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
import os
|
||||
from types import MappingProxyType
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from pi1wire import InvalidCRCException, OneWireInterface, UnsupportResponseException
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
@ -20,7 +17,6 @@ from homeassistant.components.sensor import (
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_TYPE,
|
||||
ELECTRIC_POTENTIAL_VOLT,
|
||||
LIGHT_LUX,
|
||||
PERCENTAGE,
|
||||
@ -29,13 +25,10 @@ from homeassistant.const import (
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from .const import (
|
||||
CONF_TYPE_OWSERVER,
|
||||
CONF_TYPE_SYSBUS,
|
||||
DEVICE_KEYS_0_3,
|
||||
DEVICE_KEYS_A_B,
|
||||
DOMAIN,
|
||||
@ -45,12 +38,7 @@ from .const import (
|
||||
READ_MODE_FLOAT,
|
||||
READ_MODE_INT,
|
||||
)
|
||||
from .model import OWDirectDeviceDescription, OWServerDeviceDescription
|
||||
from .onewire_entities import (
|
||||
OneWireBaseEntity,
|
||||
OneWireEntityDescription,
|
||||
OneWireProxyEntity,
|
||||
)
|
||||
from .onewire_entities import OneWireEntity, OneWireEntityDescription
|
||||
from .onewirehub import OneWireHub
|
||||
|
||||
|
||||
@ -263,8 +251,6 @@ DEVICE_SENSORS: dict[str, tuple[OneWireSensorEntityDescription, ...]] = {
|
||||
}
|
||||
|
||||
# EF sensors are usually hobbyboards specialized sensors.
|
||||
# These can only be read by OWFS. Currently this driver only supports them
|
||||
# via owserver (network protocol)
|
||||
|
||||
HOBBYBOARD_EF: dict[str, tuple[OneWireSensorEntityDescription, ...]] = {
|
||||
"HobbyBoards_EF": (
|
||||
@ -383,109 +369,72 @@ async def async_setup_entry(
|
||||
"""Set up 1-Wire platform."""
|
||||
onewirehub = hass.data[DOMAIN][config_entry.entry_id]
|
||||
entities = await hass.async_add_executor_job(
|
||||
get_entities, onewirehub, config_entry.data, config_entry.options
|
||||
get_entities, onewirehub, config_entry.options
|
||||
)
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
def get_entities(
|
||||
onewirehub: OneWireHub,
|
||||
config: MappingProxyType[str, Any],
|
||||
options: MappingProxyType[str, Any],
|
||||
) -> list[SensorEntity]:
|
||||
onewirehub: OneWireHub, options: MappingProxyType[str, Any]
|
||||
) -> list[OneWireSensor]:
|
||||
"""Get a list of entities."""
|
||||
if not onewirehub.devices:
|
||||
return []
|
||||
|
||||
entities: list[SensorEntity] = []
|
||||
conf_type = config[CONF_TYPE]
|
||||
# We have an owserver on a remote(or local) host/port
|
||||
if conf_type == CONF_TYPE_OWSERVER:
|
||||
assert onewirehub.owproxy
|
||||
for device in onewirehub.devices:
|
||||
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"
|
||||
device_path = device.path
|
||||
if "EF" in family:
|
||||
device_sub_type = "HobbyBoard"
|
||||
family = device_type
|
||||
elif "7E" in family:
|
||||
device_sub_type = "EDS"
|
||||
family = device_type
|
||||
entities: list[OneWireSensor] = []
|
||||
assert onewirehub.owproxy
|
||||
for device in onewirehub.devices:
|
||||
family = device.family
|
||||
device_type = device.type
|
||||
device_id = device.id
|
||||
device_info = device.device_info
|
||||
device_sub_type = "std"
|
||||
device_path = device.path
|
||||
if "EF" in family:
|
||||
device_sub_type = "HobbyBoard"
|
||||
family = device_type
|
||||
elif "7E" in family:
|
||||
device_sub_type = "EDS"
|
||||
family = device_type
|
||||
|
||||
if family not in get_sensor_types(device_sub_type):
|
||||
continue
|
||||
for description in get_sensor_types(device_sub_type)[family]:
|
||||
if description.key.startswith("moisture/"):
|
||||
s_id = description.key.split(".")[1]
|
||||
is_leaf = int(
|
||||
onewirehub.owproxy.read(
|
||||
f"{device_path}moisture/is_leaf.{s_id}"
|
||||
).decode()
|
||||
)
|
||||
if is_leaf:
|
||||
description = copy.deepcopy(description)
|
||||
description.device_class = SensorDeviceClass.HUMIDITY
|
||||
description.native_unit_of_measurement = PERCENTAGE
|
||||
description.name = f"Wetness {s_id}"
|
||||
override_key = None
|
||||
if description.override_key:
|
||||
override_key = description.override_key(device_id, options)
|
||||
device_file = os.path.join(
|
||||
os.path.split(device.path)[0],
|
||||
override_key or description.key,
|
||||
if family not in get_sensor_types(device_sub_type):
|
||||
continue
|
||||
for description in get_sensor_types(device_sub_type)[family]:
|
||||
if description.key.startswith("moisture/"):
|
||||
s_id = description.key.split(".")[1]
|
||||
is_leaf = int(
|
||||
onewirehub.owproxy.read(
|
||||
f"{device_path}moisture/is_leaf.{s_id}"
|
||||
).decode()
|
||||
)
|
||||
name = f"{device_id} {description.name}"
|
||||
entities.append(
|
||||
OneWireProxySensor(
|
||||
description=description,
|
||||
device_id=device_id,
|
||||
device_file=device_file,
|
||||
device_info=device_info,
|
||||
name=name,
|
||||
owproxy=onewirehub.owproxy,
|
||||
)
|
||||
)
|
||||
|
||||
# We have a raw GPIO ow sensor on a Pi
|
||||
elif conf_type == CONF_TYPE_SYSBUS:
|
||||
for device in onewirehub.devices:
|
||||
if TYPE_CHECKING:
|
||||
assert isinstance(device, OWDirectDeviceDescription)
|
||||
p1sensor: OneWireInterface = device.interface
|
||||
family = p1sensor.mac_address[:2]
|
||||
device_id = f"{family}-{p1sensor.mac_address[2:]}"
|
||||
device_info = device.device_info
|
||||
description = SIMPLE_TEMPERATURE_SENSOR_DESCRIPTION
|
||||
device_file = f"/sys/bus/w1/devices/{device_id}/w1_slave"
|
||||
if is_leaf:
|
||||
description = copy.deepcopy(description)
|
||||
description.device_class = SensorDeviceClass.HUMIDITY
|
||||
description.native_unit_of_measurement = PERCENTAGE
|
||||
description.name = f"Wetness {s_id}"
|
||||
override_key = None
|
||||
if description.override_key:
|
||||
override_key = description.override_key(device_id, options)
|
||||
device_file = os.path.join(
|
||||
os.path.split(device.path)[0],
|
||||
override_key or description.key,
|
||||
)
|
||||
name = f"{device_id} {description.name}"
|
||||
entities.append(
|
||||
OneWireDirectSensor(
|
||||
OneWireSensor(
|
||||
description=description,
|
||||
device_id=device_id,
|
||||
device_file=device_file,
|
||||
device_info=device_info,
|
||||
name=name,
|
||||
owsensor=p1sensor,
|
||||
owproxy=onewirehub.owproxy,
|
||||
)
|
||||
)
|
||||
|
||||
return entities
|
||||
|
||||
|
||||
class OneWireSensor(OneWireBaseEntity, SensorEntity):
|
||||
"""Mixin for sensor specific attributes."""
|
||||
|
||||
entity_description: OneWireSensorEntityDescription
|
||||
|
||||
|
||||
class OneWireProxySensor(OneWireProxyEntity, OneWireSensor):
|
||||
"""Implementation of a 1-Wire sensor connected through owserver."""
|
||||
class OneWireSensor(OneWireEntity, SensorEntity):
|
||||
"""Implementation of a 1-Wire sensor."""
|
||||
|
||||
entity_description: OneWireSensorEntityDescription
|
||||
|
||||
@ -493,69 +442,3 @@ class OneWireProxySensor(OneWireProxyEntity, OneWireSensor):
|
||||
def native_value(self) -> StateType:
|
||||
"""Return the state of the entity."""
|
||||
return self._state
|
||||
|
||||
|
||||
class OneWireDirectSensor(OneWireSensor):
|
||||
"""Implementation of a 1-Wire sensor directly connected to RPI GPIO."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
description: OneWireSensorEntityDescription,
|
||||
device_id: str,
|
||||
device_info: DeviceInfo,
|
||||
device_file: str,
|
||||
name: str,
|
||||
owsensor: OneWireInterface,
|
||||
) -> None:
|
||||
"""Initialize the sensor."""
|
||||
super().__init__(
|
||||
description=description,
|
||||
device_id=device_id,
|
||||
device_info=device_info,
|
||||
device_file=device_file,
|
||||
name=name,
|
||||
)
|
||||
self._attr_unique_id = device_file
|
||||
self._owsensor = owsensor
|
||||
|
||||
@property
|
||||
def native_value(self) -> StateType:
|
||||
"""Return the state of the entity."""
|
||||
return self._state
|
||||
|
||||
async def get_temperature(self) -> float:
|
||||
"""Get the latest data from the device."""
|
||||
attempts = 1
|
||||
while True:
|
||||
try:
|
||||
return await self.hass.async_add_executor_job(
|
||||
self._owsensor.get_temperature
|
||||
)
|
||||
except UnsupportResponseException as ex:
|
||||
_LOGGER.debug(
|
||||
"Cannot read from sensor %s (retry attempt %s): %s",
|
||||
self._device_file,
|
||||
attempts,
|
||||
ex,
|
||||
)
|
||||
await asyncio.sleep(0.2)
|
||||
attempts += 1
|
||||
if attempts > 10:
|
||||
raise
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Get the latest data from the device."""
|
||||
try:
|
||||
self._value_raw = await self.get_temperature()
|
||||
self._state = round(self._value_raw, 1)
|
||||
except (
|
||||
FileNotFoundError,
|
||||
InvalidCRCException,
|
||||
UnsupportResponseException,
|
||||
) as ex:
|
||||
_LOGGER.warning(
|
||||
"Cannot read from sensor %s: %s",
|
||||
self._device_file,
|
||||
ex,
|
||||
)
|
||||
self._state = None
|
||||
|
@ -4,22 +4,15 @@
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"invalid_path": "Directory not found."
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
||||
},
|
||||
"step": {
|
||||
"owserver": {
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "[%key:common::config_flow::data::host%]",
|
||||
"port": "[%key:common::config_flow::data::port%]"
|
||||
},
|
||||
"title": "Set owserver details"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"type": "Connection type"
|
||||
},
|
||||
"title": "Set up 1-Wire"
|
||||
"title": "Set server details"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -28,11 +21,6 @@
|
||||
"device_not_selected": "Select devices to configure"
|
||||
},
|
||||
"step": {
|
||||
"ack_no_options": {
|
||||
"data": {},
|
||||
"description": "There are no options for the SysBus implementation",
|
||||
"title": "OneWire SysBus Options"
|
||||
},
|
||||
"device_selection": {
|
||||
"data": {
|
||||
"clear_device_options": "Clear all device configurations",
|
||||
|
@ -3,25 +3,22 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
||||
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,
|
||||
READ_MODE_BOOL,
|
||||
)
|
||||
from .model import OWServerDeviceDescription
|
||||
from .onewire_entities import OneWireEntityDescription, OneWireProxyEntity
|
||||
from .onewire_entities import OneWireEntity, OneWireEntityDescription
|
||||
from .onewirehub import OneWireHub
|
||||
|
||||
|
||||
@ -153,24 +150,20 @@ async def async_setup_entry(
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up 1-Wire platform."""
|
||||
# Only OWServer implementation works with switches
|
||||
if config_entry.data[CONF_TYPE] == CONF_TYPE_OWSERVER:
|
||||
onewirehub = hass.data[DOMAIN][config_entry.entry_id]
|
||||
onewirehub = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
entities = await hass.async_add_executor_job(get_entities, onewirehub)
|
||||
async_add_entities(entities, True)
|
||||
entities = await hass.async_add_executor_job(get_entities, onewirehub)
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
def get_entities(onewirehub: OneWireHub) -> list[SwitchEntity]:
|
||||
def get_entities(onewirehub: OneWireHub) -> list[OneWireSwitch]:
|
||||
"""Get a list of entities."""
|
||||
if not onewirehub.devices:
|
||||
return []
|
||||
|
||||
entities: list[SwitchEntity] = []
|
||||
entities: list[OneWireSwitch] = []
|
||||
|
||||
for device in onewirehub.devices:
|
||||
if TYPE_CHECKING:
|
||||
assert isinstance(device, OWServerDeviceDescription)
|
||||
family = device.family
|
||||
device_type = device.type
|
||||
device_id = device.id
|
||||
@ -186,7 +179,7 @@ def get_entities(onewirehub: OneWireHub) -> list[SwitchEntity]:
|
||||
device_file = os.path.join(os.path.split(device.path)[0], description.key)
|
||||
name = f"{device_id} {description.name}"
|
||||
entities.append(
|
||||
OneWireProxySwitch(
|
||||
OneWireSwitch(
|
||||
description=description,
|
||||
device_id=device_id,
|
||||
device_file=device_file,
|
||||
@ -199,7 +192,7 @@ def get_entities(onewirehub: OneWireHub) -> list[SwitchEntity]:
|
||||
return entities
|
||||
|
||||
|
||||
class OneWireProxySwitch(OneWireProxyEntity, SwitchEntity):
|
||||
class OneWireSwitch(OneWireEntity, SwitchEntity):
|
||||
"""Implementation of a 1-Wire switch."""
|
||||
|
||||
entity_description: OneWireSwitchEntityDescription
|
||||
@ -211,8 +204,8 @@ class OneWireProxySwitch(OneWireProxyEntity, SwitchEntity):
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the entity on."""
|
||||
self._write_value_ownet(b"1")
|
||||
self._write_value(b"1")
|
||||
|
||||
def turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the entity off."""
|
||||
self._write_value_ownet(b"0")
|
||||
self._write_value(b"0")
|
||||
|
@ -1210,9 +1210,6 @@ pexpect==4.6.0
|
||||
# homeassistant.components.modem_callerid
|
||||
phone_modem==0.1.1
|
||||
|
||||
# homeassistant.components.onewire
|
||||
pi1wire==0.1.0
|
||||
|
||||
# homeassistant.components.remote_rpi_gpio
|
||||
pigpio==1.78
|
||||
|
||||
|
@ -812,9 +812,6 @@ pexpect==4.6.0
|
||||
# homeassistant.components.modem_callerid
|
||||
phone_modem==0.1.1
|
||||
|
||||
# homeassistant.components.onewire
|
||||
pi1wire==0.1.0
|
||||
|
||||
# homeassistant.components.pilight
|
||||
pilight==0.1.1
|
||||
|
||||
|
@ -7,7 +7,6 @@ from unittest.mock import MagicMock
|
||||
|
||||
from pyownet.protocol import ProtocolError
|
||||
|
||||
from homeassistant.components.onewire.const import DEFAULT_SYSBUS_MOUNT_DIR
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_IDENTIFIERS,
|
||||
@ -29,7 +28,6 @@ from .const import (
|
||||
ATTR_UNIQUE_ID,
|
||||
FIXED_ATTRIBUTES,
|
||||
MOCK_OWPROXY_DEVICES,
|
||||
MOCK_SYSBUS_DEVICES,
|
||||
)
|
||||
|
||||
|
||||
@ -181,30 +179,3 @@ def _setup_owproxy_mock_device_reads(
|
||||
device_sensors = mock_device.get(platform, [])
|
||||
for expected_sensor in device_sensors:
|
||||
sub_read_side_effect.append(expected_sensor[ATTR_INJECT_READS])
|
||||
|
||||
|
||||
def setup_sysbus_mock_devices(
|
||||
platform: str, device_ids: list[str]
|
||||
) -> tuple[list[str], list[Any]]:
|
||||
"""Set up mock for sysbus."""
|
||||
glob_result = []
|
||||
read_side_effect = []
|
||||
|
||||
for device_id in device_ids:
|
||||
mock_device = MOCK_SYSBUS_DEVICES[device_id]
|
||||
|
||||
# Setup directory listing
|
||||
glob_result += [f"/{DEFAULT_SYSBUS_MOUNT_DIR}/{device_id}"]
|
||||
|
||||
# Setup sub-device reads
|
||||
device_sensors = mock_device.get(platform, [])
|
||||
for expected_sensor in device_sensors:
|
||||
if isinstance(expected_sensor[ATTR_INJECT_READS], list):
|
||||
read_side_effect += expected_sensor[ATTR_INJECT_READS]
|
||||
else:
|
||||
read_side_effect.append(expected_sensor[ATTR_INJECT_READS])
|
||||
|
||||
# Ensure enough read side effect
|
||||
read_side_effect.extend([FileNotFoundError("Missing injected value")] * 20)
|
||||
|
||||
return (glob_result, read_side_effect)
|
||||
|
@ -4,15 +4,9 @@ from unittest.mock import MagicMock, patch
|
||||
from pyownet.protocol import ConnError
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.onewire.const import (
|
||||
CONF_MOUNT_DIR,
|
||||
CONF_TYPE_OWSERVER,
|
||||
CONF_TYPE_SYSBUS,
|
||||
DEFAULT_SYSBUS_MOUNT_DIR,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.components.onewire.const import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_USER, ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TYPE
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import MOCK_OWPROXY_DEVICES
|
||||
@ -33,7 +27,6 @@ def get_config_entry(hass: HomeAssistant) -> ConfigEntry:
|
||||
domain=DOMAIN,
|
||||
source=SOURCE_USER,
|
||||
data={
|
||||
CONF_TYPE: CONF_TYPE_OWSERVER,
|
||||
CONF_HOST: "1.2.3.4",
|
||||
CONF_PORT: 1234,
|
||||
},
|
||||
@ -49,24 +42,6 @@ def get_config_entry(hass: HomeAssistant) -> ConfigEntry:
|
||||
return config_entry
|
||||
|
||||
|
||||
@pytest.fixture(name="sysbus_config_entry")
|
||||
def get_sysbus_config_entry(hass: HomeAssistant) -> ConfigEntry:
|
||||
"""Create and register mock config entry."""
|
||||
config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
source=SOURCE_USER,
|
||||
data={
|
||||
CONF_TYPE: CONF_TYPE_SYSBUS,
|
||||
CONF_MOUNT_DIR: DEFAULT_SYSBUS_MOUNT_DIR,
|
||||
},
|
||||
unique_id=f"{CONF_TYPE_SYSBUS}:{DEFAULT_SYSBUS_MOUNT_DIR}",
|
||||
options={},
|
||||
entry_id="3",
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
return config_entry
|
||||
|
||||
|
||||
@pytest.fixture(name="owproxy")
|
||||
def get_owproxy() -> MagicMock:
|
||||
"""Mock owproxy."""
|
||||
@ -82,12 +57,3 @@ def get_owproxy_with_connerror() -> MagicMock:
|
||||
side_effect=ConnError,
|
||||
) as owproxy:
|
||||
yield owproxy
|
||||
|
||||
|
||||
@pytest.fixture(name="sysbus")
|
||||
def get_sysbus() -> MagicMock:
|
||||
"""Mock sysbus."""
|
||||
with patch(
|
||||
"homeassistant.components.onewire.onewirehub.os.path.isdir", return_value=True
|
||||
):
|
||||
yield
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""Constants for 1-Wire integration."""
|
||||
from pi1wire import InvalidCRCException, UnsupportResponseException
|
||||
from pyownet.protocol import Error as ProtocolError
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||
@ -1131,142 +1130,3 @@ MOCK_OWPROXY_DEVICES = {
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
MOCK_SYSBUS_DEVICES = {
|
||||
"00-111111111111": {
|
||||
ATTR_UNKNOWN_DEVICE: True,
|
||||
},
|
||||
"10-111111111111": {
|
||||
ATTR_DEVICE_INFO: {
|
||||
ATTR_IDENTIFIERS: {(DOMAIN, "10-111111111111")},
|
||||
ATTR_MANUFACTURER: MANUFACTURER_MAXIM,
|
||||
ATTR_MODEL: "10",
|
||||
ATTR_NAME: "10-111111111111",
|
||||
},
|
||||
Platform.SENSOR: [
|
||||
{
|
||||
ATTR_DEVICE_CLASS: SensorDeviceClass.TEMPERATURE,
|
||||
ATTR_ENTITY_ID: "sensor.10_111111111111_temperature",
|
||||
ATTR_INJECT_READS: 25.123,
|
||||
ATTR_STATE: "25.1",
|
||||
ATTR_STATE_CLASS: SensorStateClass.MEASUREMENT,
|
||||
ATTR_UNIQUE_ID: "/sys/bus/w1/devices/10-111111111111/w1_slave",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
},
|
||||
],
|
||||
},
|
||||
"22-111111111111": {
|
||||
ATTR_DEVICE_INFO: {
|
||||
ATTR_IDENTIFIERS: {(DOMAIN, "22-111111111111")},
|
||||
ATTR_MANUFACTURER: MANUFACTURER_MAXIM,
|
||||
ATTR_MODEL: "22",
|
||||
ATTR_NAME: "22-111111111111",
|
||||
},
|
||||
Platform.SENSOR: [
|
||||
{
|
||||
ATTR_DEVICE_CLASS: SensorDeviceClass.TEMPERATURE,
|
||||
ATTR_ENTITY_ID: "sensor.22_111111111111_temperature",
|
||||
ATTR_INJECT_READS: FileNotFoundError,
|
||||
ATTR_STATE: STATE_UNKNOWN,
|
||||
ATTR_STATE_CLASS: SensorStateClass.MEASUREMENT,
|
||||
ATTR_UNIQUE_ID: "/sys/bus/w1/devices/22-111111111111/w1_slave",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
},
|
||||
],
|
||||
},
|
||||
"28-111111111111": {
|
||||
ATTR_DEVICE_INFO: {
|
||||
ATTR_IDENTIFIERS: {(DOMAIN, "28-111111111111")},
|
||||
ATTR_MANUFACTURER: MANUFACTURER_MAXIM,
|
||||
ATTR_MODEL: "28",
|
||||
ATTR_NAME: "28-111111111111",
|
||||
},
|
||||
Platform.SENSOR: [
|
||||
{
|
||||
ATTR_DEVICE_CLASS: SensorDeviceClass.TEMPERATURE,
|
||||
ATTR_ENTITY_ID: "sensor.28_111111111111_temperature",
|
||||
ATTR_INJECT_READS: InvalidCRCException,
|
||||
ATTR_STATE: STATE_UNKNOWN,
|
||||
ATTR_STATE_CLASS: SensorStateClass.MEASUREMENT,
|
||||
ATTR_UNIQUE_ID: "/sys/bus/w1/devices/28-111111111111/w1_slave",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
},
|
||||
],
|
||||
},
|
||||
"3B-111111111111": {
|
||||
ATTR_DEVICE_INFO: {
|
||||
ATTR_IDENTIFIERS: {(DOMAIN, "3B-111111111111")},
|
||||
ATTR_MANUFACTURER: MANUFACTURER_MAXIM,
|
||||
ATTR_MODEL: "3B",
|
||||
ATTR_NAME: "3B-111111111111",
|
||||
},
|
||||
Platform.SENSOR: [
|
||||
{
|
||||
ATTR_DEVICE_CLASS: SensorDeviceClass.TEMPERATURE,
|
||||
ATTR_ENTITY_ID: "sensor.3b_111111111111_temperature",
|
||||
ATTR_INJECT_READS: 29.993,
|
||||
ATTR_STATE: "30.0",
|
||||
ATTR_STATE_CLASS: SensorStateClass.MEASUREMENT,
|
||||
ATTR_UNIQUE_ID: "/sys/bus/w1/devices/3B-111111111111/w1_slave",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
},
|
||||
],
|
||||
},
|
||||
"42-111111111111": {
|
||||
ATTR_DEVICE_INFO: {
|
||||
ATTR_IDENTIFIERS: {(DOMAIN, "42-111111111111")},
|
||||
ATTR_MANUFACTURER: MANUFACTURER_MAXIM,
|
||||
ATTR_MODEL: "42",
|
||||
ATTR_NAME: "42-111111111111",
|
||||
},
|
||||
Platform.SENSOR: [
|
||||
{
|
||||
ATTR_DEVICE_CLASS: SensorDeviceClass.TEMPERATURE,
|
||||
ATTR_ENTITY_ID: "sensor.42_111111111111_temperature",
|
||||
ATTR_INJECT_READS: UnsupportResponseException,
|
||||
ATTR_STATE: STATE_UNKNOWN,
|
||||
ATTR_STATE_CLASS: SensorStateClass.MEASUREMENT,
|
||||
ATTR_UNIQUE_ID: "/sys/bus/w1/devices/42-111111111111/w1_slave",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
},
|
||||
],
|
||||
},
|
||||
"42-111111111112": {
|
||||
ATTR_DEVICE_INFO: {
|
||||
ATTR_IDENTIFIERS: {(DOMAIN, "42-111111111112")},
|
||||
ATTR_MANUFACTURER: MANUFACTURER_MAXIM,
|
||||
ATTR_MODEL: "42",
|
||||
ATTR_NAME: "42-111111111112",
|
||||
},
|
||||
Platform.SENSOR: [
|
||||
{
|
||||
ATTR_DEVICE_CLASS: SensorDeviceClass.TEMPERATURE,
|
||||
ATTR_ENTITY_ID: "sensor.42_111111111112_temperature",
|
||||
ATTR_INJECT_READS: [UnsupportResponseException] * 9 + [27.993],
|
||||
ATTR_STATE: "28.0",
|
||||
ATTR_STATE_CLASS: SensorStateClass.MEASUREMENT,
|
||||
ATTR_UNIQUE_ID: "/sys/bus/w1/devices/42-111111111112/w1_slave",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
},
|
||||
],
|
||||
},
|
||||
"42-111111111113": {
|
||||
ATTR_DEVICE_INFO: {
|
||||
ATTR_IDENTIFIERS: {(DOMAIN, "42-111111111113")},
|
||||
ATTR_MANUFACTURER: MANUFACTURER_MAXIM,
|
||||
ATTR_MODEL: "42",
|
||||
ATTR_NAME: "42-111111111113",
|
||||
},
|
||||
Platform.SENSOR: [
|
||||
{
|
||||
ATTR_DEVICE_CLASS: SensorDeviceClass.TEMPERATURE,
|
||||
ATTR_ENTITY_ID: "sensor.42_111111111113_temperature",
|
||||
ATTR_INJECT_READS: [UnsupportResponseException] * 10 + [27.993],
|
||||
ATTR_STATE: STATE_UNKNOWN,
|
||||
ATTR_STATE_CLASS: SensorStateClass.MEASUREMENT,
|
||||
ATTR_UNIQUE_ID: "/sys/bus/w1/devices/42-111111111113/w1_slave",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
"""Tests for 1-Wire devices connected on OWServer."""
|
||||
"""Tests for 1-Wire binary sensors."""
|
||||
import logging
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
@ -27,7 +27,7 @@ def override_platforms():
|
||||
yield
|
||||
|
||||
|
||||
async def test_owserver_binary_sensor(
|
||||
async def test_binary_sensors(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
owproxy: MagicMock,
|
||||
|
@ -4,15 +4,9 @@ from unittest.mock import AsyncMock, patch
|
||||
from pyownet import protocol
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.onewire.const import (
|
||||
CONF_MOUNT_DIR,
|
||||
CONF_TYPE_OWSERVER,
|
||||
CONF_TYPE_SYSBUS,
|
||||
DEFAULT_SYSBUS_MOUNT_DIR,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.components.onewire.const import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_USER, ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TYPE
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import (
|
||||
RESULT_TYPE_ABORT,
|
||||
@ -30,23 +24,14 @@ def override_async_setup_entry() -> AsyncMock:
|
||||
yield mock_setup_entry
|
||||
|
||||
|
||||
async def test_user_owserver(hass: HomeAssistant, mock_setup_entry: AsyncMock):
|
||||
"""Test OWServer user flow."""
|
||||
async def test_user_flow(hass: HomeAssistant, mock_setup_entry: AsyncMock):
|
||||
"""Test user flow."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_TYPE: CONF_TYPE_OWSERVER},
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "owserver"
|
||||
assert not result["errors"]
|
||||
|
||||
# Invalid server
|
||||
with patch(
|
||||
"homeassistant.components.onewire.onewirehub.protocol.proxy",
|
||||
@ -58,7 +43,7 @@ async def test_user_owserver(hass: HomeAssistant, mock_setup_entry: AsyncMock):
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "owserver"
|
||||
assert result["step_id"] == "user"
|
||||
assert result["errors"] == {"base": "cannot_connect"}
|
||||
|
||||
# Valid server
|
||||
@ -73,7 +58,6 @@ async def test_user_owserver(hass: HomeAssistant, mock_setup_entry: AsyncMock):
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == "1.2.3.4"
|
||||
assert result["data"] == {
|
||||
CONF_TYPE: CONF_TYPE_OWSERVER,
|
||||
CONF_HOST: "1.2.3.4",
|
||||
CONF_PORT: 1234,
|
||||
}
|
||||
@ -81,10 +65,10 @@ async def test_user_owserver(hass: HomeAssistant, mock_setup_entry: AsyncMock):
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_user_owserver_duplicate(
|
||||
async def test_user_duplicate(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry, mock_setup_entry: AsyncMock
|
||||
):
|
||||
"""Test OWServer flow."""
|
||||
"""Test user duplicate flow."""
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
@ -93,15 +77,7 @@ async def test_user_owserver_duplicate(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_TYPE: CONF_TYPE_OWSERVER},
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "owserver"
|
||||
assert result["step_id"] == "user"
|
||||
assert not result["errors"]
|
||||
|
||||
# Duplicate server
|
||||
@ -113,93 +89,3 @@ async def test_user_owserver_duplicate(
|
||||
assert result["reason"] == "already_configured"
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_user_sysbus(hass: HomeAssistant, mock_setup_entry: AsyncMock):
|
||||
"""Test SysBus flow."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_TYPE: CONF_TYPE_SYSBUS},
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "mount_dir"
|
||||
assert not result["errors"]
|
||||
|
||||
# Invalid path
|
||||
with patch(
|
||||
"homeassistant.components.onewire.onewirehub.os.path.isdir",
|
||||
return_value=False,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_MOUNT_DIR: "/sys/bus/invalid_directory"},
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "mount_dir"
|
||||
assert result["errors"] == {"base": "invalid_path"}
|
||||
|
||||
# Valid path
|
||||
with patch(
|
||||
"homeassistant.components.onewire.onewirehub.os.path.isdir",
|
||||
return_value=True,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_MOUNT_DIR: "/sys/bus/directory"},
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == "/sys/bus/directory"
|
||||
assert result["data"] == {
|
||||
CONF_TYPE: CONF_TYPE_SYSBUS,
|
||||
CONF_MOUNT_DIR: "/sys/bus/directory",
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_user_sysbus_duplicate(
|
||||
hass: HomeAssistant, sysbus_config_entry: ConfigEntry, mock_setup_entry: AsyncMock
|
||||
):
|
||||
"""Test SysBus duplicate flow."""
|
||||
await hass.config_entries.async_setup(sysbus_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert not result["errors"]
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_TYPE: CONF_TYPE_SYSBUS},
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "mount_dir"
|
||||
assert not result["errors"]
|
||||
|
||||
# Valid path
|
||||
with patch(
|
||||
"homeassistant.components.onewire.onewirehub.os.path.isdir",
|
||||
return_value=True,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_MOUNT_DIR: DEFAULT_SYSBUS_MOUNT_DIR},
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
@ -52,7 +52,6 @@ async def test_entry_diagnostics(
|
||||
"data": {
|
||||
"host": REDACTED,
|
||||
"port": 1234,
|
||||
"type": "OWServer",
|
||||
},
|
||||
"options": {
|
||||
"device_options": {
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""Tests for 1-Wire config flow."""
|
||||
import logging
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from pyownet import protocol
|
||||
@ -11,7 +10,7 @@ from homeassistant.core import HomeAssistant
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("owproxy_with_connerror")
|
||||
async def test_owserver_connect_failure(hass: HomeAssistant, config_entry: ConfigEntry):
|
||||
async def test_connect_failure(hass: HomeAssistant, config_entry: ConfigEntry):
|
||||
"""Test connection failure raises ConfigEntryNotReady."""
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -21,7 +20,7 @@ async def test_owserver_connect_failure(hass: HomeAssistant, config_entry: Confi
|
||||
assert not hass.data.get(DOMAIN)
|
||||
|
||||
|
||||
async def test_owserver_listing_failure(
|
||||
async def test_listing_failure(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry, owproxy: MagicMock
|
||||
):
|
||||
"""Test listing failure raises ConfigEntryNotReady."""
|
||||
@ -49,34 +48,3 @@ async def test_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry):
|
||||
|
||||
assert config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
assert not hass.data.get(DOMAIN)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("sysbus")
|
||||
async def test_warning_no_devices(
|
||||
hass: HomeAssistant,
|
||||
sysbus_config_entry: ConfigEntry,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
):
|
||||
"""Test warning is generated when no sysbus devices found."""
|
||||
with caplog.at_level(logging.WARNING, logger="homeassistant.components.onewire"):
|
||||
await hass.config_entries.async_setup(sysbus_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert "No onewire sensor found. Check if dtoverlay=w1-gpio" in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("sysbus")
|
||||
async def test_unload_sysbus_entry(
|
||||
hass: HomeAssistant, sysbus_config_entry: ConfigEntry
|
||||
):
|
||||
"""Test being able to unload an entry."""
|
||||
await hass.config_entries.async_setup(sysbus_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
assert sysbus_config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
assert await hass.config_entries.async_unload(sysbus_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert sysbus_config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
assert not hass.data.get(DOMAIN)
|
||||
|
@ -2,8 +2,6 @@
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from homeassistant.components.onewire.const import (
|
||||
CONF_TYPE_SYSBUS,
|
||||
DOMAIN,
|
||||
INPUT_ENTRY_CLEAR_OPTIONS,
|
||||
INPUT_ENTRY_DEVICE_SELECTION,
|
||||
)
|
||||
@ -26,13 +24,7 @@ class FakeDevice:
|
||||
name_by_user = "Given Name"
|
||||
|
||||
|
||||
class FakeOWHubSysBus:
|
||||
"""Mock Class for mocking onewire hub."""
|
||||
|
||||
type = CONF_TYPE_SYSBUS
|
||||
|
||||
|
||||
async def test_user_owserver_options_clear(
|
||||
async def test_user_options_clear(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
owproxy: MagicMock,
|
||||
@ -61,7 +53,7 @@ async def test_user_owserver_options_clear(
|
||||
assert result["data"] == {}
|
||||
|
||||
|
||||
async def test_user_owserver_options_empty_selection(
|
||||
async def test_user_options_empty_selection(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
owproxy: MagicMock,
|
||||
@ -91,7 +83,7 @@ async def test_user_owserver_options_empty_selection(
|
||||
assert result["errors"] == {"base": "device_not_selected"}
|
||||
|
||||
|
||||
async def test_user_owserver_options_set_single(
|
||||
async def test_user_options_set_single(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
owproxy: MagicMock,
|
||||
@ -134,7 +126,7 @@ async def test_user_owserver_options_set_single(
|
||||
)
|
||||
|
||||
|
||||
async def test_user_owserver_options_set_multiple(
|
||||
async def test_user_options_set_multiple(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
owproxy: MagicMock,
|
||||
@ -208,7 +200,7 @@ async def test_user_owserver_options_set_multiple(
|
||||
)
|
||||
|
||||
|
||||
async def test_user_owserver_options_no_devices(
|
||||
async def test_user_options_no_devices(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
owproxy: MagicMock,
|
||||
@ -223,15 +215,3 @@ async def test_user_owserver_options_no_devices(
|
||||
await hass.async_block_till_done()
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "No configurable devices found."
|
||||
|
||||
|
||||
async def test_user_sysbus_options(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
):
|
||||
"""Test that SysBus options flow aborts on init."""
|
||||
hass.data[DOMAIN] = {config_entry.entry_id: FakeOWHubSysBus()}
|
||||
result = await hass.config_entries.options.async_init(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "SysBus setup does not have any config options."
|
||||
|
@ -1,4 +1,4 @@
|
||||
"""Tests for 1-Wire sensor platform."""
|
||||
"""Tests for 1-Wire sensors."""
|
||||
import logging
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
@ -14,14 +14,8 @@ from . import (
|
||||
check_device_registry,
|
||||
check_entities,
|
||||
setup_owproxy_mock_devices,
|
||||
setup_sysbus_mock_devices,
|
||||
)
|
||||
from .const import (
|
||||
ATTR_DEVICE_INFO,
|
||||
ATTR_UNKNOWN_DEVICE,
|
||||
MOCK_OWPROXY_DEVICES,
|
||||
MOCK_SYSBUS_DEVICES,
|
||||
)
|
||||
from .const import ATTR_DEVICE_INFO, ATTR_UNKNOWN_DEVICE, MOCK_OWPROXY_DEVICES
|
||||
|
||||
from tests.common import mock_device_registry, mock_registry
|
||||
|
||||
@ -33,7 +27,7 @@ def override_platforms():
|
||||
yield
|
||||
|
||||
|
||||
async def test_owserver_sensor(
|
||||
async def test_sensors(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
owproxy: MagicMock,
|
||||
@ -73,44 +67,3 @@ async def test_owserver_sensor(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
check_entities(hass, entity_registry, expected_entities)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("sysbus")
|
||||
@pytest.mark.parametrize("device_id", MOCK_SYSBUS_DEVICES.keys(), indirect=True)
|
||||
async def test_onewiredirect_setup_valid_device(
|
||||
hass: HomeAssistant,
|
||||
sysbus_config_entry: ConfigEntry,
|
||||
device_id: str,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
):
|
||||
"""Test that sysbus config entry works correctly."""
|
||||
device_registry = mock_device_registry(hass)
|
||||
entity_registry = mock_registry(hass)
|
||||
|
||||
glob_result, read_side_effect = setup_sysbus_mock_devices(
|
||||
Platform.SENSOR, [device_id]
|
||||
)
|
||||
|
||||
mock_device = MOCK_SYSBUS_DEVICES[device_id]
|
||||
expected_entities = mock_device.get(Platform.SENSOR, [])
|
||||
expected_devices = ensure_list(mock_device.get(ATTR_DEVICE_INFO))
|
||||
|
||||
with patch("pi1wire._finder.glob.glob", return_value=glob_result,), patch(
|
||||
"pi1wire.OneWire.get_temperature",
|
||||
side_effect=read_side_effect,
|
||||
), caplog.at_level(
|
||||
logging.WARNING, logger="homeassistant.components.onewire"
|
||||
), patch(
|
||||
"homeassistant.components.onewire.sensor.asyncio.sleep"
|
||||
):
|
||||
await hass.config_entries.async_setup(sysbus_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert "No onewire sensor found. Check if dtoverlay=w1-gpio" not in caplog.text
|
||||
if mock_device.get(ATTR_UNKNOWN_DEVICE):
|
||||
assert "Ignoring unknown device family" in caplog.text
|
||||
else:
|
||||
assert "Ignoring unknown device family" not in caplog.text
|
||||
|
||||
check_device_registry(device_registry, expected_devices)
|
||||
assert len(entity_registry.entities) == len(expected_entities)
|
||||
check_entities(hass, entity_registry, expected_entities)
|
||||
|
@ -1,4 +1,4 @@
|
||||
"""Tests for 1-Wire devices connected on OWServer."""
|
||||
"""Tests for 1-Wire switches."""
|
||||
import logging
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
@ -35,7 +35,7 @@ def override_platforms():
|
||||
yield
|
||||
|
||||
|
||||
async def test_owserver_switch(
|
||||
async def test_switches(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
owproxy: MagicMock,
|
||||
|
Loading…
x
Reference in New Issue
Block a user