forked from home-assistant/core
Compare commits
11 Commits
2022.12.0b
...
2022.12.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b462e1b8e | ||
|
|
92bc93466e | ||
|
|
54dd556459 | ||
|
|
8553faf3c8 | ||
|
|
1631d10365 | ||
|
|
141f37504d | ||
|
|
f97795fbb9 | ||
|
|
ebf133ef80 | ||
|
|
886525112b | ||
|
|
9a15494e69 | ||
|
|
047012d167 |
@@ -2,7 +2,7 @@
|
||||
"domain": "cloud",
|
||||
"name": "Home Assistant Cloud",
|
||||
"documentation": "https://www.home-assistant.io/integrations/cloud",
|
||||
"requirements": ["hass-nabucasa==0.59.0"],
|
||||
"requirements": ["hass-nabucasa==0.61.0"],
|
||||
"dependencies": ["http", "webhook"],
|
||||
"after_dependencies": ["google_assistant", "alexa"],
|
||||
"codeowners": ["@home-assistant/cloud"],
|
||||
|
||||
@@ -30,7 +30,7 @@ def async_manage_legacy_subscription_issue(
|
||||
If the provider is "legacy" create an issue,
|
||||
in all other cases remove the issue.
|
||||
"""
|
||||
if subscription_info["provider"] == "legacy":
|
||||
if subscription_info.get("provider") == "legacy":
|
||||
ir.async_create_issue(
|
||||
hass=hass,
|
||||
domain=DOMAIN,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"domain": "frontend",
|
||||
"name": "Home Assistant Frontend",
|
||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||
"requirements": ["home-assistant-frontend==20221206.0"],
|
||||
"requirements": ["home-assistant-frontend==20221207.0"],
|
||||
"dependencies": [
|
||||
"api",
|
||||
"auth",
|
||||
|
||||
@@ -16,7 +16,7 @@ from homeassistant.components.climate import (
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
|
||||
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
|
||||
from homeassistant.core import HomeAssistant, State, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import device_registry, entity_registry
|
||||
@@ -24,6 +24,8 @@ from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
from homeassistant.util.unit_conversion import TemperatureConverter
|
||||
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
||||
|
||||
from .const import LOGGER, SHTRV_01_TEMPERATURE_SETTINGS
|
||||
from .coordinator import ShellyBlockCoordinator, get_entry_data
|
||||
@@ -108,7 +110,7 @@ class BlockSleepingClimate(
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
|
||||
)
|
||||
_attr_target_temperature_step = SHTRV_01_TEMPERATURE_SETTINGS["step"]
|
||||
_attr_temperature_unit = TEMP_CELSIUS
|
||||
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -126,7 +128,14 @@ class BlockSleepingClimate(
|
||||
self.last_state: State | None = None
|
||||
self.last_state_attributes: Mapping[str, Any]
|
||||
self._preset_modes: list[str] = []
|
||||
self._last_target_temp = 20.0
|
||||
if coordinator.hass.config.units is US_CUSTOMARY_SYSTEM:
|
||||
self._last_target_temp = TemperatureConverter.convert(
|
||||
SHTRV_01_TEMPERATURE_SETTINGS["default"],
|
||||
UnitOfTemperature.CELSIUS,
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
)
|
||||
else:
|
||||
self._last_target_temp = SHTRV_01_TEMPERATURE_SETTINGS["default"]
|
||||
|
||||
if self.block is not None and self.device_block is not None:
|
||||
self._unique_id = f"{self.coordinator.mac}-{self.block.description}"
|
||||
@@ -157,14 +166,32 @@ class BlockSleepingClimate(
|
||||
"""Set target temperature."""
|
||||
if self.block is not None:
|
||||
return cast(float, self.block.targetTemp)
|
||||
return self.last_state_attributes.get("temperature")
|
||||
# The restored value can be in Fahrenheit so we have to convert it to Celsius
|
||||
# because we use this unit internally in integration.
|
||||
target_temp = self.last_state_attributes.get("temperature")
|
||||
if self.hass.config.units is US_CUSTOMARY_SYSTEM and target_temp:
|
||||
return TemperatureConverter.convert(
|
||||
cast(float, target_temp),
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
UnitOfTemperature.CELSIUS,
|
||||
)
|
||||
return target_temp
|
||||
|
||||
@property
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Return current temperature."""
|
||||
if self.block is not None:
|
||||
return cast(float, self.block.temp)
|
||||
return self.last_state_attributes.get("current_temperature")
|
||||
# The restored value can be in Fahrenheit so we have to convert it to Celsius
|
||||
# because we use this unit internally in integration.
|
||||
current_temp = self.last_state_attributes.get("current_temperature")
|
||||
if self.hass.config.units is US_CUSTOMARY_SYSTEM and current_temp:
|
||||
return TemperatureConverter.convert(
|
||||
cast(float, current_temp),
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
UnitOfTemperature.CELSIUS,
|
||||
)
|
||||
return current_temp
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
|
||||
@@ -147,6 +147,7 @@ SHTRV_01_TEMPERATURE_SETTINGS: Final = {
|
||||
"min": 4,
|
||||
"max": 31,
|
||||
"step": 0.5,
|
||||
"default": 20.0,
|
||||
}
|
||||
|
||||
# Kelvin value for colorTemp
|
||||
|
||||
@@ -12,10 +12,7 @@ from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity
|
||||
|
||||
from .const import DOMAIN
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -33,23 +30,6 @@ async def async_migrate_data(
|
||||
await async_migrate_device_ids(hass, entry, protect)
|
||||
_LOGGER.debug("Completed Migrate: async_migrate_device_ids")
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
for entity in er.async_entries_for_config_entry(entity_registry, entry.entry_id):
|
||||
if (
|
||||
entity.domain == Platform.SENSOR
|
||||
and entity.disabled_by is None
|
||||
and "detected_object" in entity.unique_id
|
||||
):
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"deprecate_smart_sensor",
|
||||
is_fixable=False,
|
||||
breaks_in_ha_version="2023.2.0",
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecate_smart_sensor",
|
||||
)
|
||||
|
||||
|
||||
async def async_get_bootstrap(protect: ProtectApiClient) -> Bootstrap:
|
||||
"""Get UniFi Protect bootstrap or raise appropriate HA error."""
|
||||
|
||||
@@ -75,10 +75,6 @@
|
||||
"ea_setup_failed": {
|
||||
"title": "Setup error using Early Access version",
|
||||
"description": "You are using v{version} of UniFi Protect which is an Early Access version. An unrecoverable error occurred while trying to load the integration. Please [downgrade to a stable version](https://www.home-assistant.io/integrations/unifiprotect#downgrading-unifi-protect) of UniFi Protect to continue using the integration.\n\nError: {error}"
|
||||
},
|
||||
"deprecate_smart_sensor": {
|
||||
"title": "Smart Detection Sensor Deprecated",
|
||||
"description": "The unified \"Detected Object\" sensor for smart detections is now deprecated. It has been replaced with individual smart detection binary sensors for each smart detection type. Please update any templates or automations accordingly."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,6 @@
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecate_smart_sensor": {
|
||||
"description": "The unified \"Detected Object\" sensor for smart detections is now deprecated. It has been replaced with individual smart detection binary sensors for each smart detection type. Please update any templates or automations accordingly.",
|
||||
"title": "Smart Detection Sensor Deprecated"
|
||||
},
|
||||
"ea_setup_failed": {
|
||||
"description": "You are using v{version} of UniFi Protect which is an Early Access version. An unrecoverable error occurred while trying to load the integration. Please [downgrade to a stable version](https://www.home-assistant.io/integrations/unifiprotect#downgrading-unifi-protect) of UniFi Protect to continue using the integration.\n\nError: {error}",
|
||||
"title": "Setup error using Early Access version"
|
||||
|
||||
@@ -360,6 +360,8 @@ class OnOffChannel(ZigbeeChannel):
|
||||
)
|
||||
self.ZCL_INIT_ATTRS["backlight_mode"] = True
|
||||
self.ZCL_INIT_ATTRS["power_on_state"] = True
|
||||
if self.cluster.endpoint.model == "TS011F":
|
||||
self.ZCL_INIT_ATTRS["child_lock"] = True
|
||||
|
||||
@property
|
||||
def on_off(self) -> bool | None:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"bellows==0.34.5",
|
||||
"pyserial==3.5",
|
||||
"pyserial-asyncio==0.6",
|
||||
"zha-quirks==0.0.87",
|
||||
"zha-quirks==0.0.88",
|
||||
"zigpy-deconz==0.19.2",
|
||||
"zigpy==0.52.3",
|
||||
"zigpy-xbee==0.16.2",
|
||||
|
||||
@@ -457,3 +457,15 @@ class AqaraPetFeederChildLock(ZHASwitchConfigurationEntity, id_suffix="child_loc
|
||||
_zcl_attribute: str = "child_lock"
|
||||
_attr_name = "Child lock"
|
||||
_attr_icon: str = "mdi:account-lock"
|
||||
|
||||
|
||||
@CONFIG_DIAGNOSTIC_MATCH(
|
||||
channel_names=CHANNEL_ON_OFF,
|
||||
models={"TS011F"},
|
||||
)
|
||||
class TuyaChildLockSwitch(ZHASwitchConfigurationEntity, id_suffix="child_lock"):
|
||||
"""Representation of a child lock configuration entity."""
|
||||
|
||||
_zcl_attribute: str = "child_lock"
|
||||
_attr_name = "Child lock"
|
||||
_attr_icon: str = "mdi:account-lock"
|
||||
|
||||
@@ -8,7 +8,7 @@ from .backports.enum import StrEnum
|
||||
APPLICATION_NAME: Final = "HomeAssistant"
|
||||
MAJOR_VERSION: Final = 2022
|
||||
MINOR_VERSION: Final = 12
|
||||
PATCH_VERSION: Final = "0b7"
|
||||
PATCH_VERSION: Final = "0"
|
||||
__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)
|
||||
|
||||
@@ -20,9 +20,9 @@ ciso8601==2.2.0
|
||||
cryptography==38.0.3
|
||||
dbus-fast==1.75.0
|
||||
fnvhash==0.1.0
|
||||
hass-nabucasa==0.59.0
|
||||
hass-nabucasa==0.61.0
|
||||
home-assistant-bluetooth==1.8.1
|
||||
home-assistant-frontend==20221206.0
|
||||
home-assistant-frontend==20221207.0
|
||||
httpx==0.23.1
|
||||
ifaddr==0.1.7
|
||||
janus==1.0.0
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "homeassistant"
|
||||
version = "2022.12.0b7"
|
||||
version = "2022.12.0"
|
||||
license = {text = "Apache-2.0"}
|
||||
description = "Open-source home automation platform running on Python 3."
|
||||
readme = "README.rst"
|
||||
|
||||
@@ -848,7 +848,7 @@ ha-philipsjs==2.9.0
|
||||
habitipy==0.2.0
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.59.0
|
||||
hass-nabucasa==0.61.0
|
||||
|
||||
# homeassistant.components.splunk
|
||||
hass_splunk==0.1.1
|
||||
@@ -884,7 +884,7 @@ hole==0.7.0
|
||||
holidays==0.17.2
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20221206.0
|
||||
home-assistant-frontend==20221207.0
|
||||
|
||||
# homeassistant.components.home_connect
|
||||
homeconnect==0.7.2
|
||||
@@ -2639,7 +2639,7 @@ zengge==0.2
|
||||
zeroconf==0.39.4
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha-quirks==0.0.87
|
||||
zha-quirks==0.0.88
|
||||
|
||||
# homeassistant.components.zhong_hong
|
||||
zhong_hong_hvac==1.0.9
|
||||
|
||||
@@ -640,7 +640,7 @@ ha-philipsjs==2.9.0
|
||||
habitipy==0.2.0
|
||||
|
||||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.59.0
|
||||
hass-nabucasa==0.61.0
|
||||
|
||||
# homeassistant.components.tasmota
|
||||
hatasmota==0.6.1
|
||||
@@ -664,7 +664,7 @@ hole==0.7.0
|
||||
holidays==0.17.2
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20221206.0
|
||||
home-assistant-frontend==20221207.0
|
||||
|
||||
# homeassistant.components.home_connect
|
||||
homeconnect==0.7.2
|
||||
@@ -1840,7 +1840,7 @@ zamg==0.1.1
|
||||
zeroconf==0.39.4
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha-quirks==0.0.87
|
||||
zha-quirks==0.0.88
|
||||
|
||||
# homeassistant.components.zha
|
||||
zigpy-deconz==0.19.2
|
||||
|
||||
@@ -70,7 +70,7 @@ async def test_legacy_subscription_delete_issue_if_no_longer_legacy(
|
||||
domain="cloud", issue_id="legacy_subscription"
|
||||
)
|
||||
|
||||
cloud_repairs.async_manage_legacy_subscription_issue(hass, {"provider": None})
|
||||
cloud_repairs.async_manage_legacy_subscription_issue(hass, {})
|
||||
assert not issue_registry.async_get_issue(
|
||||
domain="cloud", issue_id="legacy_subscription"
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_UNAVAILABLE
|
||||
from homeassistant.core import State
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
||||
|
||||
from . import init_integration, register_device, register_entity
|
||||
|
||||
@@ -212,6 +213,53 @@ async def test_block_restored_climate(hass, mock_block_device, device_reg, monke
|
||||
assert hass.states.get(entity_id).state == HVACMode.OFF
|
||||
|
||||
|
||||
async def test_block_restored_climate_us_customery(
|
||||
hass, mock_block_device, device_reg, monkeypatch
|
||||
):
|
||||
"""Test block restored climate with US CUSTOMATY unit system."""
|
||||
hass.config.units = US_CUSTOMARY_SYSTEM
|
||||
monkeypatch.delattr(mock_block_device.blocks[DEVICE_BLOCK_ID], "targetTemp")
|
||||
monkeypatch.setattr(mock_block_device.blocks[DEVICE_BLOCK_ID], "valveError", 0)
|
||||
entry = await init_integration(hass, 1, sleep_period=1000, skip_setup=True)
|
||||
register_device(device_reg, entry)
|
||||
entity_id = register_entity(
|
||||
hass,
|
||||
CLIMATE_DOMAIN,
|
||||
"test_name",
|
||||
"sensor_0",
|
||||
entry,
|
||||
)
|
||||
attrs = {"current_temperature": 67, "temperature": 68}
|
||||
mock_restore_cache(hass, [State(entity_id, HVACMode.HEAT, attributes=attrs)])
|
||||
|
||||
monkeypatch.setattr(mock_block_device, "initialized", False)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(entity_id).state == HVACMode.HEAT
|
||||
assert hass.states.get(entity_id).attributes.get("temperature") == 68
|
||||
assert hass.states.get(entity_id).attributes.get("current_temperature") == 67
|
||||
|
||||
# Partial update, should not change state
|
||||
mock_block_device.mock_update()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(entity_id).state == HVACMode.HEAT
|
||||
assert hass.states.get(entity_id).attributes.get("temperature") == 68
|
||||
assert hass.states.get(entity_id).attributes.get("current_temperature") == 67
|
||||
|
||||
# Make device online
|
||||
monkeypatch.setattr(mock_block_device, "initialized", True)
|
||||
monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "targetTemp", 19.7)
|
||||
monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "temp", 18.2)
|
||||
mock_block_device.mock_update()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(entity_id).state == HVACMode.HEAT
|
||||
assert hass.states.get(entity_id).attributes.get("temperature") == 67
|
||||
assert hass.states.get(entity_id).attributes.get("current_temperature") == 65
|
||||
|
||||
|
||||
async def test_block_restored_climate_unavailable(
|
||||
hass, mock_block_device, device_reg, monkeypatch
|
||||
):
|
||||
|
||||
@@ -6,7 +6,7 @@ from copy import copy
|
||||
from http import HTTPStatus
|
||||
from unittest.mock import Mock
|
||||
|
||||
from pyunifiprotect.data import Camera, Version
|
||||
from pyunifiprotect.data import Version
|
||||
|
||||
from homeassistant.components.repairs.issue_handler import (
|
||||
async_process_repairs_platforms,
|
||||
@@ -16,9 +16,7 @@ from homeassistant.components.repairs.websocket_api import (
|
||||
RepairsFlowResourceView,
|
||||
)
|
||||
from homeassistant.components.unifiprotect.const import DOMAIN
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .utils import MockUFPFixture, init_entry
|
||||
|
||||
@@ -126,53 +124,3 @@ async def test_ea_warning_fix(
|
||||
data = await resp.json()
|
||||
|
||||
assert data["type"] == "create_entry"
|
||||
|
||||
|
||||
async def test_deprecate_smart_default(
|
||||
hass: HomeAssistant, ufp: MockUFPFixture, hass_ws_client, doorbell: Camera
|
||||
):
|
||||
"""Test Deprecate Sensor repair does not exist by default (new installs)."""
|
||||
|
||||
await init_entry(hass, ufp, [doorbell])
|
||||
|
||||
await async_process_repairs_platforms(hass)
|
||||
ws_client = await hass_ws_client(hass)
|
||||
|
||||
await ws_client.send_json({"id": 1, "type": "repairs/list_issues"})
|
||||
msg = await ws_client.receive_json()
|
||||
|
||||
assert msg["success"]
|
||||
issue = None
|
||||
for i in msg["result"]["issues"]:
|
||||
if i["issue_id"] == "deprecate_smart_sensor":
|
||||
issue = i
|
||||
assert issue is None
|
||||
|
||||
|
||||
async def test_deprecate_smart_active(
|
||||
hass: HomeAssistant, ufp: MockUFPFixture, hass_ws_client, doorbell: Camera
|
||||
):
|
||||
"""Test Deprecate Sensor repair exists for existing installs."""
|
||||
|
||||
registry = er.async_get(hass)
|
||||
registry.async_get_or_create(
|
||||
Platform.SENSOR,
|
||||
DOMAIN,
|
||||
f"{doorbell.mac}_detected_object",
|
||||
config_entry=ufp.entry,
|
||||
)
|
||||
|
||||
await init_entry(hass, ufp, [doorbell])
|
||||
|
||||
await async_process_repairs_platforms(hass)
|
||||
ws_client = await hass_ws_client(hass)
|
||||
|
||||
await ws_client.send_json({"id": 1, "type": "repairs/list_issues"})
|
||||
msg = await ws_client.receive_json()
|
||||
|
||||
assert msg["success"]
|
||||
issue = None
|
||||
for i in msg["result"]["issues"]:
|
||||
if i["issue_id"] == "deprecate_smart_sensor":
|
||||
issue = i
|
||||
assert issue is not None
|
||||
|
||||
Reference in New Issue
Block a user