Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/components/alexa_devices/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"loggers": ["aioamazondevices"],
"quality_scale": "silver",
"requirements": ["aioamazondevices==3.2.10"]
"requirements": ["aioamazondevices==3.5.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/blue_current/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/blue_current",
"iot_class": "cloud_push",
"loggers": ["bluecurrent_api"],
"requirements": ["bluecurrent-api==1.2.3"]
"requirements": ["bluecurrent-api==1.2.4"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/cloud/http_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
] = {
TimeoutError: (
HTTPStatus.BAD_GATEWAY,
"Unable to reach the Home Assistant cloud.",
"Unable to reach the Home Assistant Cloud.",
),
aiohttp.ClientError: (
HTTPStatus.INTERNAL_SERVER_ERROR,
Expand Down
13 changes: 1 addition & 12 deletions homeassistant/components/command_line/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

from jsonpath import jsonpath

from homeassistant.components.sensor import SensorDeviceClass
from homeassistant.components.sensor.helpers import async_parse_date_datetime
from homeassistant.const import (
CONF_COMMAND,
CONF_NAME,
Expand Down Expand Up @@ -188,16 +186,7 @@ async def _async_update(self) -> None:
self.entity_id, variables, None
)

if self.device_class not in {
SensorDeviceClass.DATE,
SensorDeviceClass.TIMESTAMP,
}:
self._attr_native_value = value
elif value is not None:
self._attr_native_value = async_parse_date_datetime(
value, self.entity_id, self.device_class
)

self._set_native_value_with_possible_timestamp(value)
self._process_manual_data(variables)
self.async_write_ha_state()

Expand Down
37 changes: 22 additions & 15 deletions homeassistant/components/derivative/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,12 @@ def on_state_reported(event: Event[EventStateReportedData]) -> None:
# changed state, then we know it will still be zero.
return
schedule_max_sub_interval_exceeded(new_state)
calc_derivative(new_state, new_state.state, event.data["old_last_reported"])
calc_derivative(
new_state,
new_state.state,
event.data["last_reported"],
event.data["old_last_reported"],
)

@callback
def on_state_changed(event: Event[EventStateChangedData]) -> None:
Expand All @@ -334,19 +339,27 @@ def on_state_changed(event: Event[EventStateChangedData]) -> None:
schedule_max_sub_interval_exceeded(new_state)
old_state = event.data["old_state"]
if old_state is not None:
calc_derivative(new_state, old_state.state, old_state.last_reported)
calc_derivative(
new_state,
old_state.state,
new_state.last_updated,
old_state.last_reported,
)
else:
# On first state change from none, update availability
self.async_write_ha_state()

def calc_derivative(
new_state: State, old_value: str, old_last_reported: datetime
new_state: State,
old_value: str,
new_timestamp: datetime,
old_timestamp: datetime,
) -> None:
"""Handle the sensor state changes."""
if not _is_decimal_state(old_value):
if self._last_valid_state_time:
old_value = self._last_valid_state_time[0]
old_last_reported = self._last_valid_state_time[1]
old_timestamp = self._last_valid_state_time[1]
else:
# Sensor becomes valid for the first time, just keep the restored value
self.async_write_ha_state()
Expand All @@ -358,12 +371,10 @@ def calc_derivative(
"" if unit is None else unit
)

self._prune_state_list(new_state.last_reported)
self._prune_state_list(new_timestamp)

try:
elapsed_time = (
new_state.last_reported - old_last_reported
).total_seconds()
elapsed_time = (new_timestamp - old_timestamp).total_seconds()
delta_value = Decimal(new_state.state) - Decimal(old_value)
new_derivative = (
delta_value
Expand Down Expand Up @@ -392,22 +403,18 @@ def calc_derivative(
return

# add latest derivative to the window list
self._state_list.append(
(old_last_reported, new_state.last_reported, new_derivative)
)
self._state_list.append((old_timestamp, new_timestamp, new_derivative))
self._last_valid_state_time = (
new_state.state,
new_state.last_reported,
new_timestamp,
)

# If outside of time window just report derivative (is the same as modeling it in the window),
# otherwise take the weighted average with the previous derivatives
if elapsed_time > self._time_window:
derivative = new_derivative
else:
derivative = self._calc_derivative_from_state_list(
new_state.last_reported
)
derivative = self._calc_derivative_from_state_list(new_timestamp)
self._write_native_value(derivative)

source_state = self.hass.states.get(self._sensor_source_id)
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
"documentation": "https://www.home-assistant.io/integrations/frontend",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["home-assistant-frontend==20250702.2"]
"requirements": ["home-assistant-frontend==20250702.3"]
}
5 changes: 5 additions & 0 deletions homeassistant/components/husqvarna_automower/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,11 @@ def extra_state_attributes(self) -> Mapping[str, Any] | None:
"""Return the state attributes."""
return self.entity_description.extra_state_attributes_fn(self.mower_attributes)

@property
def available(self) -> bool:
"""Return the available attribute of the entity."""
return super().available and self.native_value is not None


class WorkAreaSensorEntity(WorkAreaAvailableEntity, SensorEntity):
"""Defining the Work area sensors with WorkAreaSensorEntityDescription."""
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/imgw_pib/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/imgw_pib",
"iot_class": "cloud_polling",
"quality_scale": "silver",
"requirements": ["imgw_pib==1.4.1"]
"requirements": ["imgw_pib==1.4.2"]
}
38 changes: 25 additions & 13 deletions homeassistant/components/integration/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ def _integrate_on_state_change_with_max_sub_interval(
) -> None:
"""Handle sensor state update when sub interval is configured."""
self._integrate_on_state_update_with_max_sub_interval(
None, event.data["old_state"], event.data["new_state"]
None, None, event.data["old_state"], event.data["new_state"]
)

@callback
Expand All @@ -472,13 +472,17 @@ def _integrate_on_state_report_with_max_sub_interval(
) -> None:
"""Handle sensor state report when sub interval is configured."""
self._integrate_on_state_update_with_max_sub_interval(
event.data["old_last_reported"], None, event.data["new_state"]
event.data["old_last_reported"],
event.data["last_reported"],
None,
event.data["new_state"],
)

@callback
def _integrate_on_state_update_with_max_sub_interval(
self,
old_last_reported: datetime | None,
old_timestamp: datetime | None,
new_timestamp: datetime | None,
old_state: State | None,
new_state: State | None,
) -> None:
Expand All @@ -489,7 +493,9 @@ def _integrate_on_state_update_with_max_sub_interval(
"""
self._cancel_max_sub_interval_exceeded_callback()
try:
self._integrate_on_state_change(old_last_reported, old_state, new_state)
self._integrate_on_state_change(
old_timestamp, new_timestamp, old_state, new_state
)
self._last_integration_trigger = _IntegrationTrigger.StateEvent
self._last_integration_time = datetime.now(tz=UTC)
finally:
Expand All @@ -503,7 +509,7 @@ def _integrate_on_state_change_callback(
) -> None:
"""Handle sensor state change."""
return self._integrate_on_state_change(
None, event.data["old_state"], event.data["new_state"]
None, None, event.data["old_state"], event.data["new_state"]
)

@callback
Expand All @@ -512,12 +518,16 @@ def _integrate_on_state_report_callback(
) -> None:
"""Handle sensor state report."""
return self._integrate_on_state_change(
event.data["old_last_reported"], None, event.data["new_state"]
event.data["old_last_reported"],
event.data["last_reported"],
None,
event.data["new_state"],
)

def _integrate_on_state_change(
self,
old_last_reported: datetime | None,
old_timestamp: datetime | None,
new_timestamp: datetime | None,
old_state: State | None,
new_state: State | None,
) -> None:
Expand All @@ -531,16 +541,17 @@ def _integrate_on_state_change(

if old_state:
# state has changed, we recover old_state from the event
new_timestamp = new_state.last_updated
old_state_state = old_state.state
old_last_reported = old_state.last_reported
old_timestamp = old_state.last_reported
else:
# event state reported without any state change
# first state or event state reported without any state change
old_state_state = new_state.state

self._attr_available = True
self._derive_and_set_attributes_from_state(new_state)

if old_last_reported is None and old_state is None:
if old_timestamp is None and old_state is None:
self.async_write_ha_state()
return

Expand All @@ -551,11 +562,12 @@ def _integrate_on_state_change(
return

if TYPE_CHECKING:
assert old_last_reported is not None
assert new_timestamp is not None
assert old_timestamp is not None
elapsed_seconds = Decimal(
(new_state.last_reported - old_last_reported).total_seconds()
(new_timestamp - old_timestamp).total_seconds()
if self._last_integration_trigger == _IntegrationTrigger.StateEvent
else (new_state.last_reported - self._last_integration_time).total_seconds()
else (new_timestamp - self._last_integration_time).total_seconds()
)

area = self._method.calculate_area_with_two_states(elapsed_seconds, *states)
Expand Down
16 changes: 1 addition & 15 deletions homeassistant/components/rest/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
CONF_STATE_CLASS,
DOMAIN as SENSOR_DOMAIN,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
)
from homeassistant.components.sensor.helpers import async_parse_date_datetime
from homeassistant.const import (
CONF_DEVICE_CLASS,
CONF_FORCE_UPDATE,
Expand Down Expand Up @@ -181,18 +179,6 @@ def _update_from_rest_data(self) -> None:
self.entity_id, variables, None
)

if value is None or self.device_class not in (
SensorDeviceClass.DATE,
SensorDeviceClass.TIMESTAMP,
):
self._attr_native_value = value
self._process_manual_data(variables)
self.async_write_ha_state()
return

self._attr_native_value = async_parse_date_datetime(
value, self.entity_id, self.device_class
)

self._set_native_value_with_possible_timestamp(value)
self._process_manual_data(variables)
self.async_write_ha_state()
15 changes: 2 additions & 13 deletions homeassistant/components/scrape/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

import voluptuous as vol

from homeassistant.components.sensor import CONF_STATE_CLASS, SensorDeviceClass
from homeassistant.components.sensor.helpers import async_parse_date_datetime
from homeassistant.components.sensor import CONF_STATE_CLASS
from homeassistant.const import (
CONF_ATTRIBUTE,
CONF_DEVICE_CLASS,
Expand Down Expand Up @@ -218,17 +217,7 @@ def _async_update_from_rest_data(self) -> None:
self.entity_id, variables, None
)

if self.device_class not in {
SensorDeviceClass.DATE,
SensorDeviceClass.TIMESTAMP,
}:
self._attr_native_value = value
self._process_manual_data(variables)
return

self._attr_native_value = async_parse_date_datetime(
value, self.entity_id, self.device_class
)
self._set_native_value_with_possible_timestamp(value)
self._process_manual_data(variables)

@property
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/smarla/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_push",
"loggers": ["pysmarlaapi", "pysignalr"],
"quality_scale": "bronze",
"requirements": ["pysmarlaapi==0.9.0"]
"requirements": ["pysmarlaapi==0.9.1"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/snmp/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ async def async_update(self) -> None:
self.entity_id, variables, STATE_UNKNOWN
)

self._attr_native_value = value
self._set_native_value_with_possible_timestamp(value)
self._process_manual_data(variables)


Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/sql/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,10 @@ def _update(self) -> None:
if data is not None and self._template is not None:
variables = self._template_variables_with_value(data)
if self._render_availability_template(variables):
self._attr_native_value = self._template.async_render_as_value_template(
_value = self._template.async_render_as_value_template(
self.entity_id, variables, None
)
self._set_native_value_with_possible_timestamp(_value)
self._process_manual_data(variables)
else:
self._attr_native_value = data
Expand Down
Loading
Loading