Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Support for Traccar Client."""
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.config_entries import ConfigEntry
10 from homeassistant.const import ATTR_ID, CONF_WEBHOOK_ID, Platform
11 from homeassistant.core import HomeAssistant
12 from homeassistant.helpers import config_entry_flow
14 from homeassistant.helpers.dispatcher import async_dispatcher_send
15 
16 from .const import (
17  ATTR_ACCURACY,
18  ATTR_ALTITUDE,
19  ATTR_BATTERY,
20  ATTR_BEARING,
21  ATTR_LATITUDE,
22  ATTR_LONGITUDE,
23  ATTR_SPEED,
24  ATTR_TIMESTAMP,
25  DOMAIN,
26 )
27 
28 PLATFORMS = [Platform.DEVICE_TRACKER]
29 
30 
31 TRACKER_UPDATE = f"{DOMAIN}_tracker_update"
32 
33 
34 DEFAULT_ACCURACY = 200
35 DEFAULT_BATTERY = -1
36 
37 
38 def _id(value: str) -> str:
39  """Coerce id by removing '-'."""
40  return value.replace("-", "")
41 
42 
43 WEBHOOK_SCHEMA = vol.Schema(
44  {
45  vol.Required(ATTR_ID): vol.All(cv.string, _id),
46  vol.Required(ATTR_LATITUDE): cv.latitude,
47  vol.Required(ATTR_LONGITUDE): cv.longitude,
48  vol.Optional(ATTR_ACCURACY, default=DEFAULT_ACCURACY): vol.Coerce(float),
49  vol.Optional(ATTR_ALTITUDE): vol.Coerce(float),
50  vol.Optional(ATTR_BATTERY, default=DEFAULT_BATTERY): vol.Coerce(float),
51  vol.Optional(ATTR_BEARING): vol.Coerce(float),
52  vol.Optional(ATTR_SPEED): vol.Coerce(float),
53  vol.Optional(ATTR_TIMESTAMP): vol.Coerce(int),
54  },
55  extra=vol.REMOVE_EXTRA,
56 )
57 
58 
59 async def handle_webhook(
60  hass: HomeAssistant, webhook_id: str, request: web.Request
61 ) -> web.Response:
62  """Handle incoming webhook with Traccar Client request."""
63  try:
64  data = WEBHOOK_SCHEMA(dict(request.query))
65  except vol.MultipleInvalid as error:
66  return web.Response(
67  text=error.error_message, status=HTTPStatus.UNPROCESSABLE_ENTITY
68  )
69 
70  attrs = {
71  ATTR_ALTITUDE: data.get(ATTR_ALTITUDE),
72  ATTR_BEARING: data.get(ATTR_BEARING),
73  ATTR_SPEED: data.get(ATTR_SPEED),
74  }
75 
76  device = data[ATTR_ID]
77 
79  hass,
80  TRACKER_UPDATE,
81  device,
82  data[ATTR_LATITUDE],
83  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, "Traccar", entry.data[CONF_WEBHOOK_ID], handle_webhook
97  )
98 
99  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
100  return True
101 
102 
103 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
104  """Unload a config entry."""
105  webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
106  hass.data[DOMAIN]["unsub_device_tracker"].pop(entry.entry_id)()
107  return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
108 
109 
110 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:61
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:103
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