Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2023.12.1 #105324

Merged
merged 36 commits into from
Dec 8, 2023
Merged

2023.12.1 #105324

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9527548
Initialize energy_state without price (#97031)
Excentyl Dec 8, 2023
24f0e92
Bump yolink-api to 0.3.4 (#105124)
matrixd2 Dec 7, 2023
53497e3
Bump apple_weatherkit to 1.1.2 (#105140)
tjhorner Dec 6, 2023
3972d8f
Correct smtp error message string (#105148)
jbouwh Dec 7, 2023
b977fd6
Correct smtp error message string (#105148)
jbouwh Dec 7, 2023
47032d0
Expose todo entities to Assist by default (#105150)
synesthesiam Dec 7, 2023
a2f9ffe
Disable scenarios (scenes) for local API in Overkiz (#105153)
iMicknl Dec 7, 2023
cfa8595
Improve LIDL christmas light detection in deCONZ (#105155)
Kane610 Dec 7, 2023
b832a69
Bump reolink_aio to 0.8.2 (#105157)
starkillerOG Dec 7, 2023
614e906
Don't return TTS URL in Assist pipeline (#105164)
synesthesiam Dec 7, 2023
054ede9
Bump Météo-France to 1.3.0 (#105170)
Quentame Dec 7, 2023
c035ffb
Fix ZHA quirk ID custom entities matching all devices (#105184)
TheJulianJES Dec 7, 2023
688fab4
Fix missing apostrophe in smtp (#105189)
lunmay Dec 7, 2023
8ffb147
Set ping interval to 15 seconds instead of 5 minutes (#105191)
nohn Dec 7, 2023
c5d1a0f
Increase ping update interval to 30 seconds (#105199)
jpbede Dec 7, 2023
119c9c3
Fix bug in roon incremental volume control. (#105201)
pavoni Dec 7, 2023
f1169e0
fix supportedFanOscillationModes is null (#105205)
haimn Dec 7, 2023
d679764
Disable config flow progress in peco config flow (#105222)
emontnemery Dec 7, 2023
c6187ed
Fix Fritzbox light setup (#105232)
flabbamann Dec 8, 2023
3a10ea1
Fix check_date service in workday (#105241)
gjohansson-ST Dec 7, 2023
f8d9c4c
Fix AsusWrt invalid data type with tuple type (#105247)
ollo69 Dec 8, 2023
38e01b2
Explicit check for None in Discovergy entity if condition (#105248)
jpbede Dec 7, 2023
4953a36
Add migration for old HomeWizard sensors (#105251)
DCSBL Dec 8, 2023
d89f6b5
Fix update of uncategorized OurGroceries items (#105255)
OnFreund Dec 7, 2023
f3bb832
Bump pyunifiprotect to 4.22.0 (#105265)
bdraco Dec 8, 2023
53cbde8
Set device id and forward errors to Wyoming satellites (#105266)
synesthesiam Dec 8, 2023
892a7c3
Fix mqtt json light state updates using deprecated color handling (#1…
jbouwh Dec 8, 2023
c24af97
Always set _attr_current_option in Nobø Hub select entities (#105289)
oyvindwe Dec 8, 2023
1777f6b
Update frontend to 20231208.2 (#105299)
piitaya Dec 8, 2023
1e3c154
Add test for energy cost sensor for late price sensor (#105312)
emontnemery Dec 8, 2023
d9b31e9
Use area id for context instead of name (#105313)
synesthesiam Dec 8, 2023
3595412
Add workaround for orjson not handling subclasses of str (#105314)
emontnemery Dec 8, 2023
9aaff61
Bump version to 2023.12.1
frenck Dec 8, 2023
629731e
Add rollback on exception that needs rollback in SQL (#104948)
gjohansson-ST Dec 8, 2023
5220afa
Workaround `to_json` template filter in parsing dict key (#105327)
jbouwh Dec 8, 2023
47dc48c
Bump plugwise to v0.34.5 (#105330)
bouwew Dec 8, 2023
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
10 changes: 5 additions & 5 deletions homeassistant/components/assist_pipeline/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from enum import StrEnum
import logging
from pathlib import Path
from queue import Queue
from queue import Empty, Queue
from threading import Thread
import time
from typing import TYPE_CHECKING, Any, Final, cast
Expand Down Expand Up @@ -1010,8 +1010,8 @@ async def prepare_text_to_speech(self) -> None:
self.tts_engine = engine
self.tts_options = tts_options

async def text_to_speech(self, tts_input: str) -> str:
"""Run text-to-speech portion of pipeline. Returns URL of TTS audio."""
async def text_to_speech(self, tts_input: str) -> None:
"""Run text-to-speech portion of pipeline."""
self.process_event(
PipelineEvent(
PipelineEventType.TTS_START,
Expand Down Expand Up @@ -1058,8 +1058,6 @@ async def text_to_speech(self, tts_input: str) -> str:
PipelineEvent(PipelineEventType.TTS_END, {"tts_output": tts_output})
)

return tts_media.url

def _capture_chunk(self, audio_bytes: bytes | None) -> None:
"""Forward audio chunk to various capturing mechanisms."""
if self.debug_recording_queue is not None:
Expand Down Expand Up @@ -1246,6 +1244,8 @@ def _pipeline_debug_recording_thread_proc(
# Chunk of 16-bit mono audio at 16Khz
if wav_writer is not None:
wav_writer.writeframes(message)
except Empty:
pass # occurs when pipeline has unexpected error
except Exception: # pylint: disable=broad-exception-caught
_LOGGER.exception("Unexpected error in debug recording thread")
finally:
Expand Down
6 changes: 4 additions & 2 deletions homeassistant/components/asuswrt/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@


_AsusWrtBridgeT = TypeVar("_AsusWrtBridgeT", bound="AsusWrtBridge")
_FuncType = Callable[[_AsusWrtBridgeT], Awaitable[list[Any] | dict[str, Any]]]
_FuncType = Callable[
[_AsusWrtBridgeT], Awaitable[list[Any] | tuple[Any] | dict[str, Any]]
]
_ReturnFuncType = Callable[[_AsusWrtBridgeT], Coroutine[Any, Any, dict[str, Any]]]


Expand All @@ -81,7 +83,7 @@ async def _wrapper(self: _AsusWrtBridgeT) -> dict[str, Any]:

if isinstance(data, dict):
return dict(zip(keys, list(data.values())))
if not isinstance(data, list):
if not isinstance(data, (list, tuple)):
raise UpdateFailed("Received invalid data type")
return dict(zip(keys, data))

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/conversation/default_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ def _make_intent_context(
if device_area is None:
return None

return {"area": device_area.name}
return {"area": device_area.id}

def _get_error_text(
self, response_type: ResponseType, lang_intents: LanguageIntents | None
Expand Down
6 changes: 3 additions & 3 deletions homeassistant/components/deconz/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
LightColorMode.XY: ColorMode.XY,
}

TS0601_EFFECTS = [
XMAS_LIGHT_EFFECTS = [
"carnival",
"collide",
"fading",
Expand Down Expand Up @@ -200,8 +200,8 @@ def __init__(self, device: _LightDeviceT, gateway: DeconzGateway) -> None:
if device.effect is not None:
self._attr_supported_features |= LightEntityFeature.EFFECT
self._attr_effect_list = [EFFECT_COLORLOOP]
if device.model_id == "TS0601":
self._attr_effect_list += TS0601_EFFECTS
if device.model_id in ("HG06467", "TS0601"):
self._attr_effect_list = XMAS_LIGHT_EFFECTS

@property
def color_mode(self) -> str | None:
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/discovergy/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ async def async_setup_entry(
for description in sensors
for value_key in {description.key, *description.alternative_keys}
if description.value_fn(coordinator.data, value_key, description.scale)
is not None
)

async_add_entities(entities)
Expand Down
5 changes: 5 additions & 0 deletions homeassistant/components/energy/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,11 @@ def _update_cost(self) -> None:
try:
energy_price = float(energy_price_state.state)
except ValueError:
if self._last_energy_sensor_state is None:
# Initialize as it's the first time all required entities except
# price are in place. This means that the cost will update the first
# time the energy is updated after the price entity is in place.
self._reset(energy_state)
return

energy_price_unit: str | None = energy_price_state.attributes.get(
Expand Down
46 changes: 26 additions & 20 deletions homeassistant/components/fritzbox/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ def _add_entities() -> None:
FritzboxLight(
coordinator,
ain,
device.get_colors(),
device.get_color_temps(),
)
for ain in coordinator.new_devices
if (device := coordinator.data.devices[ain]).has_lightbulb
if (coordinator.data.devices[ain]).has_lightbulb
)

entry.async_on_unload(coordinator.async_add_listener(_add_entities))
Expand All @@ -57,27 +55,10 @@ def __init__(
self,
coordinator: FritzboxDataUpdateCoordinator,
ain: str,
supported_colors: dict,
supported_color_temps: list[int],
) -> None:
"""Initialize the FritzboxLight entity."""
super().__init__(coordinator, ain, None)

if supported_color_temps:
# only available for color bulbs
self._attr_max_color_temp_kelvin = int(max(supported_color_temps))
self._attr_min_color_temp_kelvin = int(min(supported_color_temps))

# Fritz!DECT 500 only supports 12 values for hue, with 3 saturations each.
# Map supported colors to dict {hue: [sat1, sat2, sat3]} for easier lookup
self._supported_hs: dict[int, list[int]] = {}
for values in supported_colors.values():
hue = int(values[0][0])
self._supported_hs[hue] = [
int(values[0][1]),
int(values[1][1]),
int(values[2][1]),
]

@property
def is_on(self) -> bool:
Expand Down Expand Up @@ -173,3 +154,28 @@ async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
await self.hass.async_add_executor_job(self.data.set_state_off)
await self.coordinator.async_refresh()

async def async_added_to_hass(self) -> None:
"""Get light attributes from device after entity is added to hass."""
await super().async_added_to_hass()
supported_colors = await self.hass.async_add_executor_job(
self.coordinator.data.devices[self.ain].get_colors
)
supported_color_temps = await self.hass.async_add_executor_job(
self.coordinator.data.devices[self.ain].get_color_temps
)

if supported_color_temps:
# only available for color bulbs
self._attr_max_color_temp_kelvin = int(max(supported_color_temps))
self._attr_min_color_temp_kelvin = int(min(supported_color_temps))

# Fritz!DECT 500 only supports 12 values for hue, with 3 saturations each.
# Map supported colors to dict {hue: [sat1, sat2, sat3]} for easier lookup
for values in supported_colors.values():
hue = int(values[0][0])
self._supported_hs[hue] = [
int(values[0][1]),
int(values[1][1]),
int(values[2][1]),
]
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==20231206.0"]
"requirements": ["home-assistant-frontend==20231208.2"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"scene",
"script",
"switch",
"todo",
"vacuum",
"water_heater",
}
Expand Down
55 changes: 53 additions & 2 deletions homeassistant/components/homewizard/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,61 @@
"""The Homewizard integration."""
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import entity_registry as er

from .const import DOMAIN, PLATFORMS
from .const import DOMAIN, LOGGER, PLATFORMS
from .coordinator import HWEnergyDeviceUpdateCoordinator as Coordinator


async def _async_migrate_entries(
hass: HomeAssistant, config_entry: ConfigEntry
) -> None:
"""Migrate old entry.

The HWE-SKT had no total_power_*_kwh in 2023.11, in 2023.12 it does.
But simultaneously, the total_power_*_t1_kwh was removed for HWE-SKT.

This migration migrates the old unique_id to the new one, if possible.

Migration can be removed after 2024.6
"""
entity_registry = er.async_get(hass)

@callback
def update_unique_id(entry: er.RegistryEntry) -> dict[str, str] | None:
replacements = {
"total_power_import_t1_kwh": "total_power_import_kwh",
"total_power_export_t1_kwh": "total_power_export_kwh",
}

for old_id, new_id in replacements.items():
if entry.unique_id.endswith(old_id):
new_unique_id = entry.unique_id.replace(old_id, new_id)
if existing_entity_id := entity_registry.async_get_entity_id(
entry.domain, entry.platform, new_unique_id
):
LOGGER.debug(
"Cannot migrate to unique_id '%s', already exists for '%s'",
new_unique_id,
existing_entity_id,
)
return None
LOGGER.debug(
"Migrating entity '%s' unique_id from '%s' to '%s'",
entry.entity_id,
entry.unique_id,
new_unique_id,
)
return {
"new_unique_id": new_unique_id,
}

return None

await er.async_migrate_entries(hass, config_entry.entry_id, update_unique_id)


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Homewizard from a config entry."""
coordinator = Coordinator(hass)
Expand All @@ -21,6 +70,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

raise

await _async_migrate_entries(hass, entry)

hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator

# Abort reauth config flow if active
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/homewizard/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from dataclasses import dataclass
from datetime import timedelta
import logging

from homewizard_energy.models import Data, Device, State, System

Expand All @@ -11,6 +12,8 @@
DOMAIN = "homewizard"
PLATFORMS = [Platform.BUTTON, Platform.NUMBER, Platform.SENSOR, Platform.SWITCH]

LOGGER = logging.getLogger(__package__)

# Platform config.
CONF_API_ENABLED = "api_enabled"
CONF_DATA = "data"
Expand Down
1 change: 0 additions & 1 deletion homeassistant/components/homewizard/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,6 @@ async def async_setup_entry(
) -> None:
"""Initialize sensors."""
coordinator: HWEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]

async_add_entities(
HomeWizardSensorEntity(coordinator, description)
for description in SENSORS
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/meteo_france/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/meteo_france",
"iot_class": "cloud_polling",
"loggers": ["meteofrance_api"],
"requirements": ["meteofrance-api==1.2.0"]
"requirements": ["meteofrance-api==1.3.0"]
}
3 changes: 3 additions & 0 deletions homeassistant/components/mqtt/light/schema_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ def state_received(msg: ReceiveMessage) -> None:
values["color_temp"],
self.entity_id,
)
# Allow to switch back to color_temp
if "color" not in values:
self._attr_hs_color = None

if self.supported_features and LightEntityFeature.EFFECT:
with suppress(KeyError):
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/nobo_hub/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class NoboGlobalSelector(SelectEntity):
nobo.API.OVERRIDE_MODE_ECO: "eco",
}
_attr_options = list(_modes.values())
_attr_current_option: str
_attr_current_option: str | None = None

def __init__(self, hub: nobo, override_type) -> None:
"""Initialize the global override selector."""
Expand Down Expand Up @@ -117,7 +117,7 @@ class NoboProfileSelector(SelectEntity):
_attr_should_poll = False
_profiles: dict[int, str] = {}
_attr_options: list[str] = []
_attr_current_option: str
_attr_current_option: str | None = None

def __init__(self, zone_id: str, hub: nobo) -> None:
"""Initialize the week profile selector."""
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/ourgroceries/todo.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ async def async_update_todo_item(self, item: TodoItem) -> None:
if item.summary:
api_items = self.coordinator.data[self._list_id]["list"]["items"]
category = next(
api_item["categoryId"]
api_item.get("categoryId")
for api_item in api_items
if api_item["id"] == item.uid
)
Expand Down
22 changes: 9 additions & 13 deletions homeassistant/components/overkiz/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
"""The Overkiz (by Somfy) integration."""
from __future__ import annotations

import asyncio
from collections import defaultdict
from dataclasses import dataclass
from typing import cast

from aiohttp import ClientError
from pyoverkiz.client import OverkizClient
Expand All @@ -16,7 +14,7 @@
NotSuchTokenException,
TooManyRequestsException,
)
from pyoverkiz.models import Device, OverkizServer, Scenario, Setup
from pyoverkiz.models import Device, OverkizServer, Scenario
from pyoverkiz.utils import generate_local_server

from homeassistant.config_entries import ConfigEntry
Expand Down Expand Up @@ -82,13 +80,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

try:
await client.login()

setup, scenarios = await asyncio.gather(
*[
client.get_setup(),
client.get_scenarios(),
]
)
setup = await client.get_setup()

# Local API does expose scenarios, but they are not functional.
# Tracked in https://github.com/Somfy-Developer/Somfy-TaHoma-Developer-Mode/issues/21
if api_type == APIType.CLOUD:
scenarios = await client.get_scenarios()
else:
scenarios = []
except (BadCredentialsException, NotSuchTokenException) as exception:
raise ConfigEntryAuthFailed("Invalid authentication") from exception
except TooManyRequestsException as exception:
Expand All @@ -98,9 +97,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
except MaintenanceException as exception:
raise ConfigEntryNotReady("Server is down for maintenance") from exception

setup = cast(Setup, setup)
scenarios = cast(list[Scenario], scenarios)

coordinator = OverkizDataUpdateCoordinator(
hass,
LOGGER,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/overkiz/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
}
},
"local_or_cloud": {
"description": "Choose between local or cloud API. Local API supports TaHoma Connexoon, TaHoma v2, and TaHoma Switch. Climate devices are not supported in local API.",
"description": "Choose between local or cloud API. Local API supports TaHoma Connexoon, TaHoma v2, and TaHoma Switch. Climate devices and scenarios are not supported in local API.",
"data": {
"api_type": "API type"
}
Expand Down
Loading
Loading