mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 23:27:37 +00:00
2023.3.1 (#89059)
This commit is contained in:
commit
f0f12fd14a
@ -11,5 +11,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/dormakaba_dkey",
|
"documentation": "https://www.home-assistant.io/integrations/dormakaba_dkey",
|
||||||
"integration_type": "device",
|
"integration_type": "device",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"requirements": ["py-dormakaba-dkey==1.0.3"]
|
"requirements": ["py-dormakaba-dkey==1.0.4"]
|
||||||
}
|
}
|
||||||
|
@ -20,5 +20,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||||
"integration_type": "system",
|
"integration_type": "system",
|
||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
"requirements": ["home-assistant-frontend==20230301.0"]
|
"requirements": ["home-assistant-frontend==20230302.0"]
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from collections.abc import AsyncGenerator
|
from collections.abc import AsyncGenerator
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import shutil
|
||||||
from typing import Any, Final
|
from typing import Any, Final
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -549,9 +550,12 @@ class KNXCommonFlow(ABC, FlowHandler):
|
|||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
_tunnel_identifier = selected_tunnel_ia or self.new_entry_data.get(
|
||||||
|
CONF_HOST
|
||||||
|
)
|
||||||
|
_tunnel_suffix = f" @ {_tunnel_identifier}" if _tunnel_identifier else ""
|
||||||
self.new_title = (
|
self.new_title = (
|
||||||
f"{'Secure ' if _if_user_id else ''}"
|
f"{'Secure ' if _if_user_id else ''}Tunneling{_tunnel_suffix}"
|
||||||
f"Tunneling @ {selected_tunnel_ia or self.new_entry_data[CONF_HOST]}"
|
|
||||||
)
|
)
|
||||||
return self.finish_flow()
|
return self.finish_flow()
|
||||||
|
|
||||||
@ -708,7 +712,8 @@ class KNXCommonFlow(ABC, FlowHandler):
|
|||||||
else:
|
else:
|
||||||
dest_path = Path(self.hass.config.path(STORAGE_DIR, DOMAIN))
|
dest_path = Path(self.hass.config.path(STORAGE_DIR, DOMAIN))
|
||||||
dest_path.mkdir(exist_ok=True)
|
dest_path.mkdir(exist_ok=True)
|
||||||
file_path.rename(dest_path / DEFAULT_KNX_KEYRING_FILENAME)
|
dest_file = dest_path / DEFAULT_KNX_KEYRING_FILENAME
|
||||||
|
shutil.move(file_path, dest_file)
|
||||||
return keyring, errors
|
return keyring, errors
|
||||||
|
|
||||||
keyring, errors = await self.hass.async_add_executor_job(_process_upload)
|
keyring, errors = await self.hass.async_add_executor_job(_process_upload)
|
||||||
|
@ -12,5 +12,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/nuheat",
|
"documentation": "https://www.home-assistant.io/integrations/nuheat",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["nuheat"],
|
"loggers": ["nuheat"],
|
||||||
"requirements": ["nuheat==1.0.0"]
|
"requirements": ["nuheat==1.0.1"]
|
||||||
}
|
}
|
||||||
|
@ -271,15 +271,20 @@ class SensorEntity(Entity):
|
|||||||
@property
|
@property
|
||||||
def _numeric_state_expected(self) -> bool:
|
def _numeric_state_expected(self) -> bool:
|
||||||
"""Return true if the sensor must be numeric."""
|
"""Return true if the sensor must be numeric."""
|
||||||
|
# Note: the order of the checks needs to be kept aligned
|
||||||
|
# with the checks in `state` property.
|
||||||
|
device_class = try_parse_enum(SensorDeviceClass, self.device_class)
|
||||||
|
if device_class in NON_NUMERIC_DEVICE_CLASSES:
|
||||||
|
return False
|
||||||
if (
|
if (
|
||||||
self.state_class is not None
|
self.state_class is not None
|
||||||
or self.native_unit_of_measurement is not None
|
or self.native_unit_of_measurement is not None
|
||||||
or self.suggested_display_precision is not None
|
or self.suggested_display_precision is not None
|
||||||
):
|
):
|
||||||
return True
|
return True
|
||||||
# Sensors with custom device classes are not considered numeric
|
# Sensors with custom device classes will have the device class
|
||||||
device_class = try_parse_enum(SensorDeviceClass, self.device_class)
|
# converted to None and are not considered numeric
|
||||||
return device_class not in {None, *NON_NUMERIC_DEVICE_CLASSES}
|
return device_class is not None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def options(self) -> list[str] | None:
|
def options(self) -> list[str] | None:
|
||||||
|
@ -53,17 +53,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
await tibber_connection.update_info()
|
await tibber_connection.update_info()
|
||||||
if not tibber_connection.name:
|
|
||||||
raise ConfigEntryNotReady("Could not fetch Tibber data.")
|
|
||||||
|
|
||||||
except asyncio.TimeoutError as err:
|
except (
|
||||||
raise ConfigEntryNotReady from err
|
asyncio.TimeoutError,
|
||||||
except aiohttp.ClientError as err:
|
aiohttp.ClientError,
|
||||||
_LOGGER.error("Error connecting to Tibber: %s ", err)
|
tibber.RetryableHttpException,
|
||||||
return False
|
) as err:
|
||||||
|
raise ConfigEntryNotReady("Unable to connect") from err
|
||||||
except tibber.InvalidLogin as exp:
|
except tibber.InvalidLogin as exp:
|
||||||
_LOGGER.error("Failed to login. %s", exp)
|
_LOGGER.error("Failed to login. %s", exp)
|
||||||
return False
|
return False
|
||||||
|
except tibber.FatalHttpException:
|
||||||
|
return False
|
||||||
|
|
||||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||||
|
|
||||||
|
@ -44,10 +44,14 @@ class TibberConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
await tibber_connection.update_info()
|
await tibber_connection.update_info()
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
errors[CONF_ACCESS_TOKEN] = "timeout"
|
errors[CONF_ACCESS_TOKEN] = "timeout"
|
||||||
except aiohttp.ClientError:
|
|
||||||
errors[CONF_ACCESS_TOKEN] = "cannot_connect"
|
|
||||||
except tibber.InvalidLogin:
|
except tibber.InvalidLogin:
|
||||||
errors[CONF_ACCESS_TOKEN] = "invalid_access_token"
|
errors[CONF_ACCESS_TOKEN] = "invalid_access_token"
|
||||||
|
except (
|
||||||
|
aiohttp.ClientError,
|
||||||
|
tibber.RetryableHttpException,
|
||||||
|
tibber.FatalHttpException,
|
||||||
|
):
|
||||||
|
errors[CONF_ACCESS_TOKEN] = "cannot_connect"
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["tibber"],
|
"loggers": ["tibber"],
|
||||||
"quality_scale": "silver",
|
"quality_scale": "silver",
|
||||||
"requirements": ["pyTibber==0.26.13"]
|
"requirements": ["pyTibber==0.27.0"]
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ from homeassistant.helpers.entity_registry import async_get as async_get_entity_
|
|||||||
from homeassistant.helpers.update_coordinator import (
|
from homeassistant.helpers.update_coordinator import (
|
||||||
CoordinatorEntity,
|
CoordinatorEntity,
|
||||||
DataUpdateCoordinator,
|
DataUpdateCoordinator,
|
||||||
|
UpdateFailed,
|
||||||
)
|
)
|
||||||
from homeassistant.util import Throttle, dt as dt_util
|
from homeassistant.util import Throttle, dt as dt_util
|
||||||
|
|
||||||
@ -559,6 +560,8 @@ class TibberRtDataCoordinator(DataUpdateCoordinator):
|
|||||||
class TibberDataCoordinator(DataUpdateCoordinator[None]):
|
class TibberDataCoordinator(DataUpdateCoordinator[None]):
|
||||||
"""Handle Tibber data and insert statistics."""
|
"""Handle Tibber data and insert statistics."""
|
||||||
|
|
||||||
|
config_entry: ConfigEntry
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, tibber_connection: tibber.Tibber) -> None:
|
def __init__(self, hass: HomeAssistant, tibber_connection: tibber.Tibber) -> None:
|
||||||
"""Initialize the data handler."""
|
"""Initialize the data handler."""
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@ -571,9 +574,17 @@ class TibberDataCoordinator(DataUpdateCoordinator[None]):
|
|||||||
|
|
||||||
async def _async_update_data(self) -> None:
|
async def _async_update_data(self) -> None:
|
||||||
"""Update data via API."""
|
"""Update data via API."""
|
||||||
|
try:
|
||||||
await self._tibber_connection.fetch_consumption_data_active_homes()
|
await self._tibber_connection.fetch_consumption_data_active_homes()
|
||||||
await self._tibber_connection.fetch_production_data_active_homes()
|
await self._tibber_connection.fetch_production_data_active_homes()
|
||||||
await self._insert_statistics()
|
await self._insert_statistics()
|
||||||
|
except tibber.RetryableHttpException as err:
|
||||||
|
raise UpdateFailed(f"Error communicating with API ({err.status})") from err
|
||||||
|
except tibber.FatalHttpException:
|
||||||
|
# Fatal error. Reload config entry to show correct error.
|
||||||
|
self.hass.async_create_task(
|
||||||
|
self.hass.config_entries.async_reload(self.config_entry.entry_id)
|
||||||
|
)
|
||||||
|
|
||||||
async def _insert_statistics(self) -> None:
|
async def _insert_statistics(self) -> None:
|
||||||
"""Insert Tibber statistics."""
|
"""Insert Tibber statistics."""
|
||||||
|
@ -8,7 +8,7 @@ from .backports.enum import StrEnum
|
|||||||
APPLICATION_NAME: Final = "HomeAssistant"
|
APPLICATION_NAME: Final = "HomeAssistant"
|
||||||
MAJOR_VERSION: Final = 2023
|
MAJOR_VERSION: Final = 2023
|
||||||
MINOR_VERSION: Final = 3
|
MINOR_VERSION: Final = 3
|
||||||
PATCH_VERSION: Final = "0"
|
PATCH_VERSION: Final = "1"
|
||||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 10, 0)
|
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 10, 0)
|
||||||
|
@ -23,14 +23,14 @@ fnvhash==0.1.0
|
|||||||
hass-nabucasa==0.61.0
|
hass-nabucasa==0.61.0
|
||||||
hassil==1.0.6
|
hassil==1.0.6
|
||||||
home-assistant-bluetooth==1.9.3
|
home-assistant-bluetooth==1.9.3
|
||||||
home-assistant-frontend==20230301.0
|
home-assistant-frontend==20230302.0
|
||||||
home-assistant-intents==2023.2.28
|
home-assistant-intents==2023.2.28
|
||||||
httpx==0.23.3
|
httpx==0.23.3
|
||||||
ifaddr==0.1.7
|
ifaddr==0.1.7
|
||||||
janus==1.0.0
|
janus==1.0.0
|
||||||
jinja2==3.1.2
|
jinja2==3.1.2
|
||||||
lru-dict==1.1.8
|
lru-dict==1.1.8
|
||||||
orjson==3.8.6
|
orjson==3.8.7
|
||||||
paho-mqtt==1.6.1
|
paho-mqtt==1.6.1
|
||||||
pillow==9.4.0
|
pillow==9.4.0
|
||||||
pip>=21.0,<23.1
|
pip>=21.0,<23.1
|
||||||
@ -40,7 +40,7 @@ pyserial==3.5
|
|||||||
python-slugify==4.0.1
|
python-slugify==4.0.1
|
||||||
pyudev==0.23.2
|
pyudev==0.23.2
|
||||||
pyyaml==6.0
|
pyyaml==6.0
|
||||||
requests==2.28.1
|
requests==2.28.2
|
||||||
scapy==2.5.0
|
scapy==2.5.0
|
||||||
sqlalchemy==2.0.4
|
sqlalchemy==2.0.4
|
||||||
typing-extensions>=4.5.0,<5.0
|
typing-extensions>=4.5.0,<5.0
|
||||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "homeassistant"
|
name = "homeassistant"
|
||||||
version = "2023.3.0"
|
version = "2023.3.1"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
description = "Open-source home automation platform running on Python 3."
|
description = "Open-source home automation platform running on Python 3."
|
||||||
readme = "README.rst"
|
readme = "README.rst"
|
||||||
@ -44,11 +44,11 @@ dependencies = [
|
|||||||
"cryptography==39.0.1",
|
"cryptography==39.0.1",
|
||||||
# pyOpenSSL 23.0.0 is required to work with cryptography 39+
|
# pyOpenSSL 23.0.0 is required to work with cryptography 39+
|
||||||
"pyOpenSSL==23.0.0",
|
"pyOpenSSL==23.0.0",
|
||||||
"orjson==3.8.6",
|
"orjson==3.8.7",
|
||||||
"pip>=21.0,<23.1",
|
"pip>=21.0,<23.1",
|
||||||
"python-slugify==4.0.1",
|
"python-slugify==4.0.1",
|
||||||
"pyyaml==6.0",
|
"pyyaml==6.0",
|
||||||
"requests==2.28.1",
|
"requests==2.28.2",
|
||||||
"typing-extensions>=4.5.0,<5.0",
|
"typing-extensions>=4.5.0,<5.0",
|
||||||
"voluptuous==0.13.1",
|
"voluptuous==0.13.1",
|
||||||
"voluptuous-serialize==2.6.0",
|
"voluptuous-serialize==2.6.0",
|
||||||
|
@ -18,11 +18,11 @@ lru-dict==1.1.8
|
|||||||
PyJWT==2.5.0
|
PyJWT==2.5.0
|
||||||
cryptography==39.0.1
|
cryptography==39.0.1
|
||||||
pyOpenSSL==23.0.0
|
pyOpenSSL==23.0.0
|
||||||
orjson==3.8.6
|
orjson==3.8.7
|
||||||
pip>=21.0,<23.1
|
pip>=21.0,<23.1
|
||||||
python-slugify==4.0.1
|
python-slugify==4.0.1
|
||||||
pyyaml==6.0
|
pyyaml==6.0
|
||||||
requests==2.28.1
|
requests==2.28.2
|
||||||
typing-extensions>=4.5.0,<5.0
|
typing-extensions>=4.5.0,<5.0
|
||||||
voluptuous==0.13.1
|
voluptuous==0.13.1
|
||||||
voluptuous-serialize==2.6.0
|
voluptuous-serialize==2.6.0
|
||||||
|
@ -907,7 +907,7 @@ hole==0.8.0
|
|||||||
holidays==0.18.0
|
holidays==0.18.0
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20230301.0
|
home-assistant-frontend==20230302.0
|
||||||
|
|
||||||
# homeassistant.components.conversation
|
# homeassistant.components.conversation
|
||||||
home-assistant-intents==2023.2.28
|
home-assistant-intents==2023.2.28
|
||||||
@ -1225,7 +1225,7 @@ nsapi==3.0.5
|
|||||||
nsw-fuel-api-client==1.1.0
|
nsw-fuel-api-client==1.1.0
|
||||||
|
|
||||||
# homeassistant.components.nuheat
|
# homeassistant.components.nuheat
|
||||||
nuheat==1.0.0
|
nuheat==1.0.1
|
||||||
|
|
||||||
# homeassistant.components.numato
|
# homeassistant.components.numato
|
||||||
numato-gpio==0.10.0
|
numato-gpio==0.10.0
|
||||||
@ -1430,7 +1430,7 @@ py-canary==0.5.3
|
|||||||
py-cpuinfo==8.0.0
|
py-cpuinfo==8.0.0
|
||||||
|
|
||||||
# homeassistant.components.dormakaba_dkey
|
# homeassistant.components.dormakaba_dkey
|
||||||
py-dormakaba-dkey==1.0.3
|
py-dormakaba-dkey==1.0.4
|
||||||
|
|
||||||
# homeassistant.components.melissa
|
# homeassistant.components.melissa
|
||||||
py-melissa-climate==2.1.4
|
py-melissa-climate==2.1.4
|
||||||
@ -1473,7 +1473,7 @@ pyRFXtrx==0.30.1
|
|||||||
pySwitchmate==0.5.1
|
pySwitchmate==0.5.1
|
||||||
|
|
||||||
# homeassistant.components.tibber
|
# homeassistant.components.tibber
|
||||||
pyTibber==0.26.13
|
pyTibber==0.27.0
|
||||||
|
|
||||||
# homeassistant.components.dlink
|
# homeassistant.components.dlink
|
||||||
pyW215==0.7.0
|
pyW215==0.7.0
|
||||||
|
@ -690,7 +690,7 @@ hole==0.8.0
|
|||||||
holidays==0.18.0
|
holidays==0.18.0
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20230301.0
|
home-assistant-frontend==20230302.0
|
||||||
|
|
||||||
# homeassistant.components.conversation
|
# homeassistant.components.conversation
|
||||||
home-assistant-intents==2023.2.28
|
home-assistant-intents==2023.2.28
|
||||||
@ -903,7 +903,7 @@ notify-events==1.0.4
|
|||||||
nsw-fuel-api-client==1.1.0
|
nsw-fuel-api-client==1.1.0
|
||||||
|
|
||||||
# homeassistant.components.nuheat
|
# homeassistant.components.nuheat
|
||||||
nuheat==1.0.0
|
nuheat==1.0.1
|
||||||
|
|
||||||
# homeassistant.components.numato
|
# homeassistant.components.numato
|
||||||
numato-gpio==0.10.0
|
numato-gpio==0.10.0
|
||||||
@ -1045,7 +1045,7 @@ py-canary==0.5.3
|
|||||||
py-cpuinfo==8.0.0
|
py-cpuinfo==8.0.0
|
||||||
|
|
||||||
# homeassistant.components.dormakaba_dkey
|
# homeassistant.components.dormakaba_dkey
|
||||||
py-dormakaba-dkey==1.0.3
|
py-dormakaba-dkey==1.0.4
|
||||||
|
|
||||||
# homeassistant.components.melissa
|
# homeassistant.components.melissa
|
||||||
py-melissa-climate==2.1.4
|
py-melissa-climate==2.1.4
|
||||||
@ -1076,7 +1076,7 @@ pyMetno==0.9.0
|
|||||||
pyRFXtrx==0.30.1
|
pyRFXtrx==0.30.1
|
||||||
|
|
||||||
# homeassistant.components.tibber
|
# homeassistant.components.tibber
|
||||||
pyTibber==0.26.13
|
pyTibber==0.27.0
|
||||||
|
|
||||||
# homeassistant.components.dlink
|
# homeassistant.components.dlink
|
||||||
pyW215==0.7.0
|
pyW215==0.7.0
|
||||||
|
@ -77,16 +77,17 @@ def patch_file_upload(return_value=FIXTURE_KEYRING, side_effect=None):
|
|||||||
side_effect=side_effect,
|
side_effect=side_effect,
|
||||||
), patch(
|
), patch(
|
||||||
"pathlib.Path.mkdir"
|
"pathlib.Path.mkdir"
|
||||||
) as mkdir_mock:
|
) as mkdir_mock, patch(
|
||||||
file_path_mock = Mock()
|
"shutil.move"
|
||||||
file_upload_mock.return_value.__enter__.return_value = file_path_mock
|
) as shutil_move_mock:
|
||||||
|
file_upload_mock.return_value.__enter__.return_value = Mock()
|
||||||
yield return_value
|
yield return_value
|
||||||
if side_effect:
|
if side_effect:
|
||||||
mkdir_mock.assert_not_called()
|
mkdir_mock.assert_not_called()
|
||||||
file_path_mock.rename.assert_not_called()
|
shutil_move_mock.assert_not_called()
|
||||||
else:
|
else:
|
||||||
mkdir_mock.assert_called_once()
|
mkdir_mock.assert_called_once()
|
||||||
file_path_mock.rename.assert_called_once()
|
shutil_move_mock.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
def _gateway_descriptor(
|
def _gateway_descriptor(
|
||||||
|
@ -205,6 +205,47 @@ async def test_datetime_conversion(
|
|||||||
assert state.state == test_timestamp.isoformat()
|
assert state.state == test_timestamp.isoformat()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_a_sensor_with_a_non_numeric_device_class(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
enable_custom_integrations: None,
|
||||||
|
) -> None:
|
||||||
|
"""Test that a sensor with a non numeric device class will be non numeric.
|
||||||
|
|
||||||
|
A non numeric sensor with a valid device class should never be
|
||||||
|
handled as numeric because it has a device class.
|
||||||
|
"""
|
||||||
|
test_timestamp = datetime(2017, 12, 19, 18, 29, 42, tzinfo=timezone.utc)
|
||||||
|
test_local_timestamp = test_timestamp.astimezone(
|
||||||
|
dt_util.get_time_zone("Europe/Amsterdam")
|
||||||
|
)
|
||||||
|
|
||||||
|
platform = getattr(hass.components, "test.sensor")
|
||||||
|
platform.init(empty=True)
|
||||||
|
platform.ENTITIES["0"] = platform.MockSensor(
|
||||||
|
name="Test",
|
||||||
|
native_value=test_local_timestamp,
|
||||||
|
native_unit_of_measurement="",
|
||||||
|
device_class=SensorDeviceClass.TIMESTAMP,
|
||||||
|
)
|
||||||
|
|
||||||
|
platform.ENTITIES["1"] = platform.MockSensor(
|
||||||
|
name="Test",
|
||||||
|
native_value=test_local_timestamp,
|
||||||
|
state_class="",
|
||||||
|
device_class=SensorDeviceClass.TIMESTAMP,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(platform.ENTITIES["0"].entity_id)
|
||||||
|
assert state.state == test_timestamp.isoformat()
|
||||||
|
|
||||||
|
state = hass.states.get(platform.ENTITIES["1"].entity_id)
|
||||||
|
assert state.state == test_timestamp.isoformat()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("device_class", "state_value", "provides"),
|
("device_class", "state_value", "provides"),
|
||||||
[
|
[
|
||||||
|
Loading…
x
Reference in New Issue
Block a user