Bump rachiopy to 1.0.3 and update methods to handle changes (#41398)

This commit is contained in:
Brian Rogers 2020-10-10 20:44:49 -04:00 committed by GitHub
parent 80522f1bdc
commit 899431235b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 28 additions and 40 deletions

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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))

View File

@ -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"],

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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