mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Bump rachiopy to 1.0.3 and update methods to handle changes (#41398)
This commit is contained in:
parent
80522f1bdc
commit
899431235b
@ -4,6 +4,7 @@ import logging
|
|||||||
import secrets
|
import secrets
|
||||||
|
|
||||||
from rachiopy import Rachio
|
from rachiopy import Rachio
|
||||||
|
from requests.exceptions import ConnectTimeout
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||||
@ -18,7 +19,6 @@ from .const import (
|
|||||||
CONF_WEBHOOK_ID,
|
CONF_WEBHOOK_ID,
|
||||||
DEFAULT_MANUAL_RUN_MINS,
|
DEFAULT_MANUAL_RUN_MINS,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
RACHIO_API_EXCEPTIONS,
|
|
||||||
)
|
)
|
||||||
from .device import RachioPerson
|
from .device import RachioPerson
|
||||||
from .webhooks import (
|
from .webhooks import (
|
||||||
@ -113,9 +113,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
# Get the API user
|
# Get the API user
|
||||||
try:
|
try:
|
||||||
await hass.async_add_executor_job(person.setup, hass)
|
await hass.async_add_executor_job(person.setup, hass)
|
||||||
# Yes we really do get all these exceptions (hopefully rachiopy switches to requests)
|
except ConnectTimeout as error:
|
||||||
# and there is not a reasonable timeout here so it can block for a long time
|
|
||||||
except RACHIO_API_EXCEPTIONS as error:
|
|
||||||
_LOGGER.error("Could not reach the Rachio API: %s", error)
|
_LOGGER.error("Could not reach the Rachio API: %s", error)
|
||||||
raise ConfigEntryNotReady from error
|
raise ConfigEntryNotReady from error
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from rachiopy import Rachio
|
from rachiopy import Rachio
|
||||||
|
from requests.exceptions import ConnectTimeout
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries, core, exceptions
|
from homeassistant import config_entries, core, exceptions
|
||||||
@ -14,7 +15,6 @@ from .const import (
|
|||||||
KEY_ID,
|
KEY_ID,
|
||||||
KEY_STATUS,
|
KEY_STATUS,
|
||||||
KEY_USERNAME,
|
KEY_USERNAME,
|
||||||
RACHIO_API_EXCEPTIONS,
|
|
||||||
)
|
)
|
||||||
from .const import DOMAIN # pylint:disable=unused-import
|
from .const import DOMAIN # pylint:disable=unused-import
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ async def validate_input(hass: core.HomeAssistant, data):
|
|||||||
rachio = Rachio(data[CONF_API_KEY])
|
rachio = Rachio(data[CONF_API_KEY])
|
||||||
username = None
|
username = None
|
||||||
try:
|
try:
|
||||||
data = await hass.async_add_executor_job(rachio.person.getInfo)
|
data = await hass.async_add_executor_job(rachio.person.info)
|
||||||
_LOGGER.debug("rachio.person.getInfo: %s", data)
|
_LOGGER.debug("rachio.person.getInfo: %s", data)
|
||||||
if int(data[0][KEY_STATUS]) != HTTP_OK:
|
if int(data[0][KEY_STATUS]) != HTTP_OK:
|
||||||
raise InvalidAuth
|
raise InvalidAuth
|
||||||
@ -43,8 +43,7 @@ async def validate_input(hass: core.HomeAssistant, data):
|
|||||||
raise CannotConnect
|
raise CannotConnect
|
||||||
|
|
||||||
username = data[1][KEY_USERNAME]
|
username = data[1][KEY_USERNAME]
|
||||||
# Yes we really do get all these exceptions (hopefully rachiopy switches to requests)
|
except ConnectTimeout as error:
|
||||||
except RACHIO_API_EXCEPTIONS as error:
|
|
||||||
_LOGGER.error("Could not reach the Rachio API: %s", error)
|
_LOGGER.error("Could not reach the Rachio API: %s", error)
|
||||||
raise CannotConnect from error
|
raise CannotConnect from error
|
||||||
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
"""Constants for rachio."""
|
"""Constants for rachio."""
|
||||||
|
|
||||||
import http.client
|
|
||||||
import ssl
|
|
||||||
|
|
||||||
DEFAULT_NAME = "Rachio"
|
DEFAULT_NAME = "Rachio"
|
||||||
|
|
||||||
DOMAIN = "rachio"
|
DOMAIN = "rachio"
|
||||||
@ -50,14 +47,6 @@ KEY_CUSTOM_SHADE = "customShade"
|
|||||||
KEY_CUSTOM_CROP = "customCrop"
|
KEY_CUSTOM_CROP = "customCrop"
|
||||||
KEY_CUSTOM_SLOPE = "customSlope"
|
KEY_CUSTOM_SLOPE = "customSlope"
|
||||||
|
|
||||||
# Yes we really do get all these exceptions (hopefully rachiopy switches to requests)
|
|
||||||
RACHIO_API_EXCEPTIONS = (
|
|
||||||
http.client.HTTPException,
|
|
||||||
ssl.SSLError,
|
|
||||||
OSError,
|
|
||||||
AssertionError,
|
|
||||||
)
|
|
||||||
|
|
||||||
STATUS_ONLINE = "ONLINE"
|
STATUS_ONLINE = "ONLINE"
|
||||||
|
|
||||||
SCHEDULE_TYPE_FIXED = "FIXED"
|
SCHEDULE_TYPE_FIXED = "FIXED"
|
||||||
|
@ -39,7 +39,7 @@ class RachioPerson:
|
|||||||
|
|
||||||
def setup(self, hass):
|
def setup(self, hass):
|
||||||
"""Rachio device setup."""
|
"""Rachio device setup."""
|
||||||
response = self.rachio.person.getInfo()
|
response = self.rachio.person.info()
|
||||||
assert int(response[0][KEY_STATUS]) == HTTP_OK, "API key error"
|
assert int(response[0][KEY_STATUS]) == HTTP_OK, "API key error"
|
||||||
self._id = response[1][KEY_ID]
|
self._id = response[1][KEY_ID]
|
||||||
|
|
||||||
@ -49,7 +49,9 @@ class RachioPerson:
|
|||||||
self.username = data[1][KEY_USERNAME]
|
self.username = data[1][KEY_USERNAME]
|
||||||
devices = data[1][KEY_DEVICES]
|
devices = data[1][KEY_DEVICES]
|
||||||
for controller in devices:
|
for controller in devices:
|
||||||
webhooks = self.rachio.notification.getDeviceWebhook(controller[KEY_ID])[1]
|
webhooks = self.rachio.notification.get_device_webhook(controller[KEY_ID])[
|
||||||
|
1
|
||||||
|
]
|
||||||
# The API does not provide a way to tell if a controller is shared
|
# The API does not provide a way to tell if a controller is shared
|
||||||
# or if they are the owner. To work around this problem we fetch the webooks
|
# or if they are the owner. To work around this problem we fetch the webooks
|
||||||
# before we setup the device so we can skip it instead of failing.
|
# before we setup the device so we can skip it instead of failing.
|
||||||
@ -113,7 +115,7 @@ class RachioIro:
|
|||||||
if not self._webhooks:
|
if not self._webhooks:
|
||||||
# We fetched webhooks when we created the device, however if we call _init_webhooks
|
# We fetched webhooks when we created the device, however if we call _init_webhooks
|
||||||
# again we need to fetch again
|
# again we need to fetch again
|
||||||
self._webhooks = self.rachio.notification.getDeviceWebhook(
|
self._webhooks = self.rachio.notification.get_device_webhook(
|
||||||
self.controller_id
|
self.controller_id
|
||||||
)[1]
|
)[1]
|
||||||
for webhook in self._webhooks:
|
for webhook in self._webhooks:
|
||||||
@ -121,21 +123,21 @@ class RachioIro:
|
|||||||
webhook[KEY_EXTERNAL_ID].startswith(WEBHOOK_CONST_ID)
|
webhook[KEY_EXTERNAL_ID].startswith(WEBHOOK_CONST_ID)
|
||||||
or webhook[KEY_ID] == current_webhook_id
|
or webhook[KEY_ID] == current_webhook_id
|
||||||
):
|
):
|
||||||
self.rachio.notification.deleteWebhook(webhook[KEY_ID])
|
self.rachio.notification.delete(webhook[KEY_ID])
|
||||||
self._webhooks = None
|
self._webhooks = None
|
||||||
|
|
||||||
_deinit_webhooks(None)
|
_deinit_webhooks(None)
|
||||||
|
|
||||||
# Choose which events to listen for and get their IDs
|
# Choose which events to listen for and get their IDs
|
||||||
event_types = []
|
event_types = []
|
||||||
for event_type in self.rachio.notification.getWebhookEventType()[1]:
|
for event_type in self.rachio.notification.get_webhook_event_type()[1]:
|
||||||
if event_type[KEY_NAME] in LISTEN_EVENT_TYPES:
|
if event_type[KEY_NAME] in LISTEN_EVENT_TYPES:
|
||||||
event_types.append({"id": event_type[KEY_ID]})
|
event_types.append({"id": event_type[KEY_ID]})
|
||||||
|
|
||||||
# Register to listen to these events from the device
|
# Register to listen to these events from the device
|
||||||
url = self.rachio.webhook_url
|
url = self.rachio.webhook_url
|
||||||
auth = WEBHOOK_CONST_ID + self.rachio.webhook_auth
|
auth = WEBHOOK_CONST_ID + self.rachio.webhook_auth
|
||||||
new_webhook = self.rachio.notification.postWebhook(
|
new_webhook = self.rachio.notification.add(
|
||||||
self.controller_id, auth, url, event_types
|
self.controller_id, auth, url, event_types
|
||||||
)
|
)
|
||||||
# Save ID for deletion at shutdown
|
# Save ID for deletion at shutdown
|
||||||
@ -154,7 +156,7 @@ class RachioIro:
|
|||||||
@property
|
@property
|
||||||
def current_schedule(self) -> str:
|
def current_schedule(self) -> str:
|
||||||
"""Return the schedule that the device is running right now."""
|
"""Return the schedule that the device is running right now."""
|
||||||
return self.rachio.device.getCurrentSchedule(self.controller_id)[1]
|
return self.rachio.device.current_schedule(self.controller_id)[1]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def init_data(self) -> dict:
|
def init_data(self) -> dict:
|
||||||
@ -188,5 +190,5 @@ class RachioIro:
|
|||||||
|
|
||||||
def stop_watering(self) -> None:
|
def stop_watering(self) -> None:
|
||||||
"""Stop watering all zones connected to this controller."""
|
"""Stop watering all zones connected to this controller."""
|
||||||
self.rachio.device.stopWater(self.controller_id)
|
self.rachio.device.stop_water(self.controller_id)
|
||||||
_LOGGER.info("Stopped watering of all zones on %s", str(self))
|
_LOGGER.info("Stopped watering of all zones on %s", str(self))
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "rachio",
|
"domain": "rachio",
|
||||||
"name": "Rachio",
|
"name": "Rachio",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/rachio",
|
"documentation": "https://www.home-assistant.io/integrations/rachio",
|
||||||
"requirements": ["rachiopy==0.1.4"],
|
"requirements": ["rachiopy==1.0.3"],
|
||||||
"dependencies": ["http"],
|
"dependencies": ["http"],
|
||||||
"after_dependencies": ["cloud"],
|
"after_dependencies": ["cloud"],
|
||||||
"codeowners": ["@bdraco"],
|
"codeowners": ["@bdraco"],
|
||||||
|
@ -179,11 +179,11 @@ class RachioStandbySwitch(RachioSwitch):
|
|||||||
|
|
||||||
def turn_on(self, **kwargs) -> None:
|
def turn_on(self, **kwargs) -> None:
|
||||||
"""Put the controller in standby mode."""
|
"""Put the controller in standby mode."""
|
||||||
self._controller.rachio.device.off(self._controller.controller_id)
|
self._controller.rachio.device.turn_off(self._controller.controller_id)
|
||||||
|
|
||||||
def turn_off(self, **kwargs) -> None:
|
def turn_off(self, **kwargs) -> None:
|
||||||
"""Resume controller functionality."""
|
"""Resume controller functionality."""
|
||||||
self._controller.rachio.device.on(self._controller.controller_id)
|
self._controller.rachio.device.turn_on(self._controller.controller_id)
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Subscribe to updates."""
|
"""Subscribe to updates."""
|
||||||
@ -250,12 +250,12 @@ class RachioRainDelay(RachioSwitch):
|
|||||||
|
|
||||||
def turn_on(self, **kwargs) -> None:
|
def turn_on(self, **kwargs) -> None:
|
||||||
"""Activate a 24 hour rain delay on the controller."""
|
"""Activate a 24 hour rain delay on the controller."""
|
||||||
self._controller.rachio.device.rainDelay(self._controller.controller_id, 86400)
|
self._controller.rachio.device.rain_delay(self._controller.controller_id, 86400)
|
||||||
_LOGGER.debug("Starting rain delay for 24 hours")
|
_LOGGER.debug("Starting rain delay for 24 hours")
|
||||||
|
|
||||||
def turn_off(self, **kwargs) -> None:
|
def turn_off(self, **kwargs) -> None:
|
||||||
"""Resume controller functionality."""
|
"""Resume controller functionality."""
|
||||||
self._controller.rachio.device.rainDelay(self._controller.controller_id, 0)
|
self._controller.rachio.device.rain_delay(self._controller.controller_id, 0)
|
||||||
_LOGGER.debug("Canceling rain delay")
|
_LOGGER.debug("Canceling rain delay")
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
@ -381,7 +381,7 @@ class RachioZone(RachioSwitch):
|
|||||||
def set_moisture_percent(self, percent) -> None:
|
def set_moisture_percent(self, percent) -> None:
|
||||||
"""Set the zone moisture percent."""
|
"""Set the zone moisture percent."""
|
||||||
_LOGGER.debug("Setting %s moisture to %s percent", self._zone_name, percent)
|
_LOGGER.debug("Setting %s moisture to %s percent", self._zone_name, percent)
|
||||||
self._controller.rachio.zone.setMoisturePercent(self._id, percent / 100)
|
self._controller.rachio.zone.set_moisture_percent(self._id, percent / 100)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_handle_update(self, *args, **kwargs) -> None:
|
def _async_handle_update(self, *args, **kwargs) -> None:
|
||||||
|
@ -1899,7 +1899,7 @@ qnapstats==0.3.0
|
|||||||
quantum-gateway==0.0.5
|
quantum-gateway==0.0.5
|
||||||
|
|
||||||
# homeassistant.components.rachio
|
# homeassistant.components.rachio
|
||||||
rachiopy==0.1.4
|
rachiopy==1.0.3
|
||||||
|
|
||||||
# homeassistant.components.radiotherm
|
# homeassistant.components.radiotherm
|
||||||
radiotherm==2.0.0
|
radiotherm==2.0.0
|
||||||
|
@ -901,7 +901,7 @@ pywilight==0.0.65
|
|||||||
pyzerproc==0.2.5
|
pyzerproc==0.2.5
|
||||||
|
|
||||||
# homeassistant.components.rachio
|
# homeassistant.components.rachio
|
||||||
rachiopy==0.1.4
|
rachiopy==1.0.3
|
||||||
|
|
||||||
# homeassistant.components.rainmachine
|
# homeassistant.components.rainmachine
|
||||||
regenmaschine==2.1.0
|
regenmaschine==2.1.0
|
||||||
|
@ -11,11 +11,11 @@ from tests.async_mock import MagicMock, patch
|
|||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
def _mock_rachio_return_value(get=None, getInfo=None):
|
def _mock_rachio_return_value(get=None, info=None):
|
||||||
rachio_mock = MagicMock()
|
rachio_mock = MagicMock()
|
||||||
person_mock = MagicMock()
|
person_mock = MagicMock()
|
||||||
type(person_mock).get = MagicMock(return_value=get)
|
type(person_mock).get = MagicMock(return_value=get)
|
||||||
type(person_mock).getInfo = MagicMock(return_value=getInfo)
|
type(person_mock).info = MagicMock(return_value=info)
|
||||||
type(rachio_mock).person = person_mock
|
type(rachio_mock).person = person_mock
|
||||||
return rachio_mock
|
return rachio_mock
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ async def test_form(hass):
|
|||||||
|
|
||||||
rachio_mock = _mock_rachio_return_value(
|
rachio_mock = _mock_rachio_return_value(
|
||||||
get=({"status": 200}, {"username": "myusername"}),
|
get=({"status": 200}, {"username": "myusername"}),
|
||||||
getInfo=({"status": 200}, {"id": "myid"}),
|
info=({"status": 200}, {"id": "myid"}),
|
||||||
)
|
)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
@ -71,7 +71,7 @@ async def test_form_invalid_auth(hass):
|
|||||||
|
|
||||||
rachio_mock = _mock_rachio_return_value(
|
rachio_mock = _mock_rachio_return_value(
|
||||||
get=({"status": 200}, {"username": "myusername"}),
|
get=({"status": 200}, {"username": "myusername"}),
|
||||||
getInfo=({"status": 412}, {"error": "auth fail"}),
|
info=({"status": 412}, {"error": "auth fail"}),
|
||||||
)
|
)
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.rachio.config_flow.Rachio", return_value=rachio_mock
|
"homeassistant.components.rachio.config_flow.Rachio", return_value=rachio_mock
|
||||||
@ -93,7 +93,7 @@ async def test_form_cannot_connect(hass):
|
|||||||
|
|
||||||
rachio_mock = _mock_rachio_return_value(
|
rachio_mock = _mock_rachio_return_value(
|
||||||
get=({"status": 599}, {"username": "myusername"}),
|
get=({"status": 599}, {"username": "myusername"}),
|
||||||
getInfo=({"status": 200}, {"id": "myid"}),
|
info=({"status": 200}, {"id": "myid"}),
|
||||||
)
|
)
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.rachio.config_flow.Rachio", return_value=rachio_mock
|
"homeassistant.components.rachio.config_flow.Rachio", return_value=rachio_mock
|
||||||
|
Loading…
x
Reference in New Issue
Block a user