Move RainMachine services to entity services (#44139)

This commit is contained in:
Aaron Bach 2021-01-04 12:01:14 -07:00 committed by GitHub
parent cd756f20b1
commit 7657a5c901
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 140 additions and 119 deletions

View File

@ -6,7 +6,6 @@ from functools import partial
from regenmaschine import Client from regenmaschine import Client
from regenmaschine.controller import Controller from regenmaschine.controller import Controller
from regenmaschine.errors import RainMachineError from regenmaschine.errors import RainMachineError
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
@ -16,10 +15,9 @@ from homeassistant.const import (
CONF_PORT, CONF_PORT,
CONF_SSL, CONF_SSL,
) )
from homeassistant.core import HomeAssistant, ServiceCall, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import aiohttp_client, config_validation as cv from homeassistant.helpers import aiohttp_client, config_validation as cv
from homeassistant.helpers.service import verify_domain_control
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import (
CoordinatorEntity, CoordinatorEntity,
DataUpdateCoordinator, DataUpdateCoordinator,
@ -35,15 +33,10 @@ from .const import (
DATA_RESTRICTIONS_CURRENT, DATA_RESTRICTIONS_CURRENT,
DATA_RESTRICTIONS_UNIVERSAL, DATA_RESTRICTIONS_UNIVERSAL,
DATA_ZONES, DATA_ZONES,
DEFAULT_ZONE_RUN,
DOMAIN, DOMAIN,
LOGGER, LOGGER,
) )
CONF_PROGRAM_ID = "program_id"
CONF_SECONDS = "seconds"
CONF_ZONE_ID = "zone_id"
DATA_LISTENER = "listener" DATA_LISTENER = "listener"
DEFAULT_ATTRIBUTION = "Data provided by Green Electronics LLC" DEFAULT_ATTRIBUTION = "Data provided by Green Electronics LLC"
@ -51,29 +44,6 @@ DEFAULT_ICON = "mdi:water"
DEFAULT_SSL = True DEFAULT_SSL = True
DEFAULT_UPDATE_INTERVAL = timedelta(seconds=15) 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) CONFIG_SCHEMA = cv.deprecated(DOMAIN)
PLATFORMS = ["binary_sensor", "sensor", "switch"] PLATFORMS = ["binary_sensor", "sensor", "switch"]
@ -125,8 +95,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if entry_updates: if entry_updates:
hass.config_entries.async_update_entry(entry, **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) websession = aiohttp_client.async_get_clientsession(hass)
client = Client(session=websession) 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) hass.config_entries.async_forward_entry_setup(entry, component)
) )
@_verify_domain_control hass.data[DOMAIN][DATA_LISTENER] = entry.add_update_listener(async_reload_entry)
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
)
return True return True

View File

@ -2,42 +2,63 @@
disable_program: disable_program:
description: Disable a program. description: Disable a program.
fields: fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
program_id: program_id:
description: The program to disable. description: The program to disable.
example: 3 example: 3
disable_zone: disable_zone:
description: Disable a zone. description: Disable a zone.
fields: fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
zone_id: zone_id:
description: The zone to disable. description: The zone to disable.
example: 3 example: 3
enable_program: enable_program:
description: Enable a program. description: Enable a program.
fields: fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
program_id: program_id:
description: The program to enable. description: The program to enable.
example: 3 example: 3
enable_zone: enable_zone:
description: Enable a zone. description: Enable a zone.
fields: fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
zone_id: zone_id:
description: The zone to enable. description: The zone to enable.
example: 3 example: 3
pause_watering: pause_watering:
description: Pause all watering for a number of seconds. description: Pause all watering for a number of seconds.
fields: fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
seconds: seconds:
description: The number of seconds to pause. description: The number of seconds to pause.
example: 30 example: 30
start_program: start_program:
description: Start a program. description: Start a program.
fields: fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
program_id: program_id:
description: The program to start. description: The program to start.
example: 3 example: 3
start_zone: start_zone:
description: Start a zone for a set number of seconds. description: Start a zone for a set number of seconds.
fields: fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
zone_id: zone_id:
description: The zone to start. description: The zone to start.
example: 3 example: 3
@ -46,17 +67,31 @@ start_zone:
example: 120 example: 120
stop_all: stop_all:
description: Stop all watering activities. description: Stop all watering activities.
fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
stop_program: stop_program:
description: Stop a program. description: Stop a program.
fields: fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
program_id: program_id:
description: The program to stop. description: The program to stop.
example: 3 example: 3
stop_zone: stop_zone:
description: Stop a zone. description: Stop a zone.
fields: fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1
zone_id: zone_id:
description: The zone to stop. description: The zone to stop.
example: 3 example: 3
unpause_watering: unpause_watering:
description: Unpause all watering. description: Unpause all watering.
fields:
entity_id:
description: An entity from the desired RainMachine controller
example: switch.zone_1

View File

@ -4,11 +4,13 @@ from typing import Callable, Coroutine
from regenmaschine.controller import Controller from regenmaschine.controller import Controller
from regenmaschine.errors import RequestError from regenmaschine.errors import RequestError
import voluptuous as vol
from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ID from homeassistant.const import ATTR_ID
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from . import RainMachineEntity, async_update_programs_and_zones from . import RainMachineEntity, async_update_programs_and_zones
@ -18,6 +20,7 @@ from .const import (
DATA_COORDINATOR, DATA_COORDINATOR,
DATA_PROGRAMS, DATA_PROGRAMS,
DATA_ZONES, DATA_ZONES,
DEFAULT_ZONE_RUN,
DOMAIN, DOMAIN,
LOGGER, LOGGER,
) )
@ -43,6 +46,10 @@ ATTR_TIME_REMAINING = "time_remaining"
ATTR_VEGETATION_TYPE = "vegetation_type" ATTR_VEGETATION_TYPE = "vegetation_type"
ATTR_ZONES = "zones" ATTR_ZONES = "zones"
CONF_PROGRAM_ID = "program_id"
CONF_SECONDS = "seconds"
CONF_ZONE_ID = "zone_id"
DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
RUN_STATUS_MAP = {0: "Not Running", 1: "Running", 2: "Queued"} 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 hass: HomeAssistant, entry: ConfigEntry, async_add_entities: Callable
) -> None: ) -> None:
"""Set up RainMachine switches based on a config entry.""" """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] controller = hass.data[DOMAIN][DATA_CONTROLLER][entry.entry_id]
programs_coordinator = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][ programs_coordinator = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][
DATA_PROGRAMS DATA_PROGRAMS
@ -193,6 +241,61 @@ class RainMachineSwitch(RainMachineEntity, SwitchEntity):
async_update_programs_and_zones(self.hass, self._entry) 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 @callback
def update_from_latest_data(self) -> None: def update_from_latest_data(self) -> None:
"""Update the state.""" """Update the state."""