mirror of
https://github.com/Electric-Special/ha-core.git
synced 2026-03-21 03:03:17 +01:00
Add hot reload for derivative (#156898)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
@@ -5,5 +5,10 @@
|
||||
"default": "mdi:chart-line"
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"reload": {
|
||||
"service": "mdi:reload"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ from homeassistant.const import (
|
||||
CONF_UNIQUE_ID,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
Platform,
|
||||
UnitOfTime,
|
||||
)
|
||||
from homeassistant.core import (
|
||||
@@ -45,6 +46,7 @@ from homeassistant.helpers.event import (
|
||||
async_track_state_change_event,
|
||||
async_track_state_report_event,
|
||||
)
|
||||
from homeassistant.helpers.reload import async_setup_reload_service
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import (
|
||||
@@ -54,6 +56,7 @@ from .const import (
|
||||
CONF_UNIT,
|
||||
CONF_UNIT_PREFIX,
|
||||
CONF_UNIT_TIME,
|
||||
DOMAIN,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -147,6 +150,8 @@ async def async_setup_platform(
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the derivative sensor."""
|
||||
await async_setup_reload_service(hass, DOMAIN, [Platform.SENSOR])
|
||||
|
||||
derivative = DerivativeSensor(
|
||||
hass,
|
||||
name=config.get(CONF_NAME),
|
||||
@@ -288,14 +293,14 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
|
||||
)
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Handle entity which will be added."""
|
||||
await super().async_added_to_hass()
|
||||
async def _handle_restore(self) -> None:
|
||||
restored_data = await self.async_get_last_sensor_data()
|
||||
if restored_data:
|
||||
self._attr_native_unit_of_measurement = (
|
||||
restored_data.native_unit_of_measurement
|
||||
)
|
||||
if self._attr_native_unit_of_measurement is None:
|
||||
# Only restore the unit if it's not assigned from YAML
|
||||
self._attr_native_unit_of_measurement = (
|
||||
restored_data.native_unit_of_measurement
|
||||
)
|
||||
try:
|
||||
self._attr_native_value = round(
|
||||
Decimal(restored_data.native_value), # type: ignore[arg-type]
|
||||
@@ -304,6 +309,11 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
|
||||
except (InvalidOperation, TypeError):
|
||||
self._attr_native_value = None
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Handle entity which will be added."""
|
||||
await super().async_added_to_hass()
|
||||
await self._handle_restore()
|
||||
|
||||
source_state = self.hass.states.get(self._sensor_source_id)
|
||||
self._derive_and_set_attributes_from_state(source_state)
|
||||
|
||||
|
||||
1
homeassistant/components/derivative/services.yaml
Normal file
1
homeassistant/components/derivative/services.yaml
Normal file
@@ -0,0 +1 @@
|
||||
reload:
|
||||
@@ -58,5 +58,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"reload": {
|
||||
"description": "Reloads derivative sensors from the YAML-configuration.",
|
||||
"name": "[%key:common::action::reload%]"
|
||||
}
|
||||
},
|
||||
"title": "Derivative sensor"
|
||||
}
|
||||
|
||||
9
tests/components/derivative/fixtures/configuration.yaml
Normal file
9
tests/components/derivative/fixtures/configuration.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
sensor:
|
||||
- platform: derivative
|
||||
name: derivative
|
||||
source: "sensor.energy"
|
||||
unit: "W"
|
||||
- platform: derivative
|
||||
name: derivative_new
|
||||
source: "sensor.energy"
|
||||
unit: "W"
|
||||
@@ -4,13 +4,16 @@ from datetime import timedelta
|
||||
from math import sin
|
||||
import random
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun import freeze_time
|
||||
import pytest
|
||||
|
||||
from homeassistant import config as hass_config, core as ha
|
||||
from homeassistant.components.derivative.const import DOMAIN
|
||||
from homeassistant.components.sensor import ATTR_STATE_CLASS, SensorStateClass
|
||||
from homeassistant.const import (
|
||||
SERVICE_RELOAD,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
UnitOfPower,
|
||||
@@ -31,6 +34,7 @@ from homeassistant.util import dt as dt_util
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
async_fire_time_changed,
|
||||
get_fixture_path,
|
||||
mock_restore_cache_with_extra_data,
|
||||
)
|
||||
|
||||
@@ -1000,6 +1004,64 @@ async def test_source_unit_change(
|
||||
assert state.attributes.get("unit_of_measurement") == "dogs/s"
|
||||
|
||||
|
||||
async def test_reload(hass: HomeAssistant) -> None:
|
||||
"""Test hot-reloading derivative YAML sensors."""
|
||||
hass.state = ha.CoreState.not_running
|
||||
hass.states.async_set("sensor.energy", "0.0")
|
||||
|
||||
config = {
|
||||
"sensor": [
|
||||
{
|
||||
"platform": "derivative",
|
||||
"name": "derivative",
|
||||
"source": "sensor.energy",
|
||||
"unit": "kW",
|
||||
},
|
||||
{
|
||||
"platform": "derivative",
|
||||
"name": "derivative_remove",
|
||||
"source": "sensor.energy",
|
||||
"unit": "kW",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
assert await async_setup_component(hass, "sensor", config)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_start()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 3
|
||||
state = hass.states.get("sensor.derivative")
|
||||
assert state is not None
|
||||
assert state.attributes.get("unit_of_measurement") == "kW"
|
||||
assert hass.states.get("sensor.derivative_remove")
|
||||
|
||||
yaml_path = get_fixture_path("configuration.yaml", "derivative")
|
||||
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_RELOAD,
|
||||
{},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(hass.states.async_all()) == 3
|
||||
|
||||
# Check that we can change the unit of an existing sensor
|
||||
state = hass.states.get("sensor.derivative")
|
||||
assert state is not None
|
||||
assert state.attributes.get("unit_of_measurement") == "W"
|
||||
|
||||
# Check that we can remove a derivative sensor
|
||||
assert hass.states.get("sensor.derivative_remove") is None
|
||||
|
||||
# Check that we can add a new derivative sensor
|
||||
assert hass.states.get("sensor.derivative_new")
|
||||
|
||||
|
||||
async def test_unique_id(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
|
||||
Reference in New Issue
Block a user