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
4 changes: 2 additions & 2 deletions CODEOWNERS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion homeassistant/components/actron_air/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
"integration_type": "hub",
"iot_class": "cloud_polling",
"quality_scale": "silver",
"requirements": ["actron-neo-api==0.5.6"]
"requirements": ["actron-neo-api==0.5.12"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/airos/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"integration_type": "device",
"iot_class": "local_polling",
"quality_scale": "platinum",
"requirements": ["airos==0.6.5"]
"requirements": ["airos==0.6.8"]
}
5 changes: 3 additions & 2 deletions homeassistant/components/gentex_homelink/manifest.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"domain": "gentex_homelink",
"name": "HomeLink",
"codeowners": ["@niaexa", "@ryanjones-gentex"],
"codeowners": ["@Gentex-Corporation/Homelink", "@rjones-gentex"],
"config_flow": true,
"dependencies": ["application_credentials"],
"documentation": "https://www.home-assistant.io/integrations/gentex_homelink",
"integration_type": "hub",
"iot_class": "cloud_push",
"quality_scale": "bronze",
"requirements": ["homelink-integration-api==0.0.1"]
"requirements": ["homelink-integration-api==0.0.5"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/home_connect/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@
"iot_class": "cloud_push",
"loggers": ["aiohomeconnect"],
"quality_scale": "platinum",
"requirements": ["aiohomeconnect==0.36.0"],
"requirements": ["aiohomeconnect==0.36.1"],
"zeroconf": ["_homeconnect._tcp.local."]
}
64 changes: 43 additions & 21 deletions homeassistant/components/homee/cover.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""The homee cover platform."""

from enum import Enum
import logging
from typing import TYPE_CHECKING, Any, cast

Expand All @@ -24,12 +25,6 @@

PARALLEL_UPDATES = 0

OPEN_CLOSE_ATTRIBUTES = [
AttributeType.OPEN_CLOSE,
AttributeType.SLAT_ROTATION_IMPULSE,
AttributeType.UP_DOWN,
]
POSITION_ATTRIBUTES = [AttributeType.POSITION, AttributeType.SHUTTER_SLAT_POSITION]
COVER_DEVICE_PROFILES = {
NodeProfile.GARAGE_DOOR_OPERATOR: CoverDeviceClass.GARAGE,
NodeProfile.ENTRANCE_GATE_OPERATOR: CoverDeviceClass.GATE,
Expand All @@ -43,6 +38,23 @@
]


class HomeeCoverState(float, Enum):
"""Open/closed states for covers in homee."""

OPEN = 0.0
CLOSED = 1.0
STOPPED = 2.0
OPENING = 3.0
CLOSING = 4.0


class HomeeSlatState(float, Enum):
"""Slat states for covers in homee."""

CLOSED = 1.0
OPEN = 2.0


def get_open_close_attribute(node: HomeeNode) -> HomeeAttribute | None:
"""Return the attribute used for opening/closing the cover."""
# We assume, that no device has UP_DOWN and OPEN_CLOSE, but only one of them.
Expand Down Expand Up @@ -187,9 +199,9 @@ def is_opening(self) -> bool | None:
"""Return the opening status of the cover."""
if self._open_close_attribute is not None:
return (
self._open_close_attribute.get_value() == 3
self._open_close_attribute.get_value() == HomeeCoverState.OPENING
if not self._open_close_attribute.is_reversed
else self._open_close_attribute.get_value() == 4
else self._open_close_attribute.get_value() == HomeeCoverState.CLOSING
)

return None
Expand All @@ -199,9 +211,9 @@ def is_closing(self) -> bool | None:
"""Return the closing status of the cover."""
if self._open_close_attribute is not None:
return (
self._open_close_attribute.get_value() == 4
self._open_close_attribute.get_value() == HomeeCoverState.CLOSING
if not self._open_close_attribute.is_reversed
else self._open_close_attribute.get_value() == 3
else self._open_close_attribute.get_value() == HomeeCoverState.OPENING
)

return None
Expand All @@ -216,9 +228,9 @@ def is_closed(self) -> bool:

if self._open_close_attribute is not None:
if not self._open_close_attribute.is_reversed:
return self._open_close_attribute.get_value() == 1
return self._open_close_attribute.get_value() == HomeeCoverState.CLOSED

return self._open_close_attribute.get_value() == 0
return self._open_close_attribute.get_value() == HomeeCoverState.OPEN

# If none of the above is present, it will be a slat only cover.
attribute = self._node.get_attribute_by_type(
Expand All @@ -235,17 +247,25 @@ async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the cover."""
assert self._open_close_attribute is not None
if not self._open_close_attribute.is_reversed:
await self.async_set_homee_value(self._open_close_attribute, 0)
await self.async_set_homee_value(
self._open_close_attribute, HomeeCoverState.OPEN
)
else:
await self.async_set_homee_value(self._open_close_attribute, 1)
await self.async_set_homee_value(
self._open_close_attribute, HomeeCoverState.CLOSED
)

async def async_close_cover(self, **kwargs: Any) -> None:
"""Close cover."""
assert self._open_close_attribute is not None
if not self._open_close_attribute.is_reversed:
await self.async_set_homee_value(self._open_close_attribute, 1)
await self.async_set_homee_value(
self._open_close_attribute, HomeeCoverState.CLOSED
)
else:
await self.async_set_homee_value(self._open_close_attribute, 0)
await self.async_set_homee_value(
self._open_close_attribute, HomeeCoverState.OPEN
)

async def async_set_cover_position(self, **kwargs: Any) -> None:
"""Move the cover to a specific position."""
Expand All @@ -265,7 +285,9 @@ async def async_set_cover_position(self, **kwargs: Any) -> None:
async def async_stop_cover(self, **kwargs: Any) -> None:
"""Stop the cover."""
if self._open_close_attribute is not None:
await self.async_set_homee_value(self._open_close_attribute, 2)
await self.async_set_homee_value(
self._open_close_attribute, HomeeCoverState.STOPPED
)

async def async_open_cover_tilt(self, **kwargs: Any) -> None:
"""Open the cover tilt."""
Expand All @@ -275,9 +297,9 @@ async def async_open_cover_tilt(self, **kwargs: Any) -> None:
)
) is not None:
if not slat_attribute.is_reversed:
await self.async_set_homee_value(slat_attribute, 2)
await self.async_set_homee_value(slat_attribute, HomeeSlatState.OPEN)
else:
await self.async_set_homee_value(slat_attribute, 1)
await self.async_set_homee_value(slat_attribute, HomeeSlatState.CLOSED)

async def async_close_cover_tilt(self, **kwargs: Any) -> None:
"""Close the cover tilt."""
Expand All @@ -287,9 +309,9 @@ async def async_close_cover_tilt(self, **kwargs: Any) -> None:
)
) is not None:
if not slat_attribute.is_reversed:
await self.async_set_homee_value(slat_attribute, 1)
await self.async_set_homee_value(slat_attribute, HomeeSlatState.CLOSED)
else:
await self.async_set_homee_value(slat_attribute, 2)
await self.async_set_homee_value(slat_attribute, HomeeSlatState.OPEN)

async def async_set_cover_tilt_position(self, **kwargs: Any) -> None:
"""Move the cover tilt to a specific position."""
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/husqvarna_automower/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"iot_class": "cloud_push",
"loggers": ["aioautomower"],
"quality_scale": "silver",
"requirements": ["aioautomower==2.7.5"]
"requirements": ["aioautomower==2.7.6"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/itach/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
"documentation": "https://www.home-assistant.io/integrations/itach",
"iot_class": "assumed_state",
"quality_scale": "legacy",
"requirements": ["pyitachip2ir==0.0.7"]
"requirements": ["pyitachip2ir2==0.0.8"]
}
18 changes: 15 additions & 3 deletions homeassistant/components/opendisplay/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
OpenDisplayError,
)

from homeassistant.components.bluetooth import async_ble_device_from_address
from homeassistant.components.bluetooth import (
BluetoothReachabilityIntent,
async_address_reachability_diagnostics,
async_ble_device_from_address,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
Expand Down Expand Up @@ -83,9 +87,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: OpenDisplayConfigEntry)
ble_device = async_ble_device_from_address(hass, address, connectable=True)
if ble_device is None:
raise ConfigEntryNotReady(
f"Could not find OpenDisplay device with address {address}"
translation_domain=DOMAIN,
translation_key="device_not_found",
translation_placeholders={
"address": address,
"reason": async_address_reachability_diagnostics(
hass,
address.upper(),
BluetoothReachabilityIntent.CONNECTION,
),
},
)

encryption_key = _get_encryption_key(entry)

try:
Expand Down
17 changes: 14 additions & 3 deletions homeassistant/components/opendisplay/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
from PIL import Image as PILImage, ImageOps
import voluptuous as vol

from homeassistant.components.bluetooth import async_ble_device_from_address
from homeassistant.components.bluetooth import (
BluetoothReachabilityIntent,
async_address_reachability_diagnostics,
async_ble_device_from_address,
)
from homeassistant.components.http.auth import async_sign_path
from homeassistant.components.media_source import async_resolve_media
from homeassistant.config_entries import ConfigEntryState
Expand Down Expand Up @@ -108,7 +112,7 @@ def _get_entry_for_device(call: ServiceCall) -> OpenDisplayConfigEntry:
if entry is None or entry.state is not ConfigEntryState.LOADED:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="device_not_found",
translation_key="config_entry_not_found",
translation_placeholders={"address": mac_address},
)

Expand Down Expand Up @@ -171,7 +175,14 @@ async def _async_upload_image(call: ServiceCall) -> None:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="device_not_found",
translation_placeholders={"address": address},
translation_placeholders={
"address": address,
"reason": async_address_reachability_diagnostics(
call.hass,
address.upper(),
BluetoothReachabilityIntent.CONNECTION,
),
},
)

current = asyncio.current_task()
Expand Down
5 changes: 4 additions & 1 deletion homeassistant/components/opendisplay/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,11 @@
"authentication_error": {
"message": "Authentication failed. Please update the encryption key."
},
"config_entry_not_found": {
"message": "Config entry not found: `{address}`"
},
"device_not_found": {
"message": "Could not find Bluetooth device with address `{address}`."
"message": "Could not find Bluetooth device with address `{address}`. Reason: {reason}"
},
"invalid_device_id": {
"message": "Device `{device_id}` is not a valid OpenDisplay device."
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/openevse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .const import DOMAIN
from .coordinator import OpenEVSEConfigEntry, OpenEVSEDataUpdateCoordinator

PLATFORMS = [Platform.NUMBER, Platform.SENSOR]
PLATFORMS = [Platform.BINARY_SENSOR, Platform.NUMBER, Platform.SENSOR]


async def async_setup_entry(hass: HomeAssistant, entry: OpenEVSEConfigEntry) -> bool:
Expand Down
Loading
Loading