Skip to content

Commit

Permalink
2024.10.4 (home-assistant#129181)
Browse files Browse the repository at this point in the history
  • Loading branch information
frenck authored Oct 25, 2024
2 parents a301d51 + c09f15b commit d31995f
Show file tree
Hide file tree
Showing 36 changed files with 1,071 additions and 61 deletions.
5 changes: 0 additions & 5 deletions homeassistant/components/awair/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
"name": "Awair",
"codeowners": ["@ahayworth", "@danielsjf"],
"config_flow": true,
"dhcp": [
{
"macaddress": "70886B1*"
}
],
"documentation": "https://www.home-assistant.io/integrations/awair",
"iot_class": "local_polling",
"loggers": ["python_awair"],
Expand Down
93 changes: 93 additions & 0 deletions homeassistant/components/comelit/diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""Diagnostics support for Comelit integration."""

from __future__ import annotations

from typing import Any

from aiocomelit import (
ComelitSerialBridgeObject,
ComelitVedoAreaObject,
ComelitVedoZoneObject,
)
from aiocomelit.const import BRIDGE

from homeassistant.components.diagnostics import async_redact_data
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PIN, CONF_TYPE
from homeassistant.core import HomeAssistant

from .const import DOMAIN
from .coordinator import ComelitBaseCoordinator

TO_REDACT = {CONF_PIN}


async def async_get_config_entry_diagnostics(
hass: HomeAssistant, entry: ConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""

coordinator: ComelitBaseCoordinator = hass.data[DOMAIN][entry.entry_id]

dev_list: list[dict[str, Any]] = []
dev_type_list: list[dict[int, Any]] = []

for dev_type in coordinator.data:
dev_type_list = []
for sensor_data in coordinator.data[dev_type].values():
if isinstance(sensor_data, ComelitSerialBridgeObject):
dev_type_list.append(
{
sensor_data.index: {
"name": sensor_data.name,
"status": sensor_data.status,
"human_status": sensor_data.human_status,
"protected": sensor_data.protected,
"val": sensor_data.val,
"zone": sensor_data.zone,
"power": sensor_data.power,
"power_unit": sensor_data.power_unit,
}
}
)
if isinstance(sensor_data, ComelitVedoAreaObject):
dev_type_list.append(
{
sensor_data.index: {
"name": sensor_data.name,
"human_status": sensor_data.human_status.value,
"p1": sensor_data.p1,
"p2": sensor_data.p2,
"ready": sensor_data.ready,
"armed": sensor_data.armed,
"alarm": sensor_data.alarm,
"alarm_memory": sensor_data.alarm_memory,
"sabotage": sensor_data.sabotage,
"anomaly": sensor_data.anomaly,
"in_time": sensor_data.in_time,
"out_time": sensor_data.out_time,
}
}
)
if isinstance(sensor_data, ComelitVedoZoneObject):
dev_type_list.append(
{
sensor_data.index: {
"name": sensor_data.name,
"human_status": sensor_data.human_status.value,
"status": sensor_data.status,
"status_api": sensor_data.status_api,
}
}
)
dev_list.append({dev_type: dev_type_list})

return {
"entry": async_redact_data(entry.as_dict(), TO_REDACT),
"type": entry.data.get(CONF_TYPE, BRIDGE),
"device_info": {
"last_update success": coordinator.last_update_success,
"last_exception": repr(coordinator.last_exception),
"devices": dev_list,
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def new_device_callback() -> None:
)
)
tracked.add(station.mac_address)
async_add_entities(new_entities)
async_add_entities(new_entities)

@callback
def restore_entities() -> None:
Expand Down
6 changes: 5 additions & 1 deletion homeassistant/components/devolo_home_network/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
)
from devolo_plc_api.plcnet_api import DataRate, LogicalNetwork

from homeassistant.const import ATTR_CONNECTIONS
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.update_coordinator import (
Expand Down Expand Up @@ -45,14 +46,17 @@ def __init__(

self._attr_device_info = DeviceInfo(
configuration_url=f"http://{self.device.ip}",
connections={(CONNECTION_NETWORK_MAC, self.device.mac)},
identifiers={(DOMAIN, str(self.device.serial_number))},
manufacturer="devolo",
model=self.device.product,
model_id=self.device.mt_number,
serial_number=self.device.serial_number,
sw_version=self.device.firmware_version,
)
if self.device.mac:
self._attr_device_info[ATTR_CONNECTIONS] = {
(CONNECTION_NETWORK_MAC, self.device.mac)
}
self._attr_translation_key = self.entity_description.key
self._attr_unique_id = (
f"{self.device.serial_number}_{self.entity_description.key}"
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/duotecno/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"iot_class": "local_push",
"loggers": ["pyduotecno", "pyduotecno-node", "pyduotecno-unit"],
"quality_scale": "silver",
"requirements": ["pyDuotecno==2024.10.0"]
"requirements": ["pyDuotecno==2024.10.1"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/evohome/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
config[DOMAIN][CONF_PASSWORD],
)

except evo.AuthenticationFailed as err:
except (evo.AuthenticationFailed, evo.RequestFailed) as err:
handle_evo_exception(err)
return False

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==20241002.3"]
"requirements": ["home-assistant-frontend==20241002.4"]
}
22 changes: 18 additions & 4 deletions homeassistant/components/honeywell/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
RETRY,
)

MODE_PERMANENT_HOLD = 2
MODE_TEMPORARY_HOLD = 1
MODE_HOLD = {MODE_PERMANENT_HOLD, MODE_TEMPORARY_HOLD}

ATTR_FAN_ACTION = "fan_action"

ATTR_PERMANENT_HOLD = "permanent_hold"
Expand Down Expand Up @@ -175,6 +179,7 @@ def __init__(
self._cool_away_temp = cool_away_temp
self._heat_away_temp = heat_away_temp
self._away = False
self._away_hold = False
self._retry = 0

self._attr_unique_id = str(device.deviceid)
Expand Down Expand Up @@ -323,22 +328,31 @@ def target_temperature_low(self) -> float | None:
@property
def preset_mode(self) -> str | None:
"""Return the current preset mode, e.g., home, away, temp."""
if self._away:
if self._away and self._is_hold():
self._away_hold = True
return PRESET_AWAY
if self._is_permanent_hold():
if self._is_hold():
return PRESET_HOLD

# Someone has changed the stat manually out of hold in away mode
if self._away and self._away_hold:
self._away = False
self._away_hold = False
return PRESET_NONE

@property
def fan_mode(self) -> str | None:
"""Return the fan setting."""
return HW_FAN_MODE_TO_HA.get(self._device.fan_mode)

def _is_hold(self) -> bool:
heat_status = self._device.raw_ui_data.get("StatusHeat", 0)
cool_status = self._device.raw_ui_data.get("StatusCool", 0)
return heat_status in MODE_HOLD or cool_status in MODE_HOLD

def _is_permanent_hold(self) -> bool:
heat_status = self._device.raw_ui_data.get("StatusHeat", 0)
cool_status = self._device.raw_ui_data.get("StatusCool", 0)
return heat_status == 2 or cool_status == 2
return MODE_PERMANENT_HOLD in (heat_status, cool_status)

async def _set_temperature(self, **kwargs) -> None:
"""Set new target temperature."""
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/media_extractor/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"iot_class": "calculated",
"loggers": ["yt_dlp"],
"quality_scale": "internal",
"requirements": ["yt-dlp==2024.10.07"],
"requirements": ["yt-dlp==2024.10.22"],
"single_config_entry": true
}
2 changes: 1 addition & 1 deletion homeassistant/components/nyt_games/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/nyt_games",
"integration_type": "service",
"iot_class": "cloud_polling",
"requirements": ["nyt_games==0.4.3"]
"requirements": ["nyt_games==0.4.4"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/nyt_games/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class NYTGamesConnectionsSensorEntityDescription(SensorEntityDescription):
state_class=SensorStateClass.TOTAL_INCREASING,
native_unit_of_measurement=UnitOfTime.DAYS,
device_class=SensorDeviceClass.DURATION,
value_fn=lambda connections: connections.current_streak,
value_fn=lambda connections: connections.max_streak,
),
)

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/ring/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
"iot_class": "cloud_polling",
"loggers": ["ring_doorbell"],
"quality_scale": "silver",
"requirements": ["ring-doorbell==0.9.6"]
"requirements": ["ring-doorbell==0.9.8"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/tibber/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"loggers": ["tibber"],
"quality_scale": "silver",
"requirements": ["pyTibber==0.30.2"]
"requirements": ["pyTibber==0.30.3"]
}
47 changes: 47 additions & 0 deletions homeassistant/components/vodafone_station/diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Diagnostics support for Vodafone Station."""

from __future__ import annotations

from typing import Any

from homeassistant.components.diagnostics import async_redact_data
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant

from .const import DOMAIN
from .coordinator import VodafoneStationRouter

TO_REDACT = {CONF_USERNAME, CONF_PASSWORD}


async def async_get_config_entry_diagnostics(
hass: HomeAssistant, entry: ConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""

coordinator: VodafoneStationRouter = hass.data[DOMAIN][entry.entry_id]

sensors_data = coordinator.data.sensors
return {
"entry": async_redact_data(entry.as_dict(), TO_REDACT),
"device_info": {
"sys_model_name": sensors_data.get("sys_model_name"),
"sys_firmware_version": sensors_data["sys_firmware_version"],
"sys_hardware_version": sensors_data["sys_hardware_version"],
"sys_cpu_usage": sensors_data["sys_cpu_usage"][:-1],
"sys_memory_usage": sensors_data["sys_memory_usage"][:-1],
"sys_reboot_cause": sensors_data["sys_reboot_cause"],
"last_update success": coordinator.last_update_success,
"last_exception": coordinator.last_exception,
"client_devices": [
{
"hostname": device_info.device.name,
"connection_type": device_info.device.connection_type,
"connected": device_info.device.connected,
"type": device_info.device.type,
}
for _, device_info in coordinator.data.devices.items()
],
},
}
41 changes: 32 additions & 9 deletions homeassistant/components/vodafone_station/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,42 @@
from .coordinator import VodafoneStationRouter

NOT_AVAILABLE: list = ["", "N/A", "0.0.0.0"]
UPTIME_DEVIATION = 30


@dataclass(frozen=True, kw_only=True)
class VodafoneStationEntityDescription(SensorEntityDescription):
"""Vodafone Station entity description."""

value: Callable[[Any, Any], Any] = (
lambda coordinator, key: coordinator.data.sensors[key]
value: Callable[[Any, Any, Any], Any] = (
lambda coordinator, last_value, key: coordinator.data.sensors[key]
)
is_suitable: Callable[[dict], bool] = lambda val: True


def _calculate_uptime(coordinator: VodafoneStationRouter, key: str) -> datetime:
def _calculate_uptime(
coordinator: VodafoneStationRouter,
last_value: datetime | None,
key: str,
) -> datetime:
"""Calculate device uptime."""

return coordinator.api.convert_uptime(coordinator.data.sensors[key])
delta_uptime = coordinator.api.convert_uptime(coordinator.data.sensors[key])

if (
not last_value
or abs((delta_uptime - last_value).total_seconds()) > UPTIME_DEVIATION
):
return delta_uptime

def _line_connection(coordinator: VodafoneStationRouter, key: str) -> str | None:
return last_value


def _line_connection(
coordinator: VodafoneStationRouter,
last_value: str | None,
key: str,
) -> str | None:
"""Identify line type."""

value = coordinator.data.sensors
Expand Down Expand Up @@ -126,14 +143,18 @@ def _line_connection(coordinator: VodafoneStationRouter, key: str) -> str | None
translation_key="sys_cpu_usage",
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda coordinator, key: float(coordinator.data.sensors[key][:-1]),
value=lambda coordinator, last_value, key: float(
coordinator.data.sensors[key][:-1]
),
),
VodafoneStationEntityDescription(
key="sys_memory_usage",
translation_key="sys_memory_usage",
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda coordinator, key: float(coordinator.data.sensors[key][:-1]),
value=lambda coordinator, last_value, key: float(
coordinator.data.sensors[key][:-1]
),
),
VodafoneStationEntityDescription(
key="sys_reboot_cause",
Expand Down Expand Up @@ -178,10 +199,12 @@ def __init__(
self.entity_description = description
self._attr_device_info = coordinator.device_info
self._attr_unique_id = f"{coordinator.serial_number}_{description.key}"
self._old_state = None

@property
def native_value(self) -> StateType:
"""Sensor value."""
return self.entity_description.value(
self.coordinator, self.entity_description.key
self._old_state = self.entity_description.value(
self.coordinator, self._old_state, self.entity_description.key
)
return self._old_state
2 changes: 1 addition & 1 deletion homeassistant/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
APPLICATION_NAME: Final = "HomeAssistant"
MAJOR_VERSION: Final = 2024
MINOR_VERSION: Final = 10
PATCH_VERSION: Final = "3"
PATCH_VERSION: Final = "4"
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 12, 0)
Expand Down
Loading

0 comments on commit d31995f

Please sign in to comment.