Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Support for GPSLogger."""
2 
3 from http import HTTPStatus
4 
5 from aiohttp import web
6 import voluptuous as vol
7 
8 from homeassistant.components import webhook
9 from homeassistant.components.device_tracker import ATTR_BATTERY
10 from homeassistant.config_entries import ConfigEntry
11 from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE, CONF_WEBHOOK_ID, Platform
12 from homeassistant.core import HomeAssistant
13 from homeassistant.helpers import config_entry_flow
15 from homeassistant.helpers.dispatcher import async_dispatcher_send
16 
17 from .const import (
18  ATTR_ACCURACY,
19  ATTR_ACTIVITY,
20  ATTR_ALTITUDE,
21  ATTR_DEVICE,
22  ATTR_DIRECTION,
23  ATTR_PROVIDER,
24  ATTR_SPEED,
25  DOMAIN,
26 )
27 
28 PLATFORMS = [Platform.DEVICE_TRACKER]
29 
30 TRACKER_UPDATE = f"{DOMAIN}_tracker_update"
31 
32 
33 DEFAULT_ACCURACY = 200
34 DEFAULT_BATTERY = -1
35 
36 
37 def _id(value: str) -> str:
38  """Coerce id by removing '-'."""
39  return value.replace("-", "")
40 
41 
42 WEBHOOK_SCHEMA = vol.Schema(
43  {
44  vol.Required(ATTR_DEVICE): _id,
45  vol.Required(ATTR_LATITUDE): cv.latitude,
46  vol.Required(ATTR_LONGITUDE): cv.longitude,
47  vol.Optional(ATTR_ACCURACY, default=DEFAULT_ACCURACY): vol.Coerce(float),
48  vol.Optional(ATTR_ACTIVITY): cv.string,
49  vol.Optional(ATTR_ALTITUDE): vol.Coerce(float),
50  vol.Optional(ATTR_BATTERY, default=DEFAULT_BATTERY): vol.Coerce(float),
51  vol.Optional(ATTR_DIRECTION): vol.Coerce(float),
52  vol.Optional(ATTR_PROVIDER): cv.string,
53  vol.Optional(ATTR_SPEED): vol.Coerce(float),
54  }
55 )
56 
57 
58 async def handle_webhook(
59  hass: HomeAssistant, webhook_id: str, request: web.Request
60 ) -> web.Response:
61  """Handle incoming webhook with GPSLogger request."""
62  try:
63  data = WEBHOOK_SCHEMA(dict(await request.post()))
64  except vol.MultipleInvalid as error:
65  return web.Response(
66  text=error.error_message, status=HTTPStatus.UNPROCESSABLE_ENTITY
67  )
68 
69  attrs = {
70  ATTR_SPEED: data.get(ATTR_SPEED),
71  ATTR_DIRECTION: data.get(ATTR_DIRECTION),
72  ATTR_ALTITUDE: data.get(ATTR_ALTITUDE),
73  ATTR_PROVIDER: data.get(ATTR_PROVIDER),
74  ATTR_ACTIVITY: data.get(ATTR_ACTIVITY),
75  }
76 
77  device = data[ATTR_DEVICE]
78 
80  hass,
81  TRACKER_UPDATE,
82  device,
83  (data[ATTR_LATITUDE], data[ATTR_LONGITUDE]),
84  data[ATTR_BATTERY],
85  data[ATTR_ACCURACY],
86  attrs,
87  )
88 
89  return web.Response(text=f"Setting location for {device}")
90 
91 
92 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
93  """Configure based on config entry."""
94  hass.data.setdefault(DOMAIN, {"devices": set(), "unsub_device_tracker": {}})
95  webhook.async_register(
96  hass, DOMAIN, "GPSLogger", entry.data[CONF_WEBHOOK_ID], handle_webhook
97  )
98 
99  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
100 
101  return True
102 
103 
104 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
105  """Unload a config entry."""
106  webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
107  hass.data[DOMAIN]["unsub_device_tracker"].pop(entry.entry_id)()
108  return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
109 
110 
111 async_remove_entry = config_entry_flow.webhook_async_remove_entry
web.Response handle_webhook(HomeAssistant hass, str webhook_id, web.Request request)
Definition: __init__.py:60
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:104
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:92
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)
Definition: dispatcher.py:193