Discover onewire devices at startup (#42410)

This commit is contained in:
epenet 2020-10-27 05:36:51 +01:00 committed by GitHub
parent 5f3384fc8a
commit f3a15eab6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 26 deletions

View File

@ -1,6 +1,7 @@
"""Hub for communication with 1-Wire server or mount_dir."""
import os
from pi1wire import Pi1Wire
from pyownet import protocol
from homeassistant.config_entries import ConfigEntry
@ -17,7 +18,10 @@ class OneWireHub:
def __init__(self, hass: HomeAssistantType):
"""Initialize."""
self.hass = hass
self.type: str = None
self.pi1proxy: Pi1Wire = None
self.owproxy: protocol._Proxy = None
self.devices = None
async def connect(self, host: str, port: int) -> None:
"""Connect to the owserver host."""
@ -32,15 +36,44 @@ class OneWireHub:
"""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."""
if config_entry.data[CONF_TYPE] == CONF_TYPE_SYSBUS:
self.type = config_entry.data[CONF_TYPE]
if self.type == CONF_TYPE_SYSBUS:
await self.check_mount_dir(config_entry.data[CONF_MOUNT_DIR])
elif config_entry.data[CONF_TYPE] == CONF_TYPE_OWSERVER:
elif self.type == CONF_TYPE_OWSERVER:
host = config_entry.data[CONF_HOST]
port = config_entry.data[CONF_PORT]
await self.connect(host, port)
await self.discover_devices()
async def discover_devices(self):
"""Discover all devices."""
if self.devices is None:
if self.type == CONF_TYPE_SYSBUS:
self.devices = await self.hass.async_add_executor_job(
self.pi1proxy.find_all_sensors
)
if self.type == CONF_TYPE_OWSERVER:
self.devices = await self.hass.async_add_executor_job(
self._discover_devices_owserver
)
return self.devices
def _discover_devices_owserver(self):
"""Discover all owserver devices."""
devices = []
for device_path in self.owproxy.dir():
devices.append(
{
"path": device_path,
"family": self.owproxy.read(f"{device_path}family").decode(),
"type": self.owproxy.read(f"{device_path}type").decode(),
}
)
return devices
class CannotConnect(HomeAssistantError):

View File

@ -4,7 +4,7 @@ import logging
import os
from typing import Any, Dict, Optional
from pi1wire import InvalidCRCException, Pi1Wire, UnsupportResponseException
from pi1wire import InvalidCRCException, UnsupportResponseException
from pyownet import protocol
import voluptuous as vol
@ -175,21 +175,10 @@ def get_entities(onewirehub: OneWireHub, config):
conf_type = config[CONF_TYPE]
# We have an owserver on a remote(or local) host/port
if conf_type == CONF_TYPE_OWSERVER:
owhost = config[CONF_HOST]
owport = config[CONF_PORT]
try:
devices = onewirehub.owproxy.dir()
except protocol.OwnetError as exc:
_LOGGER.error(
"Failed to list devices on %s:%d, got: %s", owhost, owport, exc
)
return entities
for device in devices:
_LOGGER.debug("Found device: %s", device)
family = onewirehub.owproxy.read(f"{device}family").decode()
device_type = onewirehub.owproxy.read(f"{device}type").decode()
sensor_id = os.path.split(os.path.split(device)[0])[1]
for device in onewirehub.devices:
family = device["family"]
device_type = device["type"]
sensor_id = os.path.split(os.path.split(device["path"])[0])[1]
dev_type = "std"
if "EF" in family:
dev_type = "HobbyBoard"
@ -199,7 +188,7 @@ def get_entities(onewirehub: OneWireHub, config):
_LOGGER.warning(
"Ignoring unknown family (%s) of sensor found for device: %s",
family,
device,
sensor_id,
)
continue
device_info = {
@ -213,12 +202,14 @@ def get_entities(onewirehub: OneWireHub, config):
s_id = sensor_key.split("_")[1]
is_leaf = int(
onewirehub.owproxy.read(
f"{device}moisture/is_leaf.{s_id}"
f"{device['path']}moisture/is_leaf.{s_id}"
).decode()
)
if is_leaf:
sensor_key = f"wetness_{s_id}"
device_file = os.path.join(os.path.split(device)[0], sensor_value)
device_file = os.path.join(
os.path.split(device["path"])[0], sensor_value
)
entities.append(
OneWireProxy(
device_names.get(sensor_id, sensor_id),
@ -233,7 +224,7 @@ def get_entities(onewirehub: OneWireHub, config):
elif conf_type == CONF_TYPE_SYSBUS:
base_dir = config[CONF_MOUNT_DIR]
_LOGGER.debug("Initializing using SysBus %s", base_dir)
for p1sensor in Pi1Wire(base_dir).find_all_sensors():
for p1sensor in onewirehub.devices:
family = p1sensor.mac_address[:2]
sensor_id = f"{family}-{p1sensor.mac_address[2:]}"
if family not in DEVICE_SUPPORT_SYSBUS:

View File

@ -418,7 +418,7 @@ async def test_owserver_setup_valid_device(hass, device_id):
# Ensure enough read side effect
read_side_effect.extend([ProtocolError("Missing injected value")] * 10)
with patch("homeassistant.components.onewire.sensor.protocol.proxy") as owproxy:
with patch("homeassistant.components.onewire.onewirehub.protocol.proxy") as owproxy:
owproxy.return_value.dir.return_value = dir_return_value
owproxy.return_value.read.side_effect = read_side_effect

View File

@ -142,7 +142,7 @@ async def test_onewiredirect_setup_valid_device(hass, device_id):
read_side_effect.extend([FileNotFoundError("Missing injected value")] * 20)
with patch(
"homeassistant.components.onewire.sensor.os.path.isdir", return_value=True
"homeassistant.components.onewire.onewirehub.os.path.isdir", return_value=True
), patch("pi1wire._finder.glob.glob", return_value=glob_result,), patch(
"pi1wire.OneWire.get_temperature",
side_effect=read_side_effect,

View File

@ -16,8 +16,8 @@ from . import setup_onewire_owserver_integration, setup_onewire_sysbus_integrati
from tests.common import MockConfigEntry
async def test_owserver_platform_not_ready(hass):
"""Create the 1-Wire integration."""
async def test_owserver_connect_failure(hass):
"""Test connection failure raises ConfigEntryNotReady."""
config_entry_owserver = MockConfigEntry(
domain=DOMAIN,
source="user",