Skip to content

Commit

Permalink
Merge pull request #68159 from home-assistant/rc
Browse files Browse the repository at this point in the history
  • Loading branch information
balloob committed Mar 15, 2022
2 parents 898af3e + 27d275e commit b115372
Show file tree
Hide file tree
Showing 20 changed files with 104 additions and 37 deletions.
3 changes: 1 addition & 2 deletions homeassistant/components/amcrest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
DATA_AMCREST,
DEVICES,
DOMAIN,
RESOLUTION_LIST,
SERVICE_EVENT,
SERVICE_UPDATE,
)
Expand All @@ -76,8 +77,6 @@
NOTIFICATION_ID = "amcrest_notification"
NOTIFICATION_TITLE = "Amcrest Camera Setup"

RESOLUTION_LIST = {"high": 0, "low": 1}

SCAN_INTERVAL = timedelta(seconds=10)

AUTHENTICATION_LIST = {"basic": "basic"}
Expand Down
18 changes: 12 additions & 6 deletions homeassistant/components/amcrest/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
DATA_AMCREST,
DEVICES,
DOMAIN,
RESOLUTION_TO_STREAM,
SERVICE_UPDATE,
SNAPSHOT_TIMEOUT,
)
Expand Down Expand Up @@ -533,13 +534,14 @@ async def _async_change_setting(
return

async def _async_get_video(self) -> bool:
stream = {0: "Main", 1: "Extra"}
return await self._api.async_is_video_enabled(
channel=0, stream=stream[self._resolution]
channel=0, stream=RESOLUTION_TO_STREAM[self._resolution]
)

async def _async_set_video(self, enable: bool) -> None:
await self._api.async_set_video_enabled(enable, channel=0)
await self._api.async_set_video_enabled(
enable, channel=0, stream=RESOLUTION_TO_STREAM[self._resolution]
)

async def _async_enable_video(self, enable: bool) -> None:
"""Enable or disable camera video stream."""
Expand All @@ -548,7 +550,7 @@ async def _async_enable_video(self, enable: bool) -> None:
# recording on if video stream is being turned off.
if self.is_recording and not enable:
await self._async_enable_recording(False)
await self._async_change_setting(enable, "video", "is_streaming")
await self._async_change_setting(enable, "video", "_attr_is_streaming")
if self._control_light:
await self._async_change_light()

Expand Down Expand Up @@ -585,10 +587,14 @@ async def _async_enable_motion_detection(self, enable: bool) -> None:
)

async def _async_get_audio(self) -> bool:
return await self._api.async_audio_enabled
return await self._api.async_is_audio_enabled(
channel=0, stream=RESOLUTION_TO_STREAM[self._resolution]
)

async def _async_set_audio(self, enable: bool) -> None:
await self._api.async_set_audio_enabled(enable)
await self._api.async_set_audio_enabled(
enable, channel=0, stream=RESOLUTION_TO_STREAM[self._resolution]
)

async def _async_enable_audio(self, enable: bool) -> None:
"""Enable or disable audio stream."""
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/amcrest/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@

SERVICE_EVENT = "event"
SERVICE_UPDATE = "update"

RESOLUTION_LIST = {"high": 0, "low": 1}
RESOLUTION_TO_STREAM = {0: "Main", 1: "Extra"}
2 changes: 1 addition & 1 deletion homeassistant/components/amcrest/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"domain": "amcrest",
"name": "Amcrest",
"documentation": "https://www.home-assistant.io/integrations/amcrest",
"requirements": ["amcrest==1.9.4"],
"requirements": ["amcrest==1.9.7"],
"dependencies": ["ffmpeg"],
"codeowners": ["@flacjacket"],
"iot_class": "local_polling",
Expand Down
4 changes: 3 additions & 1 deletion homeassistant/components/doorbird/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.util.network import is_link_local
from homeassistant.util.network import is_ipv4_address, is_link_local

from .const import CONF_EVENTS, DOMAIN, DOORBIRD_OUI
from .util import get_mac_address_from_doorstation_info
Expand Down Expand Up @@ -103,6 +103,8 @@ async def async_step_zeroconf(
return self.async_abort(reason="not_doorbird_device")
if is_link_local(ip_address(host)):
return self.async_abort(reason="link_local_address")
if not is_ipv4_address(host):
return self.async_abort(reason="not_ipv4_address")

await self.async_set_unique_id(macaddress)
self._abort_if_unique_id_configured(updates={CONF_HOST: host})
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/doorbird/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"abort": {
"already_configured": "Device is already configured",
"link_local_address": "Link local addresses are not supported",
"not_doorbird_device": "This device is not a DoorBird"
"not_doorbird_device": "This device is not a DoorBird",
"not_ipv4_address": "Only IPv4 addresess are supported"
},
"error": {
"cannot_connect": "Failed to connect",
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Home Assistant Frontend",
"documentation": "https://www.home-assistant.io/integrations/frontend",
"requirements": [
"home-assistant-frontend==20220301.1"
"home-assistant-frontend==20220301.2"
],
"dependencies": [
"api",
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/home_connect/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"documentation": "https://www.home-assistant.io/integrations/home_connect",
"dependencies": ["http"],
"codeowners": ["@DavidMStraub"],
"requirements": ["homeconnect==0.6.3"],
"requirements": ["homeconnect==0.7.0"],
"config_flow": true,
"iot_class": "cloud_push",
"loggers": ["homeconnect"]
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/isy994/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"domain": "isy994",
"name": "Universal Devices ISY994",
"documentation": "https://www.home-assistant.io/integrations/isy994",
"requirements": ["pyisy==3.0.1"],
"requirements": ["pyisy==3.0.5"],
"codeowners": ["@bdraco", "@shbatm"],
"config_flow": true,
"ssdp": [
Expand Down
18 changes: 14 additions & 4 deletions homeassistant/components/mqtt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@
DEFAULT_PROTOCOL = PROTOCOL_311
DEFAULT_TLS_PROTOCOL = "auto"

DEFAULT_VALUES = {
CONF_PORT: DEFAULT_PORT,
CONF_WILL_MESSAGE: DEFAULT_WILL,
CONF_BIRTH_MESSAGE: DEFAULT_BIRTH,
CONF_DISCOVERY: DEFAULT_DISCOVERY,
}

ATTR_TOPIC_TEMPLATE = "topic_template"
ATTR_PAYLOAD_TEMPLATE = "payload_template"

Expand Down Expand Up @@ -190,7 +197,7 @@
vol.Coerce(int), vol.Range(min=15)
),
vol.Optional(CONF_BROKER): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_PORT): cv.port,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
vol.Optional(CONF_CERTIFICATE): vol.Any("auto", cv.isfile),
Expand All @@ -207,9 +214,9 @@
vol.Optional(CONF_PROTOCOL, default=DEFAULT_PROTOCOL): vol.All(
cv.string, vol.In([PROTOCOL_31, PROTOCOL_311])
),
vol.Optional(CONF_WILL_MESSAGE, default=DEFAULT_WILL): MQTT_WILL_BIRTH_SCHEMA,
vol.Optional(CONF_BIRTH_MESSAGE, default=DEFAULT_BIRTH): MQTT_WILL_BIRTH_SCHEMA,
vol.Optional(CONF_DISCOVERY, default=DEFAULT_DISCOVERY): cv.boolean,
vol.Optional(CONF_WILL_MESSAGE): MQTT_WILL_BIRTH_SCHEMA,
vol.Optional(CONF_BIRTH_MESSAGE): MQTT_WILL_BIRTH_SCHEMA,
vol.Optional(CONF_DISCOVERY): cv.boolean,
# discovery_prefix must be a valid publish topic because if no
# state topic is specified, it will be created with the given prefix.
vol.Optional(
Expand Down Expand Up @@ -613,6 +620,8 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:

def _merge_config(entry, conf):
"""Merge configuration.yaml config with config entry."""
# Base config on default values
conf = {**DEFAULT_VALUES, **conf}
return {**conf, **entry.data}


Expand All @@ -632,6 +641,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
override,
)

# Merge the configuration values from configuration.yaml
conf = _merge_config(entry, conf)

hass.data[DATA_MQTT] = MQTT(
Expand Down
6 changes: 3 additions & 3 deletions homeassistant/components/samsungtv/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from samsungctl.exceptions import AccessDenied, ConnectionClosed, UnhandledResponse
from samsungtvws import SamsungTVWS
from samsungtvws.exceptions import ConnectionFailure, HttpApiError
from websocket import WebSocketException
from websocket import WebSocketException, WebSocketTimeoutException

from homeassistant.const import (
CONF_HOST,
Expand Down Expand Up @@ -318,8 +318,8 @@ async def async_get_app_list(self) -> dict[str, str] | None:

def _get_app_list(self) -> dict[str, str] | None:
"""Get installed app list."""
if self._app_list is None:
if remote := self._get_remote():
if self._app_list is None and (remote := self._get_remote()):
with contextlib.suppress(WebSocketTimeoutException):
raw_app_list: list[dict[str, str]] = remote.app_list()
self._app_list = {
app["name"]: app["appId"]
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/shelly/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class RestSensorDescription(RestEntityDescription, SensorEntityDescription):
value=lambda value: round(value / 1000, 2),
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
available=lambda block: cast(int, block.energy) != -1,
),
("emeter", "energyReturned"): BlockSensorDescription(
key="emeter|energyReturned",
Expand All @@ -182,6 +183,7 @@ class RestSensorDescription(RestEntityDescription, SensorEntityDescription):
value=lambda value: round(value / 1000, 2),
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
available=lambda block: cast(int, block.energyReturned) != -1,
),
("light", "energy"): BlockSensorDescription(
key="light|energy",
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/somfy_mylink/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def __init__(
self._attr_unique_id = target_id
self._attr_name = name
self._reverse = reverse
self._attr_is_closed = None
self._attr_device_class = device_class
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, self._target_id)},
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

MAJOR_VERSION: Final = 2022
MINOR_VERSION: Final = 3
PATCH_VERSION: Final = "4"
PATCH_VERSION: Final = "5"
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/package_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ certifi>=2021.5.30
ciso8601==2.2.0
cryptography==35.0.0
hass-nabucasa==0.54.0
home-assistant-frontend==20220301.1
home-assistant-frontend==20220301.2
httpx==0.21.3
ifaddr==0.1.7
jinja2==3.0.3
Expand Down
8 changes: 4 additions & 4 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ amberelectric==1.0.3
ambiclimate==0.2.1

# homeassistant.components.amcrest
amcrest==1.9.4
amcrest==1.9.7

# homeassistant.components.androidtv
androidtv[async]==0.0.63
Expand Down Expand Up @@ -843,13 +843,13 @@ hole==0.7.0
holidays==0.13

# homeassistant.components.frontend
home-assistant-frontend==20220301.1
home-assistant-frontend==20220301.2

# homeassistant.components.zwave
# homeassistant-pyozw==0.1.10

# homeassistant.components.home_connect
homeconnect==0.6.3
homeconnect==0.7.0

# homeassistant.components.homematicip_cloud
homematicip==1.0.2
Expand Down Expand Up @@ -1610,7 +1610,7 @@ pyirishrail==0.0.2
pyiss==1.0.1

# homeassistant.components.isy994
pyisy==3.0.1
pyisy==3.0.5

# homeassistant.components.itach
pyitachip2ir==0.0.7
Expand Down
6 changes: 3 additions & 3 deletions requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -553,13 +553,13 @@ hole==0.7.0
holidays==0.13

# homeassistant.components.frontend
home-assistant-frontend==20220301.1
home-assistant-frontend==20220301.2

# homeassistant.components.zwave
# homeassistant-pyozw==0.1.10

# homeassistant.components.home_connect
homeconnect==0.6.3
homeconnect==0.7.0

# homeassistant.components.homematicip_cloud
homematicip==1.0.2
Expand Down Expand Up @@ -1015,7 +1015,7 @@ pyiqvia==2021.11.0
pyiss==1.0.1

# homeassistant.components.isy994
pyisy==3.0.1
pyisy==3.0.5

# homeassistant.components.kira
pykira==0.1.1
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = homeassistant
version = 2022.3.4
version = 2022.3.5
author = The Home Assistant Authors
author_email = hello@home-assistant.io
license = Apache-2.0
Expand Down
48 changes: 48 additions & 0 deletions tests/components/doorbird/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,54 @@ async def test_form_zeroconf_link_local_ignored(hass):
assert result["reason"] == "link_local_address"


async def test_form_zeroconf_ipv4_address(hass):
"""Test we abort and update the ip address from zeroconf with an ipv4 address."""

config_entry = MockConfigEntry(
domain=DOMAIN,
unique_id="1CCAE3AAAAAA",
data=VALID_CONFIG,
options={CONF_EVENTS: ["event1", "event2", "event3"]},
)
config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_ZEROCONF},
data=zeroconf.ZeroconfServiceInfo(
host="4.4.4.4",
addresses=["4.4.4.4"],
hostname="mock_hostname",
name="Doorstation - abc123._axis-video._tcp.local.",
port=None,
properties={"macaddress": "1CCAE3AAAAAA"},
type="mock_type",
),
)
assert result["type"] == "abort"
assert result["reason"] == "already_configured"
assert config_entry.data[CONF_HOST] == "4.4.4.4"


async def test_form_zeroconf_non_ipv4_ignored(hass):
"""Test we abort when we get a non ipv4 address via zeroconf."""

result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_ZEROCONF},
data=zeroconf.ZeroconfServiceInfo(
host="fd00::b27c:63bb:cc85:4ea0",
addresses=["fd00::b27c:63bb:cc85:4ea0"],
hostname="mock_hostname",
name="Doorstation - abc123._axis-video._tcp.local.",
port=None,
properties={"macaddress": "1CCAE3DOORBIRD"},
type="mock_type",
),
)
assert result["type"] == "abort"
assert result["reason"] == "not_ipv4_address"


async def test_form_zeroconf_correct_oui(hass):
"""Test we can setup from zeroconf with the correct OUI source."""
doorbirdapi = _get_mock_doorbirdapi_return_values(
Expand Down
Loading

0 comments on commit b115372

Please sign in to comment.