From 7a054719129bcc8f0fa3dc9861f2b6f56a3ee981 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Tue, 1 May 2018 13:36:43 -0600 Subject: [PATCH] Converts RainMachine to hub model (part 2) (#14225) * Converts RainMachine to hub model (part 2) * Small style adjustments for consistency * Moving MAC calculation to one-time call in component * Removing unneeded attribute * Bumping Travis * Lint --- homeassistant/components/rainmachine.py | 26 ++++++++-- .../components/switch/rainmachine.py | 47 ++++++++----------- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/homeassistant/components/rainmachine.py b/homeassistant/components/rainmachine.py index 4c8b8a1114f..99cec53c2ed 100644 --- a/homeassistant/components/rainmachine.py +++ b/homeassistant/components/rainmachine.py @@ -8,11 +8,10 @@ import logging from datetime import timedelta import voluptuous as vol -from requests.exceptions import ConnectTimeout -from homeassistant.helpers import config_validation as cv +from homeassistant.helpers import config_validation as cv, discovery from homeassistant.const import ( - CONF_IP_ADDRESS, CONF_PASSWORD, CONF_PORT, CONF_SSL) + CONF_IP_ADDRESS, CONF_PASSWORD, CONF_PORT, CONF_SSL, CONF_SWITCHES) REQUIREMENTS = ['regenmaschine==0.4.1'] @@ -24,6 +23,8 @@ DOMAIN = 'rainmachine' NOTIFICATION_ID = 'rainmachine_notification' NOTIFICATION_TITLE = 'RainMachine Component Setup' +CONF_ZONE_RUN_TIME = 'zone_run_time' + DEFAULT_ATTRIBUTION = 'Data provided by Green Electronics LLC' DEFAULT_PORT = 8080 DEFAULT_SSL = True @@ -31,6 +32,11 @@ DEFAULT_SSL = True MIN_SCAN_TIME = timedelta(seconds=1) MIN_SCAN_TIME_FORCED = timedelta(milliseconds=100) +SWITCH_SCHEMA = vol.Schema({ + vol.Optional(CONF_ZONE_RUN_TIME): + cv.positive_int +}) + CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema({ @@ -38,6 +44,7 @@ CONFIG_SCHEMA = vol.Schema( vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean, + vol.Optional(CONF_SWITCHES): SWITCH_SCHEMA, }) }, extra=vol.ALLOW_EXTRA) @@ -47,6 +54,7 @@ def setup(hass, config): """Set up the RainMachine component.""" from regenmaschine import Authenticator, Client from regenmaschine.exceptions import HTTPError + from requests.exceptions import ConnectTimeout conf = config[DOMAIN] ip_address = conf[CONF_IP_ADDRESS] @@ -54,11 +62,14 @@ def setup(hass, config): port = conf[CONF_PORT] ssl = conf[CONF_SSL] + _LOGGER.debug('Setting up RainMachine client') + try: auth = Authenticator.create_local( ip_address, password, port=port, https=ssl) client = Client(auth) - hass.data[DATA_RAINMACHINE] = client + mac = client.provision.wifi()['macAddress'] + hass.data[DATA_RAINMACHINE] = (client, mac) except (HTTPError, ConnectTimeout, UnboundLocalError) as exc_info: _LOGGER.error('An error occurred: %s', str(exc_info)) hass.components.persistent_notification.create( @@ -68,4 +79,11 @@ def setup(hass, config): title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID) return False + + _LOGGER.debug('Setting up switch platform') + switch_config = conf.get(CONF_SWITCHES, {}) + discovery.load_platform(hass, 'switch', DOMAIN, switch_config, config) + + _LOGGER.debug('Setup complete') + return True diff --git a/homeassistant/components/switch/rainmachine.py b/homeassistant/components/switch/rainmachine.py index cdada7ce274..8306b323330 100644 --- a/homeassistant/components/switch/rainmachine.py +++ b/homeassistant/components/switch/rainmachine.py @@ -2,40 +2,33 @@ from logging import getLogger -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv from homeassistant.components.rainmachine import ( - DATA_RAINMACHINE, DEFAULT_ATTRIBUTION, MIN_SCAN_TIME, MIN_SCAN_TIME_FORCED) -from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchDevice -from homeassistant.const import ATTR_ATTRIBUTION, ATTR_DEVICE_CLASS + CONF_ZONE_RUN_TIME, DATA_RAINMACHINE, DEFAULT_ATTRIBUTION, MIN_SCAN_TIME, + MIN_SCAN_TIME_FORCED) +from homeassistant.components.switch import SwitchDevice +from homeassistant.const import ATTR_ATTRIBUTION from homeassistant.util import Throttle -_LOGGER = getLogger(__name__) DEPENDENCIES = ['rainmachine'] +_LOGGER = getLogger(__name__) + ATTR_CYCLES = 'cycles' ATTR_TOTAL_DURATION = 'total_duration' -CONF_ZONE_RUN_TIME = 'zone_run_time' - -DEFAULT_ZONE_RUN_SECONDS = 60 * 10 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_ZONE_RUN_TIME, default=DEFAULT_ZONE_RUN_SECONDS): - cv.positive_int -}) +DEFAULT_ZONE_RUN = 60 * 10 def setup_platform(hass, config, add_devices, discovery_info=None): """Set this component up under its platform.""" - client = hass.data.get(DATA_RAINMACHINE) - device_name = client.provision.device_name()['name'] - device_mac = client.provision.wifi()['macAddress'] + if discovery_info is None: + return - _LOGGER.debug('Config received: %s', config) + _LOGGER.debug('Config received: %s', discovery_info) - zone_run_time = config[CONF_ZONE_RUN_TIME] + zone_run_time = discovery_info.get(CONF_ZONE_RUN_TIME, DEFAULT_ZONE_RUN) + + client, device_mac = hass.data.get(DATA_RAINMACHINE) entities = [] for program in client.programs.all().get('programs', {}): @@ -44,7 +37,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.debug('Adding program: %s', program) entities.append( - RainMachineProgram(client, device_name, device_mac, program)) + RainMachineProgram(client, device_mac, program)) for zone in client.zones.all().get('zones', {}): if not zone.get('active'): @@ -52,7 +45,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.debug('Adding zone: %s', zone) entities.append( - RainMachineZone(client, device_name, device_mac, zone, + RainMachineZone(client, device_mac, zone, zone_run_time)) add_devices(entities, True) @@ -61,18 +54,16 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class RainMachineEntity(SwitchDevice): """A class to represent a generic RainMachine entity.""" - def __init__(self, client, device_name, device_mac, entity_json): + def __init__(self, client, device_mac, entity_json): """Initialize a generic RainMachine entity.""" self._api_type = 'remote' if client.auth.using_remote_api else 'local' self._client = client self._entity_json = entity_json self.device_mac = device_mac - self.device_name = device_name self._attrs = { - ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION, - ATTR_DEVICE_CLASS: self.device_name + ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION } @property @@ -156,10 +147,10 @@ class RainMachineProgram(RainMachineEntity): class RainMachineZone(RainMachineEntity): """A RainMachine zone.""" - def __init__(self, client, device_name, device_mac, zone_json, + def __init__(self, client, device_mac, zone_json, zone_run_time): """Initialize a RainMachine zone.""" - super().__init__(client, device_name, device_mac, zone_json) + super().__init__(client, device_mac, zone_json) self._run_time = zone_run_time self._attrs.update({ ATTR_CYCLES: self._entity_json.get('noOfCycles'),