-
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdata_source.py
More file actions
131 lines (105 loc) · 4.08 KB
/
Copy pathdata_source.py
File metadata and controls
131 lines (105 loc) · 4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import logging
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ServiceValidationError
from homeassistant.util.dt import (utcnow, now)
from homeassistant.const import (
STATE_UNAVAILABLE,
STATE_UNKNOWN,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.components.sensor import (
RestoreSensor,
SensorDeviceClass,
)
from homeassistant.helpers.entity import generate_entity_id
from ..utils.attributes import dict_to_typed_dict
from ..const import DOMAIN, EVENT_DATA_SOURCE, EVENT_UPDATE_DATA_SOURCE
from ..storage.data_source_data import async_save_cached_data_source_data
from ..utils.data_source_data import DataSourceItem, merge_data_source_data, validate_data_source_data
_LOGGER = logging.getLogger(__name__)
class TargetTimePeriodDataSource(RestoreSensor):
"""Sensor for displaying a target time period data source"""
_unrecorded_attributes = frozenset({ "data" })
def __init__(self, hass: HomeAssistant, source_id: str):
"""Init sensor."""
self._hass = hass
self._state = None
self._source_id = source_id
self._attributes = {
"data_source_id": source_id
}
self.entity_id = generate_entity_id("sensor.{}", self.unique_id, hass=hass)
@property
def unique_id(self):
"""The id of the sensor."""
return f"target_timeframes_{self._source_id}_data_source_last_updated"
@property
def name(self):
"""Name of the sensor."""
return f"Data source last updated ({self._source_id})"
@property
def icon(self):
"""Icon of the sensor."""
return "mdi:clock"
@property
def device_class(self):
"""The type of sensor"""
return SensorDeviceClass.TIMESTAMP
@property
def extra_state_attributes(self):
"""Attributes of the sensor."""
return self._attributes
@property
def native_value(self):
return self._state
@callback
async def _async_handle_event(self, event) -> None:
if event.data.get("data_source_id", '').lower() == self._source_id.lower():
await self.async_update_target_timeframe_data_source(event.data.get("data", []))
async def async_added_to_hass(self):
"""Call when entity about to be added to hass."""
# If not None, we got an initial value.
await super().async_added_to_hass()
state = await self.async_get_last_state()
last_sensor_state = await self.async_get_last_sensor_data()
if state is not None and last_sensor_state is not None and self._state is None:
self._state = None if state.state in (STATE_UNAVAILABLE, STATE_UNKNOWN) else last_sensor_state.native_value
self._attributes = dict_to_typed_dict(state.attributes)
_LOGGER.debug(f'Restored state: {self._state}')
self.async_on_remove(
self._hass.bus.async_listen(EVENT_UPDATE_DATA_SOURCE, self._async_handle_event)
)
@callback
async def async_update_target_timeframe_data_source(self, data, replace_all_existing_data = False):
"""Update target timeframe data source"""
result = validate_data_source_data(data, self._source_id)
if result.success == False:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="invalid_data_source_data",
translation_placeholders={
"error": result.error_message,
},
)
data_source_data = (
result.data
if replace_all_existing_data
else merge_data_source_data(
now(),
result.data,
list(map(lambda x: DataSourceItem.parse_obj(x), self._attributes["data"]))
if "data" in self._attributes
else None
)
)
await async_save_cached_data_source_data(self._hass, self._source_id, data_source_data)
data_dict = list(map(lambda x: x.dict(), data_source_data))
self._attributes["data"] = data_dict
self._state = utcnow()
self.async_write_ha_state()
self._hass.data.setdefault(DOMAIN, {})
self._hass.data[DOMAIN].setdefault(self._source_id, {})
self._hass.data[DOMAIN][self._source_id] = data_dict
self._hass.bus.async_fire(EVENT_DATA_SOURCE, {
"data_source_id": self._source_id
})