Skip to content

Commit 1d6c662

Browse files
authored
Migrate onewire to async library (home-assistant#154439)
1 parent b6337c0 commit 1d6c662

File tree

16 files changed

+117
-108
lines changed

16 files changed

+117
-108
lines changed

homeassistant/components/onewire/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import logging
44

5-
from pyownet import protocol
5+
from aio_ownet.exceptions import OWServerConnectionError, OWServerReturnError
66

77
from homeassistant.const import Platform
88
from homeassistant.core import HomeAssistant
@@ -28,8 +28,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: OneWireConfigEntry) -> b
2828
try:
2929
await onewire_hub.initialize()
3030
except (
31-
protocol.ConnError, # Failed to connect to the server
32-
protocol.OwnetError, # Connected to server, but failed to list the devices
31+
OWServerConnectionError, # Failed to connect to the server
32+
OWServerReturnError, # Connected to server, but failed to list the devices
3333
) as exc:
3434
raise ConfigEntryNotReady from exc
3535

homeassistant/components/onewire/config_flow.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from copy import deepcopy
66
from typing import Any
77

8-
from pyownet import protocol
8+
from aio_ownet.exceptions import OWServerConnectionError
9+
from aio_ownet.proxy import OWServerStatelessProxy
910
import voluptuous as vol
1011

1112
from homeassistant.config_entries import (
@@ -45,11 +46,10 @@ async def validate_input(
4546
hass: HomeAssistant, data: dict[str, Any], errors: dict[str, str]
4647
) -> None:
4748
"""Validate the user input allows us to connect."""
49+
proxy = OWServerStatelessProxy(data[CONF_HOST], data[CONF_PORT])
4850
try:
49-
await hass.async_add_executor_job(
50-
protocol.proxy, data[CONF_HOST], data[CONF_PORT]
51-
)
52-
except protocol.ConnError:
51+
await proxy.validate()
52+
except OWServerConnectionError:
5353
errors["base"] = "cannot_connect"
5454

5555

homeassistant/components/onewire/entity.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
import logging
77
from typing import Any
88

9-
from pyownet import protocol
9+
from aio_ownet.exceptions import OWServerError
10+
from aio_ownet.proxy import OWServerStatelessProxy
1011

1112
from homeassistant.helpers.device_registry import DeviceInfo
1213
from homeassistant.helpers.entity import Entity, EntityDescription
@@ -36,7 +37,7 @@ def __init__(
3637
device_id: str,
3738
device_info: DeviceInfo,
3839
device_file: str,
39-
owproxy: protocol._Proxy,
40+
owproxy: OWServerStatelessProxy,
4041
) -> None:
4142
"""Initialize the entity."""
4243
self.entity_description = description
@@ -55,20 +56,19 @@ def extra_state_attributes(self) -> dict[str, Any] | None:
5556
"device_file": self._device_file,
5657
}
5758

58-
def _read_value(self) -> str:
59+
async def _read_value(self) -> str:
5960
"""Read a value from the server."""
60-
read_bytes: bytes = self._owproxy.read(self._device_file)
61-
return read_bytes.decode().lstrip()
61+
return (await self._owproxy.read(self._device_file)).decode().lstrip()
6262

63-
def _write_value(self, value: bytes) -> None:
63+
async def _write_value(self, value: bytes) -> None:
6464
"""Write a value to the server."""
65-
self._owproxy.write(self._device_file, value)
65+
await self._owproxy.write(self._device_file, value)
6666

67-
def update(self) -> None:
67+
async def async_update(self) -> None:
6868
"""Get the latest data from the device."""
6969
try:
70-
self._value_raw = float(self._read_value())
71-
except protocol.Error as exc:
70+
self._value_raw = float(await self._read_value())
71+
except OWServerError as exc:
7272
if self._last_update_success:
7373
_LOGGER.error("Error fetching %s data: %s", self.name, exc)
7474
self._last_update_success = False

homeassistant/components/onewire/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"documentation": "https://www.home-assistant.io/integrations/onewire",
77
"integration_type": "hub",
88
"iot_class": "local_polling",
9-
"loggers": ["pyownet"],
10-
"requirements": ["pyownet==0.10.0.post1"],
9+
"loggers": ["aio_ownet"],
10+
"requirements": ["aio-ownet==0.0.3"],
1111
"zeroconf": ["_owserver._tcp.local."]
1212
}

homeassistant/components/onewire/onewirehub.py

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import logging
88
import os
99

10-
from pyownet import protocol
10+
from aio_ownet.definitions import OWServerCommonPath
11+
from aio_ownet.exceptions import OWServerProtocolError, OWServerReturnError
12+
from aio_ownet.proxy import OWServerStatelessProxy
1113

1214
from homeassistant.config_entries import ConfigEntry
1315
from homeassistant.const import ATTR_VIA_DEVICE, CONF_HOST, CONF_PORT
@@ -57,7 +59,7 @@ def _is_known_device(device_family: str, device_type: str | None) -> bool:
5759
class OneWireHub:
5860
"""Hub to communicate with server."""
5961

60-
owproxy: protocol._Proxy
62+
owproxy: OWServerStatelessProxy
6163
devices: list[OWDeviceDescription]
6264
_version: str | None = None
6365

@@ -66,23 +68,25 @@ def __init__(self, hass: HomeAssistant, config_entry: OneWireConfigEntry) -> Non
6668
self._hass = hass
6769
self._config_entry = config_entry
6870

69-
def _initialize(self) -> None:
70-
"""Connect to the server, and discover connected devices.
71-
72-
Needs to be run in executor.
73-
"""
71+
async def _initialize(self) -> None:
72+
"""Connect to the server, and discover connected devices."""
7473
host = self._config_entry.data[CONF_HOST]
7574
port = self._config_entry.data[CONF_PORT]
7675
_LOGGER.debug("Initializing connection to %s:%s", host, port)
77-
self.owproxy = protocol.proxy(host, port)
78-
with contextlib.suppress(protocol.OwnetError):
76+
self.owproxy = OWServerStatelessProxy(
77+
self._config_entry.data[CONF_HOST], self._config_entry.data[CONF_PORT]
78+
)
79+
await self.owproxy.validate()
80+
with contextlib.suppress(OWServerReturnError):
7981
# Version is not available on all servers
80-
self._version = self.owproxy.read(protocol.PTH_VERSION).decode()
81-
self.devices = _discover_devices(self.owproxy)
82+
self._version = (
83+
await self.owproxy.read(OWServerCommonPath.VERSION)
84+
).decode()
85+
self.devices = await _discover_devices(self.owproxy)
8286

8387
async def initialize(self) -> None:
8488
"""Initialize a config entry."""
85-
await self._hass.async_add_executor_job(self._initialize)
89+
await self._initialize()
8690
self._populate_device_registry(self.devices)
8791

8892
@callback
@@ -106,9 +110,7 @@ def schedule_scan_for_new_devices(self) -> None:
106110

107111
async def _scan_for_new_devices(self, _: datetime) -> None:
108112
"""Scan the bus for new devices."""
109-
devices = await self._hass.async_add_executor_job(
110-
_discover_devices, self.owproxy
111-
)
113+
devices = await _discover_devices(self.owproxy)
112114
existing_device_ids = [device.id for device in self.devices]
113115
new_devices = [
114116
device for device in devices if device.id not in existing_device_ids
@@ -121,16 +123,16 @@ async def _scan_for_new_devices(self, _: datetime) -> None:
121123
)
122124

123125

124-
def _discover_devices(
125-
owproxy: protocol._Proxy, path: str = "/", parent_id: str | None = None
126+
async def _discover_devices(
127+
owproxy: OWServerStatelessProxy, path: str = "/", parent_id: str | None = None
126128
) -> list[OWDeviceDescription]:
127129
"""Discover all server devices."""
128130
devices: list[OWDeviceDescription] = []
129-
for device_path in owproxy.dir(path):
131+
for device_path in await owproxy.dir(path):
130132
device_id = os.path.split(os.path.split(device_path)[0])[1]
131-
device_family = owproxy.read(f"{device_path}family").decode()
133+
device_family = (await owproxy.read(f"{device_path}family")).decode()
132134
_LOGGER.debug("read `%sfamily`: %s", device_path, device_family)
133-
device_type = _get_device_type(owproxy, device_path)
135+
device_type = await _get_device_type(owproxy, device_path)
134136
if not _is_known_device(device_family, device_type):
135137
_LOGGER.warning(
136138
"Ignoring unknown device family/type (%s/%s) found for device %s",
@@ -159,22 +161,24 @@ def _discover_devices(
159161
devices.append(device)
160162
if device_branches := DEVICE_COUPLERS.get(device_family):
161163
for branch in device_branches:
162-
devices += _discover_devices(
164+
devices += await _discover_devices(
163165
owproxy, f"{device_path}{branch}", device_id
164166
)
165167

166168
return devices
167169

168170

169-
def _get_device_type(owproxy: protocol._Proxy, device_path: str) -> str | None:
171+
async def _get_device_type(
172+
owproxy: OWServerStatelessProxy, device_path: str
173+
) -> str | None:
170174
"""Get device model."""
171175
try:
172-
device_type: str = owproxy.read(f"{device_path}type").decode()
173-
except protocol.ProtocolError as exc:
176+
device_type = (await owproxy.read(f"{device_path}type")).decode()
177+
except OWServerProtocolError as exc:
174178
_LOGGER.debug("Unable to read `%stype`: %s", device_path, exc)
175179
return None
176180
_LOGGER.debug("read `%stype`: %s", device_path, device_type)
177181
if device_type == "EDS":
178-
device_type = owproxy.read(f"{device_path}device_type").decode()
182+
device_type = (await owproxy.read(f"{device_path}device_type")).decode()
179183
_LOGGER.debug("read `%sdevice_type`: %s", device_path, device_type)
180184
return device_type

homeassistant/components/onewire/select.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,6 @@ def current_option(self) -> str | None:
105105
"""Return the selected entity option to represent the entity state."""
106106
return str(self._state)
107107

108-
def select_option(self, option: str) -> None:
108+
async def async_select_option(self, option: str) -> None:
109109
"""Change the selected option."""
110-
self._write_value(option.encode("ascii"))
110+
await self._write_value(option.encode("ascii"))

homeassistant/components/onewire/sensor.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import os
1010
from typing import Any
1111

12-
from pyownet import protocol
12+
from aio_ownet.exceptions import OWServerReturnError
1313

1414
from homeassistant.components.sensor import (
1515
SensorDeviceClass,
@@ -397,11 +397,7 @@ async def _add_entities(
397397
"""Add 1-Wire entities for all devices."""
398398
if not devices:
399399
return
400-
# note: we have to go through the executor as SENSOR platform
401-
# makes extra calls to the hub during device listing
402-
entities = await hass.async_add_executor_job(
403-
get_entities, hub, devices, config_entry.options
404-
)
400+
entities = await get_entities(hub, devices, config_entry.options)
405401
async_add_entities(entities, True)
406402

407403
hub = config_entry.runtime_data
@@ -411,7 +407,7 @@ async def _add_entities(
411407
)
412408

413409

414-
def get_entities(
410+
async def get_entities(
415411
onewire_hub: OneWireHub,
416412
devices: list[OWDeviceDescription],
417413
options: Mapping[str, Any],
@@ -441,8 +437,10 @@ def get_entities(
441437
if description.key.startswith("moisture/"):
442438
s_id = description.key.split(".")[1]
443439
is_leaf = int(
444-
onewire_hub.owproxy.read(
445-
f"{device_path}moisture/is_leaf.{s_id}"
440+
(
441+
await onewire_hub.owproxy.read(
442+
f"{device_path}moisture/is_leaf.{s_id}"
443+
)
446444
).decode()
447445
)
448446
if is_leaf:
@@ -463,8 +461,8 @@ def get_entities(
463461
if family == "12":
464462
# We need to check if there is TAI8570 plugged in
465463
try:
466-
onewire_hub.owproxy.read(device_file)
467-
except protocol.OwnetError as err:
464+
await onewire_hub.owproxy.read(device_file)
465+
except OWServerReturnError as err:
468466
_LOGGER.debug(
469467
"Ignoring unreachable sensor %s",
470468
device_file,

homeassistant/components/onewire/switch.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,10 @@ def is_on(self) -> bool | None:
220220
return None
221221
return self._state == 1
222222

223-
def turn_on(self, **kwargs: Any) -> None:
223+
async def async_turn_on(self, **kwargs: Any) -> None:
224224
"""Turn the entity on."""
225-
self._write_value(b"1")
225+
await self._write_value(b"1")
226226

227-
def turn_off(self, **kwargs: Any) -> None:
227+
async def async_turn_off(self, **kwargs: Any) -> None:
228228
"""Turn the entity off."""
229-
self._write_value(b"0")
229+
await self._write_value(b"0")

requirements_all.txt

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

requirements_test_all.txt

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)