diff --git a/homeassistant/components/rainmachine/__init__.py b/homeassistant/components/rainmachine/__init__.py index c8697adbcd4..98fbdbcf401 100644 --- a/homeassistant/components/rainmachine/__init__.py +++ b/homeassistant/components/rainmachine/__init__.py @@ -6,7 +6,6 @@ from functools import partial from regenmaschine import Client from regenmaschine.controller import Controller from regenmaschine.errors import RainMachineError -import voluptuous as vol from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( @@ -16,10 +15,9 @@ from homeassistant.const import ( CONF_PORT, CONF_SSL, ) -from homeassistant.core import HomeAssistant, ServiceCall, callback +from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import aiohttp_client, config_validation as cv -from homeassistant.helpers.service import verify_domain_control from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, DataUpdateCoordinator, @@ -35,15 +33,10 @@ from .const import ( DATA_RESTRICTIONS_CURRENT, DATA_RESTRICTIONS_UNIVERSAL, DATA_ZONES, - DEFAULT_ZONE_RUN, DOMAIN, LOGGER, ) -CONF_PROGRAM_ID = "program_id" -CONF_SECONDS = "seconds" -CONF_ZONE_ID = "zone_id" - DATA_LISTENER = "listener" DEFAULT_ATTRIBUTION = "Data provided by Green Electronics LLC" @@ -51,29 +44,6 @@ DEFAULT_ICON = "mdi:water" DEFAULT_SSL = True DEFAULT_UPDATE_INTERVAL = timedelta(seconds=15) -SERVICE_ALTER_PROGRAM = vol.Schema({vol.Required(CONF_PROGRAM_ID): cv.positive_int}) - -SERVICE_ALTER_ZONE = vol.Schema({vol.Required(CONF_ZONE_ID): cv.positive_int}) - -SERVICE_PAUSE_WATERING = vol.Schema({vol.Required(CONF_SECONDS): cv.positive_int}) - -SERVICE_START_PROGRAM_SCHEMA = vol.Schema( - {vol.Required(CONF_PROGRAM_ID): cv.positive_int} -) - -SERVICE_START_ZONE_SCHEMA = vol.Schema( - { - vol.Required(CONF_ZONE_ID): cv.positive_int, - vol.Optional(CONF_ZONE_RUN_TIME, default=DEFAULT_ZONE_RUN): cv.positive_int, - } -) - -SERVICE_STOP_PROGRAM_SCHEMA = vol.Schema( - {vol.Required(CONF_PROGRAM_ID): cv.positive_int} -) - -SERVICE_STOP_ZONE_SCHEMA = vol.Schema({vol.Required(CONF_ZONE_ID): cv.positive_int}) - CONFIG_SCHEMA = cv.deprecated(DOMAIN) PLATFORMS = ["binary_sensor", "sensor", "switch"] @@ -125,8 +95,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: if entry_updates: hass.config_entries.async_update_entry(entry, **entry_updates) - _verify_domain_control = verify_domain_control(hass, DOMAIN) - websession = aiohttp_client.async_get_clientsession(hass) client = Client(session=websession) @@ -192,92 +160,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass.config_entries.async_forward_entry_setup(entry, component) ) - @_verify_domain_control - async def disable_program(call: ServiceCall): - """Disable a program.""" - await controller.programs.disable(call.data[CONF_PROGRAM_ID]) - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def disable_zone(call: ServiceCall): - """Disable a zone.""" - await controller.zones.disable(call.data[CONF_ZONE_ID]) - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def enable_program(call: ServiceCall): - """Enable a program.""" - await controller.programs.enable(call.data[CONF_PROGRAM_ID]) - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def enable_zone(call: ServiceCall): - """Enable a zone.""" - await controller.zones.enable(call.data[CONF_ZONE_ID]) - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def pause_watering(call: ServiceCall): - """Pause watering for a set number of seconds.""" - await controller.watering.pause_all(call.data[CONF_SECONDS]) - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def start_program(call: ServiceCall): - """Start a particular program.""" - await controller.programs.start(call.data[CONF_PROGRAM_ID]) - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def start_zone(call: ServiceCall): - """Start a particular zone for a certain amount of time.""" - await controller.zones.start( - call.data[CONF_ZONE_ID], call.data[CONF_ZONE_RUN_TIME] - ) - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def stop_all(call: ServiceCall): - """Stop all watering.""" - await controller.watering.stop_all() - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def stop_program(call: ServiceCall): - """Stop a program.""" - await controller.programs.stop(call.data[CONF_PROGRAM_ID]) - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def stop_zone(call: ServiceCall): - """Stop a zone.""" - await controller.zones.stop(call.data[CONF_ZONE_ID]) - await async_update_programs_and_zones(hass, entry) - - @_verify_domain_control - async def unpause_watering(call: ServiceCall): - """Unpause watering.""" - await controller.watering.unpause_all() - await async_update_programs_and_zones(hass, entry) - - for service, method, schema in [ - ("disable_program", disable_program, SERVICE_ALTER_PROGRAM), - ("disable_zone", disable_zone, SERVICE_ALTER_ZONE), - ("enable_program", enable_program, SERVICE_ALTER_PROGRAM), - ("enable_zone", enable_zone, SERVICE_ALTER_ZONE), - ("pause_watering", pause_watering, SERVICE_PAUSE_WATERING), - ("start_program", start_program, SERVICE_START_PROGRAM_SCHEMA), - ("start_zone", start_zone, SERVICE_START_ZONE_SCHEMA), - ("stop_all", stop_all, {}), - ("stop_program", stop_program, SERVICE_STOP_PROGRAM_SCHEMA), - ("stop_zone", stop_zone, SERVICE_STOP_ZONE_SCHEMA), - ("unpause_watering", unpause_watering, {}), - ]: - hass.services.async_register(DOMAIN, service, method, schema=schema) - - hass.data[DOMAIN][DATA_LISTENER][entry.entry_id] = entry.add_update_listener( - async_reload_entry - ) + hass.data[DOMAIN][DATA_LISTENER] = entry.add_update_listener(async_reload_entry) return True diff --git a/homeassistant/components/rainmachine/services.yaml b/homeassistant/components/rainmachine/services.yaml index e66bd2a1d14..a73dc5c899d 100644 --- a/homeassistant/components/rainmachine/services.yaml +++ b/homeassistant/components/rainmachine/services.yaml @@ -2,42 +2,63 @@ disable_program: description: Disable a program. fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 program_id: description: The program to disable. example: 3 disable_zone: description: Disable a zone. fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 zone_id: description: The zone to disable. example: 3 enable_program: description: Enable a program. fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 program_id: description: The program to enable. example: 3 enable_zone: description: Enable a zone. fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 zone_id: description: The zone to enable. example: 3 pause_watering: description: Pause all watering for a number of seconds. fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 seconds: description: The number of seconds to pause. example: 30 start_program: description: Start a program. fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 program_id: description: The program to start. example: 3 start_zone: description: Start a zone for a set number of seconds. fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 zone_id: description: The zone to start. example: 3 @@ -46,17 +67,31 @@ start_zone: example: 120 stop_all: description: Stop all watering activities. + fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 stop_program: description: Stop a program. fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 program_id: description: The program to stop. example: 3 stop_zone: description: Stop a zone. fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 zone_id: description: The zone to stop. example: 3 unpause_watering: description: Unpause all watering. + fields: + entity_id: + description: An entity from the desired RainMachine controller + example: switch.zone_1 diff --git a/homeassistant/components/rainmachine/switch.py b/homeassistant/components/rainmachine/switch.py index 5c54000a15f..6741abbfc9f 100644 --- a/homeassistant/components/rainmachine/switch.py +++ b/homeassistant/components/rainmachine/switch.py @@ -4,11 +4,13 @@ from typing import Callable, Coroutine from regenmaschine.controller import Controller from regenmaschine.errors import RequestError +import voluptuous as vol from homeassistant.components.switch import SwitchEntity from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_ID from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers import config_validation as cv, entity_platform from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from . import RainMachineEntity, async_update_programs_and_zones @@ -18,6 +20,7 @@ from .const import ( DATA_COORDINATOR, DATA_PROGRAMS, DATA_ZONES, + DEFAULT_ZONE_RUN, DOMAIN, LOGGER, ) @@ -43,6 +46,10 @@ ATTR_TIME_REMAINING = "time_remaining" ATTR_VEGETATION_TYPE = "vegetation_type" ATTR_ZONES = "zones" +CONF_PROGRAM_ID = "program_id" +CONF_SECONDS = "seconds" +CONF_ZONE_ID = "zone_id" + DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] RUN_STATUS_MAP = {0: "Not Running", 1: "Running", 2: "Queued"} @@ -103,6 +110,47 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: Callable ) -> None: """Set up RainMachine switches based on a config entry.""" + platform = entity_platform.current_platform.get() + + alter_program_schema = {vol.Required(CONF_PROGRAM_ID): cv.positive_int} + alter_zone_schema = {vol.Required(CONF_ZONE_ID): cv.positive_int} + + for service_name, schema, method in [ + ("disable_program", alter_program_schema, "async_disable_program"), + ("disable_zone", alter_zone_schema, "async_disable_zone"), + ("enable_program", alter_program_schema, "async_enable_program"), + ("enable_zone", alter_zone_schema, "async_enable_zone"), + ( + "pause_watering", + {vol.Required(CONF_SECONDS): cv.positive_int}, + "async_pause_watering", + ), + ( + "start_program", + {vol.Required(CONF_PROGRAM_ID): cv.positive_int}, + "async_start_program", + ), + ( + "start_zone", + { + vol.Required(CONF_ZONE_ID): cv.positive_int, + vol.Optional( + CONF_ZONE_RUN_TIME, default=DEFAULT_ZONE_RUN + ): cv.positive_int, + }, + "async_start_zone", + ), + ("stop_all", {}, "async_stop_all"), + ( + "stop_program", + {vol.Required(CONF_PROGRAM_ID): cv.positive_int}, + "async_stop_program", + ), + ("stop_zone", {vol.Required(CONF_ZONE_ID): cv.positive_int}, "async_stop_zone"), + ("unpause_watering", {}, "async_unpause_watering"), + ]: + platform.async_register_entity_service(service_name, schema, method) + controller = hass.data[DOMAIN][DATA_CONTROLLER][entry.entry_id] programs_coordinator = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][ DATA_PROGRAMS @@ -193,6 +241,61 @@ class RainMachineSwitch(RainMachineEntity, SwitchEntity): async_update_programs_and_zones(self.hass, self._entry) ) + async def async_disable_program(self, *, program_id): + """Disable a program.""" + await self._controller.programs.disable(program_id) + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_disable_zone(self, *, zone_id): + """Disable a zone.""" + await self._controller.zones.disable(zone_id) + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_enable_program(self, *, program_id): + """Enable a program.""" + await self._controller.programs.enable(program_id) + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_enable_zone(self, *, zone_id): + """Enable a zone.""" + await self._controller.zones.enable(zone_id) + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_pause_watering(self, *, seconds): + """Pause watering for a set number of seconds.""" + await self._controller.watering.pause_all(seconds) + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_start_program(self, *, program_id): + """Start a particular program.""" + await self._controller.programs.start(program_id) + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_start_zone(self, *, zone_id, zone_run_time): + """Start a particular zone for a certain amount of time.""" + await self._controller.zones.start(zone_id, zone_run_time) + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_stop_all(self): + """Stop all watering.""" + await self._controller.watering.stop_all() + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_stop_program(self, *, program_id): + """Stop a program.""" + await self._controller.programs.stop(program_id) + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_stop_zone(self, *, zone_id): + """Stop a zone.""" + await self._controller.zones.stop(zone_id) + await async_update_programs_and_zones(self.hass, self._entry) + + async def async_unpause_watering(self): + """Unpause watering.""" + await self._controller.watering.unpause_all() + await async_update_programs_and_zones(self.hass, self._entry) + @callback def update_from_latest_data(self) -> None: """Update the state."""