Skip to content

Commit

Permalink
Merge pull request #64317 from home-assistant/rc
Browse files Browse the repository at this point in the history
  • Loading branch information
balloob committed Jan 18, 2022
2 parents b6f4326 + c312654 commit 7887f23
Show file tree
Hide file tree
Showing 36 changed files with 2,011 additions and 226 deletions.
27 changes: 25 additions & 2 deletions homeassistant/components/august/__init__.py
Expand Up @@ -138,6 +138,17 @@ async def async_setup(self):
pubnub.subscribe(self.async_pubnub_message)
self._pubnub_unsub = async_create_pubnub(user_data["UserID"], pubnub)

if self._locks_by_id:
tasks = []
for lock_id in self._locks_by_id:
detail = self._device_detail_by_id[lock_id]
tasks.append(
self.async_status_async(
lock_id, bool(detail.bridge and detail.bridge.hyper_bridge)
)
)
await asyncio.gather(*tasks)

@callback
def async_pubnub_message(self, device_id, date_time, message):
"""Process a pubnub message."""
Expand Down Expand Up @@ -245,13 +256,24 @@ async def async_lock(self, device_id):
device_id,
)

async def async_lock_async(self, device_id):
async def async_status_async(self, device_id, hyper_bridge):
"""Request status of the the device but do not wait for a response since it will come via pubnub."""
return await self._async_call_api_op_requires_bridge(
device_id,
self._api.async_status_async,
self._august_gateway.access_token,
device_id,
hyper_bridge,
)

async def async_lock_async(self, device_id, hyper_bridge):
"""Lock the device but do not wait for a response since it will come via pubnub."""
return await self._async_call_api_op_requires_bridge(
device_id,
self._api.async_lock_async,
self._august_gateway.access_token,
device_id,
hyper_bridge,
)

async def async_unlock(self, device_id):
Expand All @@ -263,13 +285,14 @@ async def async_unlock(self, device_id):
device_id,
)

async def async_unlock_async(self, device_id):
async def async_unlock_async(self, device_id, hyper_bridge):
"""Unlock the device but do not wait for a response since it will come via pubnub."""
return await self._async_call_api_op_requires_bridge(
device_id,
self._api.async_unlock_async,
self._august_gateway.access_token,
device_id,
hyper_bridge,
)

async def _async_call_api_op_requires_bridge(
Expand Down
9 changes: 7 additions & 2 deletions homeassistant/components/august/lock.py
Expand Up @@ -39,17 +39,22 @@ def __init__(self, data, device):
self._attr_unique_id = f"{self._device_id:s}_lock"
self._update_from_data()

@property
def _hyper_bridge(self):
"""Check if the lock has a paired hyper bridge."""
return bool(self._detail.bridge and self._detail.bridge.hyper_bridge)

async def async_lock(self, **kwargs):
"""Lock the device."""
if self._data.activity_stream.pubnub.connected:
await self._data.async_lock_async(self._device_id)
await self._data.async_lock_async(self._device_id, self._hyper_bridge)
return
await self._call_lock_operation(self._data.async_lock)

async def async_unlock(self, **kwargs):
"""Unlock the device."""
if self._data.activity_stream.pubnub.connected:
await self._data.async_unlock_async(self._device_id)
await self._data.async_unlock_async(self._device_id, self._hyper_bridge)
return
await self._call_lock_operation(self._data.async_unlock)

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/august/manifest.json
Expand Up @@ -2,7 +2,7 @@
"domain": "august",
"name": "August",
"documentation": "https://www.home-assistant.io/integrations/august",
"requirements": ["yalexs==1.1.17"],
"requirements": ["yalexs==1.1.19"],
"codeowners": ["@bdraco"],
"dhcp": [
{
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/bmw_connected_drive/manifest.json
Expand Up @@ -2,7 +2,7 @@
"domain": "bmw_connected_drive",
"name": "BMW Connected Drive",
"documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive",
"requirements": ["bimmer_connected==0.8.7"],
"requirements": ["bimmer_connected==0.8.10"],
"codeowners": ["@gerard33", "@rikroe"],
"config_flow": true,
"iot_class": "cloud_polling"
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/dlna_dmr/config_flow.py
Expand Up @@ -474,8 +474,8 @@ def _is_ignored_device(discovery_info: ssdp.SsdpServiceInfo) -> bool:
# Special cases for devices with other discovery methods (e.g. mDNS), or
# that advertise multiple unrelated (sent in separate discovery packets)
# UPnP devices.
manufacturer = discovery_info.upnp.get(ssdp.ATTR_UPNP_MANUFACTURER, "").lower()
model = discovery_info.upnp.get(ssdp.ATTR_UPNP_MODEL_NAME, "").lower()
manufacturer = (discovery_info.upnp.get(ssdp.ATTR_UPNP_MANUFACTURER) or "").lower()
model = (discovery_info.upnp.get(ssdp.ATTR_UPNP_MODEL_NAME) or "").lower()

if manufacturer.startswith("xbmc") or model == "kodi":
# kodi
Expand Down
32 changes: 23 additions & 9 deletions homeassistant/components/flux_led/light.py
Expand Up @@ -71,7 +71,14 @@
TRANSITION_STROBE,
)
from .entity import FluxOnOffEntity
from .util import _effect_brightness, _flux_color_mode_to_hass, _hass_color_modes
from .util import (
_effect_brightness,
_flux_color_mode_to_hass,
_hass_color_modes,
_min_rgb_brightness,
_min_rgbw_brightness,
_min_rgbwc_brightness,
)

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -313,13 +320,13 @@ def _async_brightness(self, **kwargs: Any) -> int:
"""Determine brightness from kwargs or current value."""
if (brightness := kwargs.get(ATTR_BRIGHTNESS)) is None:
brightness = self.brightness
if not brightness:
# If the brightness was previously 0, the light
# will not turn on unless brightness is at least 1
# If the device was on and brightness was not
# set, it means it was masked by an effect
brightness = 255 if self.is_on else 1
return brightness
# If the brightness was previously 0, the light
# will not turn on unless brightness is at least 1
#
# We previously had a problem with the brightness
# sometimes reporting as 0 when an effect was in progress,
# however this has since been resolved in the upstream library
return max(1, brightness)

async def _async_set_mode(self, **kwargs: Any) -> None:
"""Set an effect or color mode."""
Expand Down Expand Up @@ -348,20 +355,27 @@ async def _async_set_mode(self, **kwargs: Any) -> None:
return
# Handle switch to RGB Color Mode
if rgb := kwargs.get(ATTR_RGB_COLOR):
if not self._device.requires_turn_on:
rgb = _min_rgb_brightness(rgb)
red, green, blue = rgb
await self._device.async_set_levels(red, green, blue, brightness=brightness)
return
# Handle switch to RGBW Color Mode
if rgbw := kwargs.get(ATTR_RGBW_COLOR):
if ATTR_BRIGHTNESS in kwargs:
rgbw = rgbw_brightness(rgbw, brightness)
if not self._device.requires_turn_on:
rgbw = _min_rgbw_brightness(rgbw)
await self._device.async_set_levels(*rgbw)
return
# Handle switch to RGBWW Color Mode
if rgbcw := kwargs.get(ATTR_RGBWW_COLOR):
if ATTR_BRIGHTNESS in kwargs:
rgbcw = rgbcw_brightness(kwargs[ATTR_RGBWW_COLOR], brightness)
await self._device.async_set_levels(*rgbcw_to_rgbwc(rgbcw))
rgbwc = rgbcw_to_rgbwc(rgbcw)
if not self._device.requires_turn_on:
rgbwc = _min_rgbwc_brightness(rgbwc)
await self._device.async_set_levels(*rgbwc)
return
if (white := kwargs.get(ATTR_WHITE)) is not None:
await self._device.async_set_levels(w=white)
Expand Down
65 changes: 32 additions & 33 deletions homeassistant/components/flux_led/manifest.json
Expand Up @@ -3,42 +3,41 @@
"name": "Flux LED/MagicHome",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/flux_led",
"requirements": ["flux_led==0.27.45"],
"requirements": ["flux_led==0.28.4"],
"quality_scale": "platinum",
"codeowners": ["@icemanch"],
"iot_class": "local_push",
"dhcp": [
{
"macaddress": "18B905*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "249494*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "7CB94C*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "B4E842*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "F0FE6B*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "8CCE4E*",
"hostname": "lwip*"
},
{
"hostname": "zengge_[0-9a-f][0-9a-f]_*"
},
{
"macaddress": "C82E47*",
"hostname": "sta*"
}
{
"macaddress": "18B905*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "249494*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "7CB94C*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "B4E842*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "F0FE6B*",
"hostname": "[ba][lk]*"
},
{
"macaddress": "8CCE4E*",
"hostname": "lwip*"
},
{
"hostname": "zengge_[0-9a-f][0-9a-f]_*"
},
{
"macaddress": "C82E47*",
"hostname": "sta*"
}
]
}

23 changes: 23 additions & 0 deletions homeassistant/components/flux_led/util.py
Expand Up @@ -34,3 +34,26 @@ def _flux_color_mode_to_hass(
def _effect_brightness(brightness: int) -> int:
"""Convert hass brightness to effect brightness."""
return round(brightness / 255 * 100)


def _min_rgb_brightness(rgb: tuple[int, int, int]) -> tuple[int, int, int]:
"""Ensure the RGB value will not turn off the device from a turn on command."""
if all(byte == 0 for byte in rgb):
return (1, 1, 1)
return rgb


def _min_rgbw_brightness(rgbw: tuple[int, int, int, int]) -> tuple[int, int, int, int]:
"""Ensure the RGBW value will not turn off the device from a turn on command."""
if all(byte == 0 for byte in rgbw):
return (1, 1, 1, 0)
return rgbw


def _min_rgbwc_brightness(
rgbwc: tuple[int, int, int, int, int]
) -> tuple[int, int, int, int, int]:
"""Ensure the RGBWC value will not turn off the device from a turn on command."""
if all(byte == 0 for byte in rgbwc):
return (1, 1, 1, 0, 0)
return rgbwc
5 changes: 3 additions & 2 deletions homeassistant/components/homekit/__init__.py
Expand Up @@ -2,6 +2,7 @@
from __future__ import annotations

import asyncio
from copy import deepcopy
import ipaddress
import logging
import os
Expand Down Expand Up @@ -352,8 +353,8 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry):

@callback
def _async_import_options_from_data_if_missing(hass: HomeAssistant, entry: ConfigEntry):
options = dict(entry.options)
data = dict(entry.data)
options = deepcopy(dict(entry.options))
data = deepcopy(dict(entry.data))
modified = False
for importable_option in CONFIG_OPTIONS:
if importable_option not in entry.options and importable_option in entry.data:
Expand Down
8 changes: 5 additions & 3 deletions homeassistant/components/homekit/config_flow.py
Expand Up @@ -2,9 +2,11 @@
from __future__ import annotations

import asyncio
from copy import deepcopy
import random
import re
import string
from typing import Final

import voluptuous as vol

Expand Down Expand Up @@ -116,7 +118,7 @@
"water_heater",
]

_EMPTY_ENTITY_FILTER = {
_EMPTY_ENTITY_FILTER: Final = {
CONF_INCLUDE_DOMAINS: [],
CONF_EXCLUDE_DOMAINS: [],
CONF_INCLUDE_ENTITIES: [],
Expand Down Expand Up @@ -151,7 +153,7 @@ def __init__(self) -> None:
async def async_step_user(self, user_input=None):
"""Choose specific domains in bridge mode."""
if user_input is not None:
entity_filter = _EMPTY_ENTITY_FILTER.copy()
entity_filter = deepcopy(_EMPTY_ENTITY_FILTER)
entity_filter[CONF_INCLUDE_DOMAINS] = user_input[CONF_INCLUDE_DOMAINS]
self.hk_data[CONF_FILTER] = entity_filter
return await self.async_step_pairing()
Expand Down Expand Up @@ -492,7 +494,7 @@ async def async_step_init(self, user_input=None):
self.hk_options.update(user_input)
return await self.async_step_include_exclude()

self.hk_options = dict(self.config_entry.options)
self.hk_options = deepcopy(dict(self.config_entry.options))
entity_filter = self.hk_options.get(CONF_FILTER, {})
homekit_mode = self.hk_options.get(CONF_HOMEKIT_MODE, DEFAULT_HOMEKIT_MODE)
domains = entity_filter.get(CONF_INCLUDE_DOMAINS, [])
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/homekit/manifest.json
Expand Up @@ -3,7 +3,7 @@
"name": "HomeKit",
"documentation": "https://www.home-assistant.io/integrations/homekit",
"requirements": [
"HAP-python==4.3.0",
"HAP-python==4.4.0",
"fnvhash==0.1.0",
"PyQRCode==1.2.1",
"base36==0.1.1"
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/homekit/type_thermostats.py
Expand Up @@ -174,6 +174,7 @@ def __init__(self, *args):
self.char_target_heat_cool.override_properties(
valid_values=self.hc_hass_to_homekit
)
self.char_target_heat_cool.allow_invalid_client_values = True
# Current and target temperature characteristics

self.char_current_temp = serv_thermostat.configure_char(
Expand Down Expand Up @@ -252,7 +253,6 @@ def _set_chars(self, char_values):

hvac_mode = state.state
homekit_hvac_mode = HC_HASS_TO_HOMEKIT[hvac_mode]

# Homekit will reset the mode when VIEWING the temp
# Ignore it if its the same mode
if (
Expand Down Expand Up @@ -282,7 +282,7 @@ def _set_chars(self, char_values):
target_hc,
hc_fallback,
)
target_hc = hc_fallback
self.char_target_heat_cool.value = target_hc = hc_fallback
break

params[ATTR_HVAC_MODE] = self.hc_homekit_to_hass[target_hc]
Expand Down

0 comments on commit 7887f23

Please sign in to comment.