1 """Support for the Abode Security System."""
3 from __future__
import annotations
5 from dataclasses
import dataclass, field
6 from functools
import partial
7 from pathlib
import Path
9 from jaraco.abode.client
import Client
as Abode
10 import jaraco.abode.config
11 from jaraco.abode.exceptions
import (
12 AuthenticationException
as AbodeAuthenticationException,
13 Exception
as AbodeException,
15 from jaraco.abode.helpers.timeline
import Groups
as GROUPS
16 from requests.exceptions
import ConnectTimeout, HTTPError
17 import voluptuous
as vol
27 EVENT_HOMEASSISTANT_STOP,
36 from .const
import CONF_POLLING, DOMAIN, LOGGER
38 SERVICE_SETTINGS =
"change_setting"
39 SERVICE_CAPTURE_IMAGE =
"capture_image"
40 SERVICE_TRIGGER_AUTOMATION =
"trigger_automation"
42 ATTR_DEVICE_NAME =
"device_name"
43 ATTR_DEVICE_TYPE =
"device_type"
44 ATTR_EVENT_CODE =
"event_code"
45 ATTR_EVENT_NAME =
"event_name"
46 ATTR_EVENT_TYPE =
"event_type"
47 ATTR_EVENT_UTC =
"event_utc"
48 ATTR_SETTING =
"setting"
49 ATTR_USER_NAME =
"user_name"
50 ATTR_APP_TYPE =
"app_type"
51 ATTR_EVENT_BY =
"event_by"
54 CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=
False)
56 CHANGE_SETTING_SCHEMA = vol.Schema(
57 {vol.Required(ATTR_SETTING): cv.string, vol.Required(ATTR_VALUE): cv.string}
60 CAPTURE_IMAGE_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
62 AUTOMATION_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
65 Platform.ALARM_CONTROL_PANEL,
66 Platform.BINARY_SENSOR,
78 """Abode System class."""
82 entity_ids: set[str |
None] = field(default_factory=set)
83 logout_listener: CALLBACK_TYPE |
None =
None
86 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
87 """Set up the Abode component."""
93 """Set up Abode integration from a config entry."""
94 username = entry.data[CONF_USERNAME]
95 password = entry.data[CONF_PASSWORD]
96 polling = entry.data[CONF_POLLING]
99 jaraco.abode.config.paths.override(user_data=Path(hass.config.path(
"Abode")))
102 if entry.unique_id
is None:
103 hass.config_entries.async_update_entry(
104 entry, unique_id=entry.data[CONF_USERNAME]
108 abode = await hass.async_add_executor_job(
109 Abode, username, password,
True,
True,
True
112 except AbodeAuthenticationException
as ex:
115 except (AbodeException, ConnectTimeout, HTTPError)
as ex:
120 await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
123 await hass.async_add_executor_job(setup_abode_events, hass)
129 """Unload a config entry."""
130 unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
132 await hass.async_add_executor_job(hass.data[DOMAIN].abode.events.stop)
133 await hass.async_add_executor_job(hass.data[DOMAIN].abode.logout)
135 hass.data[DOMAIN].logout_listener()
136 hass.data.pop(DOMAIN)
142 """Home Assistant services."""
144 def change_setting(call: ServiceCall) ->
None:
145 """Change an Abode system setting."""
146 setting = call.data[ATTR_SETTING]
147 value = call.data[ATTR_VALUE]
150 hass.data[DOMAIN].abode.set_setting(setting, value)
151 except AbodeException
as ex:
154 def capture_image(call: ServiceCall) ->
None:
155 """Capture a new image."""
156 entity_ids = call.data[ATTR_ENTITY_ID]
160 for entity_id
in hass.data[DOMAIN].entity_ids
161 if entity_id
in entity_ids
164 for entity_id
in target_entities:
165 signal = f
"abode_camera_capture_{entity_id}"
168 def trigger_automation(call: ServiceCall) ->
None:
169 """Trigger an Abode automation."""
170 entity_ids = call.data[ATTR_ENTITY_ID]
174 for entity_id
in hass.data[DOMAIN].entity_ids
175 if entity_id
in entity_ids
178 for entity_id
in target_entities:
179 signal = f
"abode_trigger_automation_{entity_id}"
182 hass.services.async_register(
183 DOMAIN, SERVICE_SETTINGS, change_setting, schema=CHANGE_SETTING_SCHEMA
186 hass.services.async_register(
187 DOMAIN, SERVICE_CAPTURE_IMAGE, capture_image, schema=CAPTURE_IMAGE_SCHEMA
190 hass.services.async_register(
191 DOMAIN, SERVICE_TRIGGER_AUTOMATION, trigger_automation, schema=AUTOMATION_SCHEMA
196 """Home Assistant start and stop callbacks."""
198 def logout(event: Event) ->
None:
199 """Logout of Abode."""
200 if not hass.data[DOMAIN].polling:
201 hass.data[DOMAIN].abode.events.stop()
203 hass.data[DOMAIN].abode.logout()
204 LOGGER.info(
"Logged out of Abode")
206 if not hass.data[DOMAIN].polling:
207 await hass.async_add_executor_job(hass.data[DOMAIN].abode.events.start)
209 hass.data[DOMAIN].logout_listener = hass.bus.async_listen_once(
210 EVENT_HOMEASSISTANT_STOP, logout
215 """Event callbacks."""
217 def event_callback(event: str, event_json: dict[str, str]) ->
None:
218 """Handle an event callback from Abode."""
220 ATTR_DEVICE_ID: event_json.get(ATTR_DEVICE_ID,
""),
221 ATTR_DEVICE_NAME: event_json.get(ATTR_DEVICE_NAME,
""),
222 ATTR_DEVICE_TYPE: event_json.get(ATTR_DEVICE_TYPE,
""),
223 ATTR_EVENT_CODE: event_json.get(ATTR_EVENT_CODE,
""),
224 ATTR_EVENT_NAME: event_json.get(ATTR_EVENT_NAME,
""),
225 ATTR_EVENT_TYPE: event_json.get(ATTR_EVENT_TYPE,
""),
226 ATTR_EVENT_UTC: event_json.get(ATTR_EVENT_UTC,
""),
227 ATTR_USER_NAME: event_json.get(ATTR_USER_NAME,
""),
228 ATTR_APP_TYPE: event_json.get(ATTR_APP_TYPE,
""),
229 ATTR_EVENT_BY: event_json.get(ATTR_EVENT_BY,
""),
230 ATTR_DATE: event_json.get(ATTR_DATE,
""),
231 ATTR_TIME: event_json.get(ATTR_TIME,
""),
234 hass.bus.fire(event, data)
240 GROUPS.PANEL_RESTORE,
251 hass.data[DOMAIN].abode.events.add_event_callback(
252 event, partial(event_callback, event)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup(HomeAssistant hass, ConfigType config)
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
None setup_abode_events(HomeAssistant hass)
None setup_hass_events(HomeAssistant hass)
None setup_hass_services(HomeAssistant hass)
None dispatcher_send(HomeAssistant hass, str signal, *Any args)