core/homeassistant/components/rachio/webhooks.py

133 lines
4.2 KiB
Python

"""Webhooks used by rachio."""
from aiohttp import web
from homeassistant.const import URL_API
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_send
from .const import (
CONF_CLOUDHOOK_URL,
CONF_WEBHOOK_ID,
DOMAIN,
KEY_EXTERNAL_ID,
KEY_TYPE,
SIGNAL_RACHIO_CONTROLLER_UPDATE,
SIGNAL_RACHIO_RAIN_DELAY_UPDATE,
SIGNAL_RACHIO_RAIN_SENSOR_UPDATE,
SIGNAL_RACHIO_SCHEDULE_UPDATE,
SIGNAL_RACHIO_ZONE_UPDATE,
)
# Device webhook values
TYPE_CONTROLLER_STATUS = "DEVICE_STATUS"
SUBTYPE_OFFLINE = "OFFLINE"
SUBTYPE_ONLINE = "ONLINE"
SUBTYPE_OFFLINE_NOTIFICATION = "OFFLINE_NOTIFICATION"
SUBTYPE_COLD_REBOOT = "COLD_REBOOT"
SUBTYPE_SLEEP_MODE_ON = "SLEEP_MODE_ON"
SUBTYPE_SLEEP_MODE_OFF = "SLEEP_MODE_OFF"
SUBTYPE_BROWNOUT_VALVE = "BROWNOUT_VALVE"
# Rain delay values
TYPE_RAIN_DELAY_STATUS = "RAIN_DELAY"
SUBTYPE_RAIN_DELAY_ON = "RAIN_DELAY_ON"
SUBTYPE_RAIN_DELAY_OFF = "RAIN_DELAY_OFF"
# Rain sensor values
TYPE_RAIN_SENSOR_STATUS = "RAIN_SENSOR_DETECTION"
SUBTYPE_RAIN_SENSOR_DETECTION_ON = "RAIN_SENSOR_DETECTION_ON"
SUBTYPE_RAIN_SENSOR_DETECTION_OFF = "RAIN_SENSOR_DETECTION_OFF"
# Schedule webhook values
TYPE_SCHEDULE_STATUS = "SCHEDULE_STATUS"
SUBTYPE_SCHEDULE_STARTED = "SCHEDULE_STARTED"
SUBTYPE_SCHEDULE_STOPPED = "SCHEDULE_STOPPED"
SUBTYPE_SCHEDULE_COMPLETED = "SCHEDULE_COMPLETED"
SUBTYPE_WEATHER_NO_SKIP = "WEATHER_INTELLIGENCE_NO_SKIP"
SUBTYPE_WEATHER_SKIP = "WEATHER_INTELLIGENCE_SKIP"
SUBTYPE_WEATHER_CLIMATE_SKIP = "WEATHER_INTELLIGENCE_CLIMATE_SKIP"
SUBTYPE_WEATHER_FREEZE = "WEATHER_INTELLIGENCE_FREEZE"
# Zone webhook values
TYPE_ZONE_STATUS = "ZONE_STATUS"
SUBTYPE_ZONE_STARTED = "ZONE_STARTED"
SUBTYPE_ZONE_STOPPED = "ZONE_STOPPED"
SUBTYPE_ZONE_COMPLETED = "ZONE_COMPLETED"
SUBTYPE_ZONE_CYCLING = "ZONE_CYCLING"
SUBTYPE_ZONE_CYCLING_COMPLETED = "ZONE_CYCLING_COMPLETED"
SUBTYPE_ZONE_PAUSED = "ZONE_PAUSED"
# Webhook callbacks
LISTEN_EVENT_TYPES = [
"DEVICE_STATUS_EVENT",
"ZONE_STATUS_EVENT",
"RAIN_DELAY_EVENT",
"RAIN_SENSOR_DETECTION_EVENT",
"SCHEDULE_STATUS_EVENT",
]
WEBHOOK_CONST_ID = "homeassistant.rachio:"
WEBHOOK_PATH = URL_API + DOMAIN
SIGNAL_MAP = {
TYPE_CONTROLLER_STATUS: SIGNAL_RACHIO_CONTROLLER_UPDATE,
TYPE_RAIN_DELAY_STATUS: SIGNAL_RACHIO_RAIN_DELAY_UPDATE,
TYPE_RAIN_SENSOR_STATUS: SIGNAL_RACHIO_RAIN_SENSOR_UPDATE,
TYPE_SCHEDULE_STATUS: SIGNAL_RACHIO_SCHEDULE_UPDATE,
TYPE_ZONE_STATUS: SIGNAL_RACHIO_ZONE_UPDATE,
}
@callback
def async_register_webhook(hass, webhook_id, entry_id):
"""Register a webhook."""
async def _async_handle_rachio_webhook(hass, webhook_id, request):
"""Handle webhook calls from the server."""
data = await request.json()
try:
auth = data.get(KEY_EXTERNAL_ID, "").split(":")[1]
assert auth == hass.data[DOMAIN][entry_id].rachio.webhook_auth
except (AssertionError, IndexError):
return web.Response(status=web.HTTPForbidden.status_code)
update_type = data[KEY_TYPE]
if update_type in SIGNAL_MAP:
async_dispatcher_send(hass, SIGNAL_MAP[update_type], data)
return web.Response(status=web.HTTPNoContent.status_code)
hass.components.webhook.async_register(
DOMAIN, "Rachio", webhook_id, _async_handle_rachio_webhook
)
async def async_get_or_create_registered_webhook_id_and_url(hass, entry):
"""Generate webhook ID."""
config = entry.data.copy()
updated_config = False
webhook_url = None
if not (webhook_id := config.get(CONF_WEBHOOK_ID)):
webhook_id = hass.components.webhook.async_generate_id()
config[CONF_WEBHOOK_ID] = webhook_id
updated_config = True
if hass.components.cloud.async_active_subscription():
if not (cloudhook_url := config.get(CONF_CLOUDHOOK_URL)):
cloudhook_url = await hass.components.cloud.async_create_cloudhook(
webhook_id
)
config[CONF_CLOUDHOOK_URL] = cloudhook_url
updated_config = True
webhook_url = cloudhook_url
if not webhook_url:
webhook_url = hass.components.webhook.async_generate_url(webhook_id)
if updated_config:
hass.config_entries.async_update_entry(entry, data=config)
return webhook_id, webhook_url