Skip to content

Commit

Permalink
2024.1.3 (#107883)
Browse files Browse the repository at this point in the history
  • Loading branch information
frenck authored Jan 12, 2024
2 parents 4eddbe7 + 9c6cb53 commit 99ee57a
Show file tree
Hide file tree
Showing 105 changed files with 1,612 additions and 263 deletions.
2 changes: 1 addition & 1 deletion CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -1550,7 +1550,7 @@ build.json @home-assistant/supervisor
/tests/components/zodiac/ @JulienTant
/homeassistant/components/zone/ @home-assistant/core
/tests/components/zone/ @home-assistant/core
/homeassistant/components/zoneminder/ @rohankapoorcom
/homeassistant/components/zoneminder/ @rohankapoorcom @nabbi
/homeassistant/components/zwave_js/ @home-assistant/z-wave
/tests/components/zwave_js/ @home-assistant/z-wave
/homeassistant/components/zwave_me/ @lawfulchaos @Z-Wave-Me @PoltoS
Expand Down
9 changes: 5 additions & 4 deletions homeassistant/components/alexa/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
from homeassistant.helpers.storage import Store
from homeassistant.util import dt as dt_util

from .const import STORAGE_ACCESS_TOKEN, STORAGE_REFRESH_TOKEN
from .diagnostics import async_redact_lwa_params

_LOGGER = logging.getLogger(__name__)

LWA_TOKEN_URI = "https://api.amazon.com/auth/o2/token"
Expand All @@ -24,8 +27,6 @@
STORAGE_KEY = "alexa_auth"
STORAGE_VERSION = 1
STORAGE_EXPIRE_TIME = "expire_time"
STORAGE_ACCESS_TOKEN = "access_token"
STORAGE_REFRESH_TOKEN = "refresh_token"


class Auth:
Expand Down Expand Up @@ -56,7 +57,7 @@ async def async_do_auth(self, accept_grant_code: str) -> str | None:
}
_LOGGER.debug(
"Calling LWA to get the access token (first time), with: %s",
json.dumps(lwa_params),
json.dumps(async_redact_lwa_params(lwa_params)),
)

return await self._async_request_new_token(lwa_params)
Expand Down Expand Up @@ -133,7 +134,7 @@ async def _async_request_new_token(self, lwa_params: dict[str, str]) -> str | No
return None

response_json = await response.json()
_LOGGER.debug("LWA response body : %s", response_json)
_LOGGER.debug("LWA response body : %s", async_redact_lwa_params(response_json))

access_token: str = response_json["access_token"]
refresh_token: str = response_json["refresh_token"]
Expand Down
16 changes: 10 additions & 6 deletions homeassistant/components/alexa/capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -1112,13 +1112,17 @@ def properties_supported(self) -> list[dict[str, str]]:
"""Return what properties this entity supports."""
properties = [{"name": "thermostatMode"}]
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
if supported & climate.ClimateEntityFeature.TARGET_TEMPERATURE:
properties.append({"name": "targetSetpoint"})
if supported & water_heater.WaterHeaterEntityFeature.TARGET_TEMPERATURE:
if self.entity.domain == climate.DOMAIN:
if supported & climate.ClimateEntityFeature.TARGET_TEMPERATURE_RANGE:
properties.append({"name": "lowerSetpoint"})
properties.append({"name": "upperSetpoint"})
if supported & climate.ClimateEntityFeature.TARGET_TEMPERATURE:
properties.append({"name": "targetSetpoint"})
elif (
self.entity.domain == water_heater.DOMAIN
and supported & water_heater.WaterHeaterEntityFeature.TARGET_TEMPERATURE
):
properties.append({"name": "targetSetpoint"})
if supported & climate.ClimateEntityFeature.TARGET_TEMPERATURE_RANGE:
properties.append({"name": "lowerSetpoint"})
properties.append({"name": "upperSetpoint"})
return properties

def properties_proactively_reported(self) -> bool:
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/alexa/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@
# we add PRESET_MODE_NA if a fan / humidifier has only one preset_mode
PRESET_MODE_NA = "-"

STORAGE_ACCESS_TOKEN = "access_token"
STORAGE_REFRESH_TOKEN = "refresh_token"


class Cause:
"""Possible causes for property changes.
Expand Down
34 changes: 34 additions & 0 deletions homeassistant/components/alexa/diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Diagnostics helpers for Alexa."""

from __future__ import annotations

from collections.abc import Mapping
from typing import Any

from homeassistant.components.diagnostics import async_redact_data
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
from homeassistant.core import callback

STORAGE_ACCESS_TOKEN = "access_token"
STORAGE_REFRESH_TOKEN = "refresh_token"

TO_REDACT_LWA = {
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
STORAGE_ACCESS_TOKEN,
STORAGE_REFRESH_TOKEN,
}

TO_REDACT_AUTH = {"correlationToken", "token"}


@callback
def async_redact_lwa_params(lwa_params: dict[str, str]) -> dict[str, str]:
"""Redact lwa_params."""
return async_redact_data(lwa_params, TO_REDACT_LWA)


@callback
def async_redact_auth_data(mapping: Mapping[Any, Any]) -> dict[str, str]:
"""React auth data."""
return async_redact_data(mapping, TO_REDACT_AUTH)
1 change: 0 additions & 1 deletion homeassistant/components/alexa/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ async def async_api_accept_grant(
Async friendly.
"""
auth_code: str = directive.payload["grant"]["code"]
_LOGGER.debug("AcceptGrant code: %s", auth_code)

if config.supports_auth:
await config.async_accept_grant(auth_code)
Expand Down
14 changes: 12 additions & 2 deletions homeassistant/components/alexa/smart_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
CONF_LOCALE,
EVENT_ALEXA_SMART_HOME,
)
from .diagnostics import async_redact_auth_data
from .errors import AlexaBridgeUnreachableError, AlexaError
from .handlers import HANDLERS
from .state_report import AlexaDirective
Expand Down Expand Up @@ -149,12 +150,21 @@ async def post(self, request: HomeAssistantRequest) -> web.Response | bytes:
user: User = request["hass_user"]
message: dict[str, Any] = await request.json()

_LOGGER.debug("Received Alexa Smart Home request: %s", message)
if _LOGGER.isEnabledFor(logging.DEBUG):
_LOGGER.debug(
"Received Alexa Smart Home request: %s",
async_redact_auth_data(message),
)

response = await async_handle_message(
hass, self.smart_home_config, message, context=core.Context(user_id=user.id)
)
_LOGGER.debug("Sending Alexa Smart Home response: %s", response)
if _LOGGER.isEnabledFor(logging.DEBUG):
_LOGGER.debug(
"Sending Alexa Smart Home response: %s",
async_redact_auth_data(response),
)

return b"" if response is None else self.json(response)


Expand Down
11 changes: 9 additions & 2 deletions homeassistant/components/alexa/state_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
DOMAIN,
Cause,
)
from .diagnostics import async_redact_auth_data
from .entities import ENTITY_ADAPTERS, AlexaEntity, generate_alexa_id
from .errors import AlexaInvalidEndpointError, NoTokenAvailable, RequireRelink

Expand All @@ -43,6 +44,8 @@
_LOGGER = logging.getLogger(__name__)
DEFAULT_TIMEOUT = 10

TO_REDACT = {"correlationToken", "token"}


class AlexaDirective:
"""An incoming Alexa directive."""
Expand Down Expand Up @@ -379,7 +382,9 @@ async def async_send_changereport_message(
response_text = await response.text()

if _LOGGER.isEnabledFor(logging.DEBUG):
_LOGGER.debug("Sent: %s", json.dumps(message_serialized))
_LOGGER.debug(
"Sent: %s", json.dumps(async_redact_auth_data(message_serialized))
)
_LOGGER.debug("Received (%s): %s", response.status, response_text)

if response.status == HTTPStatus.ACCEPTED:
Expand Down Expand Up @@ -533,7 +538,9 @@ async def async_send_doorbell_event_message(
response_text = await response.text()

if _LOGGER.isEnabledFor(logging.DEBUG):
_LOGGER.debug("Sent: %s", json.dumps(message_serialized))
_LOGGER.debug(
"Sent: %s", json.dumps(async_redact_auth_data(message_serialized))
)
_LOGGER.debug("Received (%s): %s", response.status, response_text)

if response.status == HTTPStatus.ACCEPTED:
Expand Down
39 changes: 39 additions & 0 deletions homeassistant/components/aosmith/diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Diagnostics support for A. O. Smith."""
from __future__ import annotations

from typing import Any

from homeassistant.components.diagnostics import async_redact_data
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant

from . import AOSmithData
from .const import DOMAIN

TO_REDACT = {
"address",
"city",
"contactId",
"dsn",
"email",
"firstName",
"heaterSsid",
"id",
"lastName",
"phone",
"postalCode",
"registeredOwner",
"serial",
"ssid",
"state",
}


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

all_device_info = await data.client.get_all_device_info()
return async_redact_data(all_device_info, TO_REDACT)
2 changes: 1 addition & 1 deletion homeassistant/components/aosmith/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/aosmith",
"iot_class": "cloud_polling",
"requirements": ["py-aosmith==1.0.1"]
"requirements": ["py-aosmith==1.0.4"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/blink/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = 30
SCAN_INTERVAL = 300


class BlinkUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/blink/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/blink",
"iot_class": "cloud_polling",
"loggers": ["blinkpy"],
"requirements": ["blinkpy==0.22.4"]
"requirements": ["blinkpy==0.22.5"]
}
4 changes: 2 additions & 2 deletions homeassistant/components/bluetooth/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
"bleak==0.21.1",
"bleak-retry-connector==3.4.0",
"bluetooth-adapters==0.16.2",
"bluetooth-auto-recovery==1.2.3",
"bluetooth-auto-recovery==1.3.0",
"bluetooth-data-tools==1.19.0",
"dbus-fast==2.21.0",
"habluetooth==2.0.2"
"habluetooth==2.1.0"
]
}
20 changes: 11 additions & 9 deletions homeassistant/components/cloud/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,22 +291,14 @@ async def async_startup_repairs(_: datetime) -> None:
}

async def _on_start() -> None:
"""Discover platforms."""
"""Handle cloud started after login."""
nonlocal loaded

# Prevent multiple discovery
if loaded:
return
loaded = True

tts_info = {"platform_loaded": tts_platform_loaded}

await async_load_platform(hass, Platform.TTS, DOMAIN, tts_info, config)
await tts_platform_loaded.wait()

# The config entry should be loaded after the legacy tts platform is loaded
# to make sure that the tts integration is setup before we try to migrate
# old assist pipelines in the cloud stt entity.
await hass.config_entries.flow.async_init(DOMAIN, context={"source": "system"})

async def _on_connect() -> None:
Expand Down Expand Up @@ -335,6 +327,16 @@ async def _on_initialized() -> None:

account_link.async_setup(hass)

hass.async_create_task(
async_load_platform(
hass,
Platform.TTS,
DOMAIN,
{"platform_loaded": tts_platform_loaded},
config,
)
)

async_call_later(
hass=hass,
delay=timedelta(hours=STARTUP_REPAIR_DELAY),
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/comelit/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class ComelitConfigFlow(ConfigFlow, domain=DOMAIN):
_reauth_entry: ConfigEntry | None
_reauth_host: str
_reauth_port: int
_reauth_type: str

async def async_step_user(
self, user_input: dict[str, Any] | None = None
Expand Down Expand Up @@ -109,6 +110,7 @@ async def async_step_reauth(self, entry_data: Mapping[str, Any]) -> FlowResult:
)
self._reauth_host = entry_data[CONF_HOST]
self._reauth_port = entry_data.get(CONF_PORT, DEFAULT_PORT)
self._reauth_type = entry_data.get(CONF_TYPE, BRIDGE)

self.context["title_placeholders"] = {"host": self._reauth_host}
return await self.async_step_reauth_confirm()
Expand All @@ -127,6 +129,7 @@ async def async_step_reauth_confirm(
{
CONF_HOST: self._reauth_host,
CONF_PORT: self._reauth_port,
CONF_TYPE: self._reauth_type,
}
| user_input,
)
Expand All @@ -144,6 +147,7 @@ async def async_step_reauth_confirm(
CONF_HOST: self._reauth_host,
CONF_PORT: self._reauth_port,
CONF_PIN: user_input[CONF_PIN],
CONF_TYPE: self._reauth_type,
},
)
self.hass.async_create_task(
Expand Down
8 changes: 2 additions & 6 deletions homeassistant/components/comelit/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,11 @@ async def _async_update_data(self) -> dict[str, Any]:
try:
await self.api.login()
return await self._async_update_system_data()
except exceptions.CannotConnect as err:
_LOGGER.warning("Connection error for %s", self._host)
await self.api.close()
raise UpdateFailed(f"Error fetching data: {repr(err)}") from err
except (exceptions.CannotConnect, exceptions.CannotRetrieveData) as err:
raise UpdateFailed(repr(err)) from err
except exceptions.CannotAuthenticate:
raise ConfigEntryAuthFailed

return {}

@abstractmethod
async def _async_update_system_data(self) -> dict[str, Any]:
"""Class method for updating data."""
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/comelit/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/comelit",
"iot_class": "local_polling",
"loggers": ["aiocomelit"],
"requirements": ["aiocomelit==0.7.0"]
"requirements": ["aiocomelit==0.7.3"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/cover/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ async def async_toggle_tilt(self, **kwargs: Any) -> None:
def _get_toggle_function(
self, fns: dict[str, Callable[_P, _R]]
) -> Callable[_P, _R]:
if CoverEntityFeature.STOP | self.supported_features and (
if self.supported_features & CoverEntityFeature.STOP and (
self.is_closing or self.is_opening
):
return fns["stop"]
Expand Down
12 changes: 11 additions & 1 deletion homeassistant/components/enphase_envoy/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,10 +479,20 @@ def __init__(
)

@property
def native_value(self) -> datetime.datetime | float:
def native_value(self) -> datetime.datetime | float | None:
"""Return the state of the sensor."""
inverters = self.data.inverters
assert inverters is not None
# Some envoy fw versions return an empty inverter array every 4 hours when
# no production is taking place. Prevent collection failure due to this
# as other data seems fine. Inverters will show unknown during this cycle.
if self._serial_number not in inverters:
_LOGGER.debug(
"Inverter %s not in returned inverters array (size: %s)",
self._serial_number,
len(inverters),
)
return None
return self.entity_description.value_fn(inverters[self._serial_number])


Expand Down
Loading

0 comments on commit 99ee57a

Please sign in to comment.