diff --git a/homeassistant/components/daikin/climate.py b/homeassistant/components/daikin/climate.py index 3d064f47e97..fb708916039 100644 --- a/homeassistant/components/daikin/climate.py +++ b/homeassistant/components/daikin/climate.py @@ -118,8 +118,8 @@ async def async_setup_entry( def format_target_temperature(target_temperature): - """Format target temperature to be sent to the Daikin unit, taking care of keeping at most 1 decimal digit.""" - return str(round(float(target_temperature), 1)).rstrip("0").rstrip(".") + """Format target temperature to be sent to the Daikin unit, rounding to nearest half degree.""" + return str(round(float(target_temperature) * 2, 0) / 2).rstrip("0").rstrip(".") class DaikinClimate(ClimateEntity): diff --git a/homeassistant/components/dhcp/manifest.json b/homeassistant/components/dhcp/manifest.json index e540d077781..fea7772f72d 100644 --- a/homeassistant/components/dhcp/manifest.json +++ b/homeassistant/components/dhcp/manifest.json @@ -2,7 +2,7 @@ "domain": "dhcp", "name": "DHCP Discovery", "documentation": "https://www.home-assistant.io/integrations/dhcp", - "requirements": ["scapy==2.4.5", "aiodiscover==1.4.9"], + "requirements": ["scapy==2.4.5", "aiodiscover==1.4.11"], "codeowners": ["@bdraco"], "quality_scale": "internal", "iot_class": "local_push", diff --git a/homeassistant/components/knx/manifest.json b/homeassistant/components/knx/manifest.json index f11ef8c56cb..1058bf25ad8 100644 --- a/homeassistant/components/knx/manifest.json +++ b/homeassistant/components/knx/manifest.json @@ -3,7 +3,7 @@ "name": "KNX", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/knx", - "requirements": ["xknx==0.20.3"], + "requirements": ["xknx==0.20.4"], "codeowners": ["@Julius2342", "@farmio", "@marvin-w"], "quality_scale": "silver", "iot_class": "local_push", diff --git a/homeassistant/components/plaato/manifest.json b/homeassistant/components/plaato/manifest.json index 5335a79fe15..4a88db58934 100644 --- a/homeassistant/components/plaato/manifest.json +++ b/homeassistant/components/plaato/manifest.json @@ -6,7 +6,7 @@ "dependencies": ["webhook"], "after_dependencies": ["cloud"], "codeowners": ["@JohNan"], - "requirements": ["pyplaato==0.0.16"], + "requirements": ["pyplaato==0.0.18"], "iot_class": "cloud_push", "loggers": ["pyplaato"] } diff --git a/homeassistant/components/rainmachine/config_flow.py b/homeassistant/components/rainmachine/config_flow.py index 989616f6367..d24dae46c2b 100644 --- a/homeassistant/components/rainmachine/config_flow.py +++ b/homeassistant/components/rainmachine/config_flow.py @@ -132,7 +132,7 @@ class RainMachineFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): # access token without using the IP address and password, so we have to # store it: return self.async_create_entry( - title=controller.name, + title=str(controller.name), data={ CONF_IP_ADDRESS: user_input[CONF_IP_ADDRESS], CONF_PASSWORD: user_input[CONF_PASSWORD], diff --git a/homeassistant/components/recorder/history.py b/homeassistant/components/recorder/history.py index 82a74c36a83..95f69bf769f 100644 --- a/homeassistant/components/recorder/history.py +++ b/homeassistant/components/recorder/history.py @@ -395,7 +395,7 @@ def _get_states_with_session( if ( run is None - and (run := (recorder.run_information_from_instance(hass, utc_point_in_time))) + and (run := (recorder.run_information_with_session(session, utc_point_in_time))) is None ): # History did not run before utc_point_in_time diff --git a/homeassistant/components/recorder/migration.py b/homeassistant/components/recorder/migration.py index 26234be0502..87cfb88032f 100644 --- a/homeassistant/components/recorder/migration.py +++ b/homeassistant/components/recorder/migration.py @@ -544,7 +544,7 @@ def _apply_update(instance, new_version, old_version): # noqa: C901 # https://github.com/home-assistant/core/issues/56104 text( f"ALTER TABLE {table} CONVERT TO " - "CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci LOCK=EXCLUSIVE" + "CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, LOCK=EXCLUSIVE" ) ) elif new_version == 22: diff --git a/homeassistant/components/zwave_js/__init__.py b/homeassistant/components/zwave_js/__init__.py index 12ff9acb530..fa87ad954ad 100644 --- a/homeassistant/components/zwave_js/__init__.py +++ b/homeassistant/components/zwave_js/__init__.py @@ -4,6 +4,7 @@ from __future__ import annotations import asyncio from collections import defaultdict from collections.abc import Callable +from typing import Any from async_timeout import timeout from zwave_js_server.client import Client as ZwaveClient @@ -289,12 +290,7 @@ async def async_setup_entry( # noqa: C901 ) ) # add listener for stateless node notification events - entry.async_on_unload( - node.on( - "notification", - lambda event: async_on_notification(event["notification"]), - ) - ) + entry.async_on_unload(node.on("notification", async_on_notification)) async def async_on_node_added(node: ZwaveNode) -> None: """Handle node added event.""" @@ -402,12 +398,14 @@ async def async_setup_entry( # noqa: C901 ) @callback - def async_on_notification( - notification: EntryControlNotification - | NotificationNotification - | PowerLevelNotification, - ) -> None: + def async_on_notification(event: dict[str, Any]) -> None: """Relay stateless notification events from Z-Wave nodes to hass.""" + if "notification" not in event: + LOGGER.info("Unknown notification: %s", event) + return + notification: EntryControlNotification | NotificationNotification | PowerLevelNotification = event[ + "notification" + ] device = dev_reg.async_get_device({get_device_id(client, notification.node)}) # We assert because we know the device exists assert device diff --git a/homeassistant/components/zwave_js/manifest.json b/homeassistant/components/zwave_js/manifest.json index c3968181563..abdb5d6fbb8 100644 --- a/homeassistant/components/zwave_js/manifest.json +++ b/homeassistant/components/zwave_js/manifest.json @@ -3,7 +3,7 @@ "name": "Z-Wave JS", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zwave_js", - "requirements": ["zwave-js-server-python==0.35.2"], + "requirements": ["zwave-js-server-python==0.35.3"], "codeowners": ["@home-assistant/z-wave"], "dependencies": ["usb", "http", "websocket_api"], "iot_class": "local_push", diff --git a/homeassistant/const.py b/homeassistant/const.py index 02e1b896df1..e8eee10d950 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from .backports.enum import StrEnum MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 4 -PATCH_VERSION: Final = "6" +PATCH_VERSION: Final = "7" __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) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index f3df4c88c80..948fea5fa44 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -1,6 +1,6 @@ PyJWT==2.3.0 PyNaCl==1.5.0 -aiodiscover==1.4.9 +aiodiscover==1.4.11 aiohttp==3.8.1 aiohttp_cors==0.7.0 astral==2.2 diff --git a/requirements_all.txt b/requirements_all.txt index a75516a4668..c1ca25c6f4c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -128,7 +128,7 @@ aioazuredevops==1.3.5 aiobotocore==2.1.0 # homeassistant.components.dhcp -aiodiscover==1.4.9 +aiodiscover==1.4.11 # homeassistant.components.dnsip # homeassistant.components.minecraft_server @@ -1723,7 +1723,7 @@ pypck==0.7.14 pypjlink2==1.2.1 # homeassistant.components.plaato -pyplaato==0.0.16 +pyplaato==0.0.18 # homeassistant.components.point pypoint==2.3.0 @@ -2435,7 +2435,7 @@ xbox-webapi==2.0.11 xboxapi==2.0.1 # homeassistant.components.knx -xknx==0.20.3 +xknx==0.20.4 # homeassistant.components.bluesound # homeassistant.components.fritz @@ -2500,7 +2500,7 @@ zigpy==0.44.2 zm-py==0.5.2 # homeassistant.components.zwave_js -zwave-js-server-python==0.35.2 +zwave-js-server-python==0.35.3 # homeassistant.components.zwave_me zwave_me_ws==0.2.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 77df1910b77..66bc32309f9 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -112,7 +112,7 @@ aioazuredevops==1.3.5 aiobotocore==2.1.0 # homeassistant.components.dhcp -aiodiscover==1.4.9 +aiodiscover==1.4.11 # homeassistant.components.dnsip # homeassistant.components.minecraft_server @@ -1154,7 +1154,7 @@ pyownet==0.10.0.post1 pypck==0.7.14 # homeassistant.components.plaato -pyplaato==0.0.16 +pyplaato==0.0.18 # homeassistant.components.point pypoint==2.3.0 @@ -1575,7 +1575,7 @@ wolf_smartset==0.1.11 xbox-webapi==2.0.11 # homeassistant.components.knx -xknx==0.20.3 +xknx==0.20.4 # homeassistant.components.bluesound # homeassistant.components.fritz @@ -1619,7 +1619,7 @@ zigpy-znp==0.7.0 zigpy==0.44.2 # homeassistant.components.zwave_js -zwave-js-server-python==0.35.2 +zwave-js-server-python==0.35.3 # homeassistant.components.zwave_me zwave_me_ws==0.2.3 diff --git a/setup.cfg b/setup.cfg index 903d09f4267..e19c4dc9572 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = homeassistant -version = 2022.4.6 +version = 2022.4.7 author = The Home Assistant Authors author_email = hello@home-assistant.io license = Apache-2.0 diff --git a/tests/components/daikin/test_temperature_format.py b/tests/components/daikin/test_temperature_format.py index d05efa98b8d..bc085fa1fd8 100644 --- a/tests/components/daikin/test_temperature_format.py +++ b/tests/components/daikin/test_temperature_format.py @@ -8,13 +8,13 @@ def test_int_conversion(): assert formatted == "16" -def test_decimal_conversion(): +def test_rounding(): """Check 1 decimal is kept when target temp is a decimal.""" formatted = format_target_temperature("16.1") - assert formatted == "16.1" - - -def test_decimal_conversion_more_digits(): - """Check at most 1 decimal is kept when target temp is a decimal with more than 1 decimal.""" - formatted = format_target_temperature("16.09") - assert formatted == "16.1" + assert formatted == "16" + formatted = format_target_temperature("16.3") + assert formatted == "16.5" + formatted = format_target_temperature("16.65") + assert formatted == "16.5" + formatted = format_target_temperature("16.9") + assert formatted == "17" diff --git a/tests/components/rainmachine/conftest.py b/tests/components/rainmachine/conftest.py index 3a32b3b7c9a..457df4a3ef2 100644 --- a/tests/components/rainmachine/conftest.py +++ b/tests/components/rainmachine/conftest.py @@ -49,7 +49,9 @@ def controller_fixture( controller = AsyncMock() controller.api_version = "4.5.0" controller.hardware_version = 3 - controller.name = "My RainMachine" + # The api returns a controller with all numbers as numeric + # instead of a string + controller.name = 12345 controller.mac = controller_mac controller.software_version = "4.0.925" diff --git a/tests/components/rainmachine/test_config_flow.py b/tests/components/rainmachine/test_config_flow.py index 5a0e1fc08cc..8b313eb2fb5 100644 --- a/tests/components/rainmachine/test_config_flow.py +++ b/tests/components/rainmachine/test_config_flow.py @@ -124,7 +124,7 @@ async def test_step_user(hass, config, setup_rainmachine): data=config, ) assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY - assert result["title"] == "My RainMachine" + assert result["title"] == "12345" assert result["data"] == { CONF_IP_ADDRESS: "192.168.1.100", CONF_PASSWORD: "password", @@ -232,7 +232,7 @@ async def test_step_homekit_zeroconf_new_controller_when_some_exist( await hass.async_block_till_done() assert result2["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY - assert result2["title"] == "My RainMachine" + assert result2["title"] == "12345" assert result2["data"] == { CONF_IP_ADDRESS: "192.168.1.100", CONF_PASSWORD: "password", diff --git a/tests/components/rainmachine/test_diagnostics.py b/tests/components/rainmachine/test_diagnostics.py index 575e596abc2..d770d01fd36 100644 --- a/tests/components/rainmachine/test_diagnostics.py +++ b/tests/components/rainmachine/test_diagnostics.py @@ -585,7 +585,7 @@ async def test_entry_diagnostics(hass, config_entry, hass_client, setup_rainmach "controller": { "api_version": "4.5.0", "hardware_version": 3, - "name": "My RainMachine", + "name": 12345, "software_version": "4.0.925", }, }, diff --git a/tests/components/zwave_js/test_events.py b/tests/components/zwave_js/test_events.py index 32859ae3c37..5085175de83 100644 --- a/tests/components/zwave_js/test_events.py +++ b/tests/components/zwave_js/test_events.py @@ -307,3 +307,26 @@ async def test_unknown_notification(hass, hank_binary_switch, integration, clien notification_obj.node = node with pytest.raises(TypeError): node.emit("notification", {"notification": notification_obj}) + + notification_events = async_capture_events(hass, "zwave_js_notification") + + # Test a valid notification with an unsupported command class + event = Event( + type="notification", + data={ + "source": "node", + "event": "notification", + "nodeId": node.node_id, + "ccId": 0, + "args": { + "commandClassName": "No Operation", + "commandClass": 0, + "testNodeId": 1, + "status": 0, + "acknowledgedFrames": 2, + }, + }, + ) + node.receive_event(event) + + assert not notification_events