Home Assistant Unofficial Reference 2024.12.1
storage.py
Go to the documentation of this file.
1 """API for persistent storage for the frontend."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable, Coroutine
6 from functools import wraps
7 from typing import Any
8 
9 import voluptuous as vol
10 
11 from homeassistant.components import websocket_api
12 from homeassistant.components.websocket_api import ActiveConnection
13 from homeassistant.core import HomeAssistant, callback
14 from homeassistant.helpers.storage import Store
15 
16 DATA_STORAGE = "frontend_storage"
17 STORAGE_VERSION_USER_DATA = 1
18 
19 
20 @callback
21 def _initialize_frontend_storage(hass: HomeAssistant) -> None:
22  """Set up frontend storage."""
23  if DATA_STORAGE in hass.data:
24  return
25  hass.data[DATA_STORAGE] = ({}, {})
26 
27 
28 async def async_setup_frontend_storage(hass: HomeAssistant) -> None:
29  """Set up frontend storage."""
31  websocket_api.async_register_command(hass, websocket_set_user_data)
32  websocket_api.async_register_command(hass, websocket_get_user_data)
33 
34 
35 async def async_user_store(
36  hass: HomeAssistant, user_id: str
37 ) -> tuple[Store, dict[str, Any]]:
38  """Access a user store."""
40  stores, data = hass.data[DATA_STORAGE]
41  if (store := stores.get(user_id)) is None:
42  store = stores[user_id] = Store(
43  hass,
44  STORAGE_VERSION_USER_DATA,
45  f"frontend.user_data_{user_id}",
46  )
47 
48  if user_id not in data:
49  data[user_id] = await store.async_load() or {}
50 
51  return store, data[user_id]
52 
53 
55  orig_func: Callable[
56  [HomeAssistant, ActiveConnection, dict[str, Any], Store, dict[str, Any]],
57  Coroutine[Any, Any, None],
58  ],
59 ) -> Callable[
60  [HomeAssistant, ActiveConnection, dict[str, Any]], Coroutine[Any, Any, None]
61 ]:
62  """Decorate function to provide data."""
63 
64  @wraps(orig_func)
65  async def with_store_func(
66  hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]
67  ) -> None:
68  """Provide user specific data and store to function."""
69  user_id = connection.user.id
70 
71  store, user_data = await async_user_store(hass, user_id)
72 
73  await orig_func(hass, connection, msg, store, user_data)
74 
75  return with_store_func
76 
77 
78 @websocket_api.websocket_command( { vol.Required("type"): "frontend/set_user_data",
79  vol.Required("key"): str,
80  vol.Required("value"): vol.Any(bool, str, int, float, dict, list, None),
81  }
82 )
83 @websocket_api.async_response
84 @with_store
85 async def websocket_set_user_data(
86  hass: HomeAssistant,
87  connection: ActiveConnection,
88  msg: dict[str, Any],
89  store: Store,
90  data: dict[str, Any],
91 ) -> None:
92  """Handle set global data command.
93 
94  Async friendly.
95  """
96  data[msg["key"]] = msg["value"]
97  await store.async_save(data)
98  connection.send_message(websocket_api.result_message(msg["id"]))
99 
100 
101 @websocket_api.websocket_command( {vol.Required("type"): "frontend/get_user_data", vol.Optional("key"): str}
102 )
103 @websocket_api.async_response
104 @with_store
105 async def websocket_get_user_data(
106  hass: HomeAssistant,
107  connection: ActiveConnection,
108  msg: dict[str, Any],
109  store: Store,
110  data: dict[str, Any],
111 ) -> None:
112  """Handle get global data command.
113 
114  Async friendly.
115  """
116  connection.send_message(
117  websocket_api.result_message(
118  msg["id"], {"value": data.get(msg["key"]) if "key" in msg else data}
119  )
120  )
121 
None websocket_set_user_data(HomeAssistant hass, ActiveConnection connection, dict[str, Any] msg, Store store, dict[str, Any] data)
Definition: storage.py:93
None websocket_get_user_data(HomeAssistant hass, ActiveConnection connection, dict[str, Any] msg, Store store, dict[str, Any] data)
Definition: storage.py:114
tuple[Store, dict[str, Any]] async_user_store(HomeAssistant hass, str user_id)
Definition: storage.py:37
None async_setup_frontend_storage(HomeAssistant hass)
Definition: storage.py:28
None _initialize_frontend_storage(HomeAssistant hass)
Definition: storage.py:21
Callable[[HomeAssistant, ActiveConnection, dict[str, Any]], Coroutine[Any, Any, None]] with_store(Callable[[HomeAssistant, ActiveConnection, dict[str, Any], Store, dict[str, Any]], Coroutine[Any, Any, None],] orig_func)
Definition: storage.py:61