Skip to content

Commit

Permalink
2023.10.4 (#102397)
Browse files Browse the repository at this point in the history
  • Loading branch information
frenck authored Oct 21, 2023
2 parents 93d7ff3 + 6be4019 commit aa5c4d8
Show file tree
Hide file tree
Showing 39 changed files with 4,878 additions and 101 deletions.
4 changes: 4 additions & 0 deletions homeassistant/components/aemet/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""The AEMET OpenData component."""

import asyncio
import logging

from aemet_opendata.exceptions import TownNotFound
Expand All @@ -8,6 +9,7 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import aiohttp_client

from .const import (
Expand Down Expand Up @@ -37,6 +39,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
except TownNotFound as err:
_LOGGER.error(err)
return False
except asyncio.TimeoutError as err:
raise ConfigEntryNotReady("AEMET OpenData API timed out") from err

weather_coordinator = WeatherUpdateCoordinator(hass, aemet)
await weather_coordinator.async_config_entry_first_refresh()
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/airzone/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
"documentation": "https://www.home-assistant.io/integrations/airzone",
"iot_class": "local_polling",
"loggers": ["aioairzone"],
"requirements": ["aioairzone==0.6.8"]
"requirements": ["aioairzone==0.6.9"]
}
4 changes: 2 additions & 2 deletions homeassistant/components/bluetooth/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"bleak-retry-connector==3.2.1",
"bluetooth-adapters==0.16.1",
"bluetooth-auto-recovery==1.2.3",
"bluetooth-data-tools==1.12.0",
"dbus-fast==2.11.1"
"bluetooth-data-tools==1.13.0",
"dbus-fast==2.12.0"
]
}
8 changes: 5 additions & 3 deletions homeassistant/components/calendar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ class CalendarEntity(Entity):

_entity_component_unrecorded_attributes = frozenset({"description"})

_alarm_unsubs: list[CALLBACK_TYPE] = []
_alarm_unsubs: list[CALLBACK_TYPE] | None = None

@property
def event(self) -> CalendarEvent | None:
Expand Down Expand Up @@ -528,6 +528,8 @@ def async_write_ha_state(self) -> None:
the current or upcoming event.
"""
super().async_write_ha_state()
if self._alarm_unsubs is None:
self._alarm_unsubs = []
_LOGGER.debug(
"Clearing %s alarms (%s)", self.entity_id, len(self._alarm_unsubs)
)
Expand Down Expand Up @@ -571,9 +573,9 @@ async def async_will_remove_from_hass(self) -> None:
To be extended by integrations.
"""
for unsub in self._alarm_unsubs:
for unsub in self._alarm_unsubs or ():
unsub()
self._alarm_unsubs.clear()
self._alarm_unsubs = None

async def async_get_events(
self,
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 @@ -5,5 +5,5 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/duotecno",
"iot_class": "local_push",
"requirements": ["pyDuotecno==2023.10.0"]
"requirements": ["pyDuotecno==2023.10.1"]
}
9 changes: 6 additions & 3 deletions homeassistant/components/esphome/bluetooth/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
BluetoothProxyFeature,
DeviceInfo,
)
from aioesphomeapi.connection import APIConnectionError, TimeoutAPIError
from aioesphomeapi.core import BluetoothGATTAPIError
from aioesphomeapi.core import (
APIConnectionError,
BluetoothGATTAPIError,
TimeoutAPIError,
)
from async_interrupt import interrupt
from bleak.backends.characteristic import BleakGATTCharacteristic
from bleak.backends.client import BaseBleakClient, NotifyCallback
Expand Down Expand Up @@ -389,8 +392,8 @@ async def disconnect(self) -> bool:
return await self._disconnect()

async def _disconnect(self) -> bool:
self._async_disconnected_cleanup()
await self._client.bluetooth_device_disconnect(self._address_as_int)
self._async_ble_device_disconnected()
await self._wait_for_free_connection_slot(DISCONNECT_TIMEOUT)
return True

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/esphome/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ async def async_start(self) -> None:
on_connect=self.on_connect,
on_disconnect=self.on_disconnect,
zeroconf_instance=self.zeroconf_instance,
name=self.host,
name=entry.data.get(CONF_DEVICE_NAME, self.host),
on_connect_error=self.on_connect_error,
)
self.reconnect_logic = reconnect_logic
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/esphome/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"loggers": ["aioesphomeapi", "noiseprotocol"],
"requirements": [
"async-interrupt==1.1.1",
"aioesphomeapi==17.0.1",
"bluetooth-data-tools==1.12.0",
"aioesphomeapi==18.0.7",
"bluetooth-data-tools==1.13.0",
"esphome-dashboard-api==1.2.3"
],
"zeroconf": ["_esphomelib._tcp.local."]
Expand Down
11 changes: 10 additions & 1 deletion homeassistant/components/esphome/voice_assistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
VoiceAssistantEventType.VOICE_ASSISTANT_TTS_END: PipelineEventType.TTS_END,
VoiceAssistantEventType.VOICE_ASSISTANT_WAKE_WORD_START: PipelineEventType.WAKE_WORD_START,
VoiceAssistantEventType.VOICE_ASSISTANT_WAKE_WORD_END: PipelineEventType.WAKE_WORD_END,
VoiceAssistantEventType.VOICE_ASSISTANT_STT_VAD_START: PipelineEventType.STT_VAD_START,
VoiceAssistantEventType.VOICE_ASSISTANT_STT_VAD_END: PipelineEventType.STT_VAD_END,
}
)

Expand Down Expand Up @@ -161,7 +163,7 @@ def _event_callback(self, event: PipelineEvent) -> None:
try:
event_type = _VOICE_ASSISTANT_EVENT_TYPES.from_hass(event.type)
except KeyError:
_LOGGER.warning("Received unknown pipeline event type: %s", event.type)
_LOGGER.debug("Received unknown pipeline event type: %s", event.type)
return

data_to_send = None
Expand Down Expand Up @@ -296,6 +298,10 @@ async def _send_tts(self, media_id: str) -> None:
if self.transport is None:
return

self.handle_event(
VoiceAssistantEventType.VOICE_ASSISTANT_TTS_STREAM_START, {}
)

_extension, audio_bytes = await tts.async_get_media_source_audio(
self.hass,
media_id,
Expand All @@ -321,4 +327,7 @@ async def _send_tts(self, media_id: str) -> None:
sample_offset += samples_in_chunk

finally:
self.handle_event(
VoiceAssistantEventType.VOICE_ASSISTANT_TTS_STREAM_END, {}
)
self._tts_done.set()
4 changes: 1 addition & 3 deletions homeassistant/components/google_maps/device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,7 @@ def _update_info(self, now=None):
)
_LOGGER.debug("%s < %s", last_seen, self._prev_seen[dev_id])
continue
if last_seen == self._prev_seen.get(dev_id, last_seen) and hasattr(
self, "success_init"
):
if last_seen == self._prev_seen.get(dev_id):
_LOGGER.debug(
"Ignoring %s update because timestamp "
"is the same as the last timestamp %s",
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/ld2410_ble/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/ld2410_ble",
"integration_type": "device",
"iot_class": "local_push",
"requirements": ["bluetooth-data-tools==1.12.0", "ld2410-ble==0.1.1"]
"requirements": ["bluetooth-data-tools==1.13.0", "ld2410-ble==0.1.1"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/led_ble/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
"dependencies": ["bluetooth_adapters"],
"documentation": "https://www.home-assistant.io/integrations/led_ble",
"iot_class": "local_polling",
"requirements": ["bluetooth-data-tools==1.12.0", "led-ble==1.0.1"]
"requirements": ["bluetooth-data-tools==1.13.0", "led-ble==1.0.1"]
}
4 changes: 2 additions & 2 deletions homeassistant/components/matter/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,9 @@ def _update_from_device(self) -> None:
self._attr_min_temp = DEFAULT_MIN_TEMP
# update max_temp
if self._attr_hvac_mode in (HVACMode.COOL, HVACMode.HEAT_COOL):
attribute = clusters.Thermostat.Attributes.AbsMaxHeatSetpointLimit
else:
attribute = clusters.Thermostat.Attributes.AbsMaxCoolSetpointLimit
else:
attribute = clusters.Thermostat.Attributes.AbsMaxHeatSetpointLimit
if (value := self._get_temperature_in_degrees(attribute)) is not None:
self._attr_max_temp = value
else:
Expand Down
8 changes: 7 additions & 1 deletion homeassistant/components/mqtt/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,13 @@ async def async_subscribe(
raise HomeAssistantError(
f"Cannot subscribe to topic '{topic}', MQTT is not enabled"
)
mqtt_data = get_mqtt_data(hass)
try:
mqtt_data = get_mqtt_data(hass)
except KeyError as ex:
raise HomeAssistantError(
f"Cannot subscribe to topic '{topic}', "
"make sure MQTT is set up correctly"
) from ex
async_remove = await mqtt_data.client.async_subscribe(
topic,
catch_log_exception(
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/nina/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/nina",
"iot_class": "cloud_polling",
"loggers": ["pynina"],
"requirements": ["PyNINA==0.3.2"]
"requirements": ["PyNINA==0.3.3"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/opower/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"documentation": "https://www.home-assistant.io/integrations/opower",
"iot_class": "cloud_polling",
"loggers": ["opower"],
"requirements": ["opower==0.0.35"]
"requirements": ["opower==0.0.36"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/private_ble_device/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"dependencies": ["bluetooth_adapters"],
"documentation": "https://www.home-assistant.io/integrations/private_ble_device",
"iot_class": "local_push",
"requirements": ["bluetooth-data-tools==1.12.0"]
"requirements": ["bluetooth-data-tools==1.13.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/rdw/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"integration_type": "service",
"iot_class": "cloud_polling",
"quality_scale": "platinum",
"requirements": ["vehicle==1.0.1"]
"requirements": ["vehicle==2.0.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/screenlogic/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
"documentation": "https://www.home-assistant.io/integrations/screenlogic",
"iot_class": "local_push",
"loggers": ["screenlogicpy"],
"requirements": ["screenlogicpy==0.9.2"]
"requirements": ["screenlogicpy==0.9.3"]
}
13 changes: 4 additions & 9 deletions homeassistant/components/spotify/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from __future__ import annotations

from asyncio import run_coroutine_threadsafe
import datetime as dt
from datetime import timedelta
import logging
from typing import Any
Expand All @@ -27,7 +26,7 @@
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util.dt import utc_from_timestamp
from homeassistant.util.dt import utcnow

from . import HomeAssistantSpotifyData
from .browse_media import async_browse_media_internal
Expand Down Expand Up @@ -199,13 +198,6 @@ def media_position(self) -> int | None:
return None
return self._currently_playing["progress_ms"] / 1000

@property
def media_position_updated_at(self) -> dt.datetime | None:
"""When was the position of the current playing media valid."""
if not self._currently_playing:
return None
return utc_from_timestamp(self._currently_playing["timestamp"] / 1000)

@property
def media_image_url(self) -> str | None:
"""Return the media image URL."""
Expand Down Expand Up @@ -413,6 +405,9 @@ def update(self) -> None:
additional_types=[MediaType.EPISODE]
)
self._currently_playing = current or {}
# Record the last updated time, because Spotify's timestamp property is unreliable
# and doesn't actually return the fetch time as is mentioned in the API description
self._attr_media_position_updated_at = utcnow() if current is not None else None

context = self._currently_playing.get("context") or {}

Expand Down
21 changes: 18 additions & 3 deletions homeassistant/components/unifi/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@
CONF_PORT,
CONF_USERNAME,
CONF_VERIFY_SSL,
Platform,
)
from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant, callback
from homeassistant.helpers import aiohttp_client, device_registry as dr
from homeassistant.helpers import (
aiohttp_client,
device_registry as dr,
entity_registry as er,
)
from homeassistant.helpers.device_registry import (
DeviceEntry,
DeviceEntryType,
Expand All @@ -33,6 +38,7 @@
async_dispatcher_send,
)
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.entity_registry import async_entries_for_config_entry
from homeassistant.helpers.event import async_call_later, async_track_time_interval
import homeassistant.util.dt as dt_util

Expand Down Expand Up @@ -131,7 +137,7 @@ def load_config_entry_options(self) -> None:
# Client control options

# Config entry option with list of clients to control network access.
self.option_block_clients = options.get(CONF_BLOCK_CLIENT, [])
self.option_block_clients: list[str] = options.get(CONF_BLOCK_CLIENT, [])
# Config entry option to control DPI restriction groups.
self.option_dpi_restrictions: bool = options.get(
CONF_DPI_RESTRICTIONS, DEFAULT_DPI_RESTRICTIONS
Expand Down Expand Up @@ -244,7 +250,16 @@ async def initialize(self) -> None:
assert self.config_entry.unique_id is not None
self.is_admin = self.api.sites[self.config_entry.unique_id].role == "admin"

for mac in self.option_block_clients:
# Restore device tracker clients that are not a part of active clients list.
macs: list[str] = []
entity_registry = er.async_get(self.hass)
for entry in async_entries_for_config_entry(
entity_registry, self.config_entry.entry_id
):
if entry.domain == Platform.DEVICE_TRACKER:
macs.append(entry.unique_id.split("-", 1)[0])

for mac in self.option_block_clients + macs:
if mac not in self.api.clients and mac in self.api.clients_all:
self.api.clients.process_raw([dict(self.api.clients_all[mac].raw)])

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/velbus/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"velbus-packet",
"velbus-protocol"
],
"requirements": ["velbus-aio==2023.2.0"],
"requirements": ["velbus-aio==2023.10.1"],
"usb": [
{
"vid": "10CF",
Expand Down
21 changes: 7 additions & 14 deletions homeassistant/components/velbus/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,18 @@ def __init__(
"""Initialize a sensor Velbus entity."""
super().__init__(channel)
self._is_counter: bool = counter
# define the unique id
if self._is_counter:
self._attr_unique_id = f"{self._attr_unique_id}-counter"
# define the name
if self._is_counter:
self._attr_device_class = SensorDeviceClass.ENERGY
self._attr_icon = "mdi:counter"
self._attr_name = f"{self._attr_name}-counter"
# define the device class
if self._is_counter:
self._attr_device_class = SensorDeviceClass.POWER
self._attr_state_class = SensorStateClass.TOTAL_INCREASING
self._attr_unique_id = f"{self._attr_unique_id}-counter"
elif channel.is_counter_channel():
self._attr_device_class = SensorDeviceClass.ENERGY
self._attr_device_class = SensorDeviceClass.POWER
self._attr_state_class = SensorStateClass.MEASUREMENT
elif channel.is_temperature():
self._attr_device_class = SensorDeviceClass.TEMPERATURE
# define the icon
if self._is_counter:
self._attr_icon = "mdi:counter"
# the state class
if self._is_counter:
self._attr_state_class = SensorStateClass.TOTAL_INCREASING
self._attr_state_class = SensorStateClass.MEASUREMENT
else:
self._attr_state_class = SensorStateClass.MEASUREMENT
# unit
Expand Down
6 changes: 1 addition & 5 deletions homeassistant/components/venstar/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,14 @@ def __init__(
super().__init__(coordinator, config)
self.entity_description = entity_description
self.sensor_name = sensor_name
self._attr_name = entity_description.name_fn(sensor_name)
self._config = config

@property
def unique_id(self):
"""Return the unique id."""
return f"{self._config.entry_id}_{self.sensor_name.replace(' ', '_')}_{self.entity_description.key}"

@property
def name(self):
"""Return the name of the device."""
return self.entity_description.name_fn(self.sensor_name)

@property
def native_value(self) -> int:
"""Return state of the sensor."""
Expand Down
Loading

0 comments on commit aa5c4d8

Please sign in to comment.