Skip to content

Commit

Permalink
Add async access to database (fix #127)
Browse files Browse the repository at this point in the history
  • Loading branch information
Limych committed May 22, 2022
1 parent 9b98257 commit 5e3f1ad
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 21 deletions.
2 changes: 1 addition & 1 deletion custom_components/average/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# Base component constants
NAME: Final = "Average Sensor"
DOMAIN: Final = "average"
VERSION: Final = "2.2.2"
VERSION: Final = "2.2.3-alpha"
ISSUE_URL: Final = "https://github.com/Limych/ha-average/issues"

STARTUP_MESSAGE: Final = f"""
Expand Down
2 changes: 1 addition & 1 deletion custom_components/average/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"domain": "average",
"name": "Average Sensor",
"version": "2.2.2",
"version": "2.2.3-alpha",
"documentation": "https://github.com/Limych/ha-average",
"issue_tracker": "https://github.com/Limych/ha-average/issues",
"dependencies": [],
Expand Down
38 changes: 22 additions & 16 deletions custom_components/average/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@

try: # pragma: no cover
# HA version >=2021.6
from homeassistant.components.recorder import history
from homeassistant.components.recorder import get_instance, history
from homeassistant.components.recorder.models import LazyState
except ImportError: # pragma: no cover
# HA version <=2021.5
Expand Down Expand Up @@ -217,24 +217,26 @@ async def async_added_to_hass(self) -> None:

# pylint: disable=unused-argument
@callback
def sensor_state_listener(entity, old_state, new_state):
async def async_sensor_state_listener(entity, old_state, new_state):
"""Handle device state changes."""
last_state = self._attr_native_value
self._update_state()
await self._async_update_state()
if last_state != self._attr_native_value:
self.async_schedule_update_ha_state(True)

# pylint: disable=unused-argument
@callback
def sensor_startup(event):
async def async_sensor_startup(event):
"""Update template on startup."""
if self._has_period:
self.async_schedule_update_ha_state(True)
else:
async_track_state_change(self.hass, self.sources, sensor_state_listener)
sensor_state_listener(None, None, None)
async_track_state_change(
self.hass, self.sources, async_sensor_state_listener
)
await async_sensor_state_listener(None, None, None)

self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, sensor_startup)
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, async_sensor_startup)

@staticmethod
def _has_state(state) -> bool:
Expand Down Expand Up @@ -293,10 +295,10 @@ def _get_state_value(self, state: LazyState) -> Optional[float]:
return state

@Throttle(UPDATE_MIN_TIME)
def update(self):
async def async_update(self):
"""Update the sensor state if it needed."""
if self._has_period:
self._update_state()
await self._async_update_state()

@staticmethod
def handle_template_exception(exc, field):
Expand All @@ -310,7 +312,7 @@ def handle_template_exception(exc, field):
else:
_LOGGER.error('Error parsing template for field "%s": %s', field, exc)

def _update_period(self): # pylint: disable=too-many-branches
async def _async_update_period(self): # pylint: disable=too-many-branches
"""Parse the templates and calculate a datetime tuples."""
start = end = None
now = dt_util.now()
Expand All @@ -319,7 +321,7 @@ def _update_period(self): # pylint: disable=too-many-branches
if self._start_template is not None:
_LOGGER.debug("Process start template: %s", self._start_template)
try:
start_rendered = self._start_template.render()
start_rendered = self._start_template.async_render()
except (TemplateError, TypeError) as ex:
self.handle_template_exception(ex, "start")
return
Expand All @@ -340,7 +342,7 @@ def _update_period(self): # pylint: disable=too-many-branches
if self._end_template is not None:
_LOGGER.debug("Process end template: %s", self._end_template)
try:
end_rendered = self._end_template.render()
end_rendered = self._end_template.async_render()
except (TemplateError, TypeError) as ex:
self.handle_template_exception(ex, "end")
return
Expand Down Expand Up @@ -410,7 +412,7 @@ def _init_mode(self, state: LazyState):
_LOGGER.debug("%s is NOT a temperature entity.", state.entity_id)
self._attr_icon = state.attributes.get(ATTR_ICON)

def _update_state(
async def _async_update_state(
self,
): # pylint: disable=too-many-locals,too-many-branches,too-many-statements
"""Update the sensor state."""
Expand All @@ -419,7 +421,7 @@ def _update_state(
p_period = self._period

# Parse templates
self._update_period()
await self._async_update_period()

if self._period is not None:
now = datetime.datetime.now()
Expand Down Expand Up @@ -474,8 +476,12 @@ def _update_state(

else:
# Get history between start and now
history_list = history.state_changes_during_period(
self.hass, start, end, str(entity_id)
history_list = await get_instance(self.hass).async_add_executor_job(
history.state_changes_during_period,
self.hass,
start,
end,
str(entity_id),
)

if (
Expand Down
6 changes: 3 additions & 3 deletions tests/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,10 +498,10 @@ async def test__init_mode(hass: HomeAssistant, default_sensor, caplog):

async def test_update(default_sensor):
"""Test update throttler."""
with patch.object(default_sensor, "_update_state") as ups:
default_sensor.update()
with patch.object(default_sensor, "_async_update_state") as ups:
await default_sensor.async_update()
await sleep(1)
default_sensor.update()
await default_sensor.async_update()

assert ups.call_count == 1

Expand Down

0 comments on commit 5e3f1ad

Please sign in to comment.