1
mirror of https://github.com/home-assistant/core synced 2024-08-06 09:34:49 +02:00

Fritzbox enable temp sensor (#52558)

This commit is contained in:
Michael 2021-07-22 18:19:39 +02:00 committed by GitHub
parent 258162d933
commit 24e07bc154
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 205 additions and 63 deletions

View File

@ -6,6 +6,7 @@ from datetime import timedelta
from pyfritzhome import Fritzhome, FritzhomeDevice, LoginError
import requests
from homeassistant.components.sensor import ATTR_STATE_CLASS
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_DEVICE_CLASS,
@ -16,10 +17,12 @@ from homeassistant.const import (
CONF_PASSWORD,
CONF_USERNAME,
EVENT_HOMEASSISTANT_STOP,
TEMP_CELSIUS,
)
from homeassistant.core import Event, HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_registry import RegistryEntry, async_migrate_entries
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
@ -81,6 +84,21 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await coordinator.async_config_entry_first_refresh()
def _update_unique_id(entry: RegistryEntry) -> dict[str, str] | None:
"""Update unique ID of entity entry."""
if (
entry.unit_of_measurement == TEMP_CELSIUS
and "_temperature" not in entry.unique_id
):
new_unique_id = f"{entry.unique_id}_temperature"
LOGGER.info(
"Migrating unique_id [%s] to [%s]", entry.unique_id, new_unique_id
)
return {"new_unique_id": new_unique_id}
return None
await async_migrate_entries(hass, entry.entry_id, _update_unique_id)
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
def logout_fritzbox(event: Event) -> None:
@ -123,6 +141,7 @@ class FritzBoxEntity(CoordinatorEntity):
self._unique_id = entity_info[ATTR_ENTITY_ID]
self._unit_of_measurement = entity_info[ATTR_UNIT_OF_MEASUREMENT]
self._device_class = entity_info[ATTR_DEVICE_CLASS]
self._attr_state_class = entity_info[ATTR_STATE_CLASS]
@property
def device(self) -> FritzhomeDevice:

View File

@ -5,6 +5,7 @@ from homeassistant.components.binary_sensor import (
DEVICE_CLASS_WINDOW,
BinarySensorEntity,
)
from homeassistant.components.sensor import ATTR_STATE_CLASS
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_DEVICE_CLASS,
@ -37,6 +38,7 @@ async def async_setup_entry(
ATTR_ENTITY_ID: f"{device.ain}",
ATTR_UNIT_OF_MEASUREMENT: None,
ATTR_DEVICE_CLASS: DEVICE_CLASS_WINDOW,
ATTR_STATE_CLASS: None,
},
coordinator,
ain,

View File

@ -13,6 +13,7 @@ from homeassistant.components.climate.const import (
SUPPORT_PRESET_MODE,
SUPPORT_TARGET_TEMPERATURE,
)
from homeassistant.components.sensor import ATTR_STATE_CLASS
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_BATTERY_LEVEL,
@ -74,6 +75,7 @@ async def async_setup_entry(
ATTR_ENTITY_ID: f"{device.ain}",
ATTR_UNIT_OF_MEASUREMENT: None,
ATTR_DEVICE_CLASS: None,
ATTR_STATE_CLASS: None,
},
coordinator,
ain,

View File

@ -11,6 +11,7 @@ class EntityInfo(TypedDict):
entity_id: str
unit_of_measurement: str | None
device_class: str | None
state_class: str | None
class ClimateExtraAttributes(TypedDict, total=False):

View File

@ -1,7 +1,11 @@
"""Support for AVM FRITZ!SmartHome temperature sensor only devices."""
from __future__ import annotations
from homeassistant.components.sensor import SensorEntity
from homeassistant.components.sensor import (
ATTR_STATE_CLASS,
STATE_CLASS_MEASUREMENT,
SensorEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_DEVICE_CLASS,
@ -34,18 +38,15 @@ async def async_setup_entry(
coordinator = hass.data[FRITZBOX_DOMAIN][entry.entry_id][CONF_COORDINATOR]
for ain, device in coordinator.data.items():
if (
device.has_temperature_sensor
and not device.has_switch
and not device.has_thermostat
):
if device.has_temperature_sensor and not device.has_thermostat:
entities.append(
FritzBoxTempSensor(
{
ATTR_NAME: f"{device.name}",
ATTR_ENTITY_ID: f"{device.ain}",
ATTR_NAME: f"{device.name} Temperature",
ATTR_ENTITY_ID: f"{device.ain}_temperature",
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
},
coordinator,
ain,
@ -60,6 +61,7 @@ async def async_setup_entry(
ATTR_ENTITY_ID: f"{device.ain}_battery",
ATTR_UNIT_OF_MEASUREMENT: PERCENTAGE,
ATTR_DEVICE_CLASS: DEVICE_CLASS_BATTERY,
ATTR_STATE_CLASS: None,
},
coordinator,
ain,

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from typing import Any
from homeassistant.components.sensor import ATTR_STATE_CLASS
from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
@ -50,6 +51,7 @@ async def async_setup_entry(
ATTR_ENTITY_ID: f"{device.ain}",
ATTR_UNIT_OF_MEASUREMENT: None,
ATTR_DEVICE_CLASS: None,
ATTR_STATE_CLASS: None,
},
coordinator,
ain,

View File

@ -5,22 +5,16 @@ from typing import Any
from unittest.mock import Mock
from homeassistant.components.fritzbox.const import DOMAIN
from homeassistant.const import CONF_DEVICES, CONF_HOST, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
from .const import (
CONF_FAKE_AIN,
CONF_FAKE_MANUFACTURER,
CONF_FAKE_NAME,
CONF_FAKE_PRODUCTNAME,
)
MOCK_CONFIG = {
DOMAIN: {
CONF_DEVICES: [
{
CONF_HOST: "fake_host",
CONF_PASSWORD: "fake_pass",
CONF_USERNAME: "fake_user",
}
]
}
}
from tests.common import MockConfigEntry
async def setup_config_entry(
@ -45,27 +39,32 @@ async def setup_config_entry(
return result
class FritzDeviceBinarySensorMock(Mock):
class FritzDeviceBaseMock(Mock):
"""base mock of a AVM Fritz!Box binary sensor device."""
ain = CONF_FAKE_AIN
manufacturer = CONF_FAKE_MANUFACTURER
name = CONF_FAKE_NAME
productname = CONF_FAKE_PRODUCTNAME
class FritzDeviceBinarySensorMock(FritzDeviceBaseMock):
"""Mock of a AVM Fritz!Box binary sensor device."""
ain = "fake_ain"
alert_state = "fake_state"
battery_level = 23
fw_version = "1.2.3"
has_alarm = True
has_switch = False
has_temperature_sensor = False
has_thermostat = False
manufacturer = "fake_manufacturer"
name = "fake_name"
present = True
productname = "fake_productname"
class FritzDeviceClimateMock(Mock):
class FritzDeviceClimateMock(FritzDeviceBaseMock):
"""Mock of a AVM Fritz!Box climate device."""
actual_temperature = 18.0
ain = "fake_ain"
alert_state = "fake_state"
battery_level = 23
battery_low = True
@ -79,19 +78,15 @@ class FritzDeviceClimateMock(Mock):
has_thermostat = True
holiday_active = "fake_holiday"
lock = "fake_locked"
manufacturer = "fake_manufacturer"
name = "fake_name"
present = True
productname = "fake_productname"
summer_active = "fake_summer"
target_temperature = 19.5
window_open = "fake_window"
class FritzDeviceSensorMock(Mock):
class FritzDeviceSensorMock(FritzDeviceBaseMock):
"""Mock of a AVM Fritz!Box sensor device."""
ain = "fake_ain"
battery_level = 23
device_lock = "fake_locked_device"
fw_version = "1.2.3"
@ -100,17 +95,14 @@ class FritzDeviceSensorMock(Mock):
has_temperature_sensor = True
has_thermostat = False
lock = "fake_locked"
manufacturer = "fake_manufacturer"
name = "fake_name"
present = True
productname = "fake_productname"
temperature = 1.23
class FritzDeviceSwitchMock(Mock):
class FritzDeviceSwitchMock(FritzDeviceBaseMock):
"""Mock of a AVM Fritz!Box switch device."""
ain = "fake_ain"
battery_level = None
device_lock = "fake_locked_device"
energy = 1234
fw_version = "1.2.3"
@ -120,9 +112,6 @@ class FritzDeviceSwitchMock(Mock):
has_thermostat = False
switch_state = "fake_state"
lock = "fake_locked"
manufacturer = "fake_manufacturer"
name = "fake_name"
power = 5678
present = True
productname = "fake_productname"
temperature = 135
temperature = 1.23

View File

@ -0,0 +1,20 @@
"""Constants for fritzbox tests."""
from homeassistant.components.fritzbox.const import DOMAIN
from homeassistant.const import CONF_DEVICES, CONF_HOST, CONF_PASSWORD, CONF_USERNAME
MOCK_CONFIG = {
DOMAIN: {
CONF_DEVICES: [
{
CONF_HOST: "fake_host",
CONF_PASSWORD: "fake_pass",
CONF_USERNAME: "fake_user",
}
]
}
}
CONF_FAKE_NAME = "fake_name"
CONF_FAKE_AIN = "fake_ain"
CONF_FAKE_MANUFACTURER = "fake_manufacturer"
CONF_FAKE_PRODUCTNAME = "fake_productname"

View File

@ -7,21 +7,25 @@ from requests.exceptions import HTTPError
from homeassistant.components.binary_sensor import DOMAIN
from homeassistant.components.fritzbox.const import DOMAIN as FB_DOMAIN
from homeassistant.components.sensor import ATTR_STATE_CLASS, DOMAIN as SENSOR_DOMAIN
from homeassistant.const import (
ATTR_DEVICE_CLASS,
ATTR_FRIENDLY_NAME,
ATTR_UNIT_OF_MEASUREMENT,
CONF_DEVICES,
PERCENTAGE,
STATE_OFF,
STATE_ON,
)
from homeassistant.core import HomeAssistant
import homeassistant.util.dt as dt_util
from . import MOCK_CONFIG, FritzDeviceBinarySensorMock, setup_config_entry
from . import FritzDeviceBinarySensorMock, setup_config_entry
from .const import CONF_FAKE_NAME, MOCK_CONFIG
from tests.common import async_fire_time_changed
ENTITY_ID = f"{DOMAIN}.fake_name"
ENTITY_ID = f"{DOMAIN}.{CONF_FAKE_NAME}"
async def test_setup(hass: HomeAssistant, fritz: Mock):
@ -34,8 +38,16 @@ async def test_setup(hass: HomeAssistant, fritz: Mock):
state = hass.states.get(ENTITY_ID)
assert state
assert state.state == STATE_ON
assert state.attributes[ATTR_FRIENDLY_NAME] == "fake_name"
assert state.attributes[ATTR_FRIENDLY_NAME] == CONF_FAKE_NAME
assert state.attributes[ATTR_DEVICE_CLASS] == "window"
assert ATTR_STATE_CLASS not in state.attributes
state = hass.states.get(f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_battery")
assert state
assert state.state == "23"
assert state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Battery"
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == PERCENTAGE
assert ATTR_STATE_CLASS not in state.attributes
async def test_is_off(hass: HomeAssistant, fritz: Mock):

View File

@ -30,21 +30,25 @@ from homeassistant.components.fritzbox.const import (
ATTR_STATE_WINDOW_OPEN,
DOMAIN as FB_DOMAIN,
)
from homeassistant.components.sensor import ATTR_STATE_CLASS, DOMAIN as SENSOR_DOMAIN
from homeassistant.const import (
ATTR_BATTERY_LEVEL,
ATTR_ENTITY_ID,
ATTR_FRIENDLY_NAME,
ATTR_TEMPERATURE,
ATTR_UNIT_OF_MEASUREMENT,
CONF_DEVICES,
PERCENTAGE,
)
from homeassistant.core import HomeAssistant
import homeassistant.util.dt as dt_util
from . import MOCK_CONFIG, FritzDeviceClimateMock, setup_config_entry
from . import FritzDeviceClimateMock, setup_config_entry
from .const import CONF_FAKE_NAME, MOCK_CONFIG
from tests.common import async_fire_time_changed
ENTITY_ID = f"{DOMAIN}.fake_name"
ENTITY_ID = f"{DOMAIN}.{CONF_FAKE_NAME}"
async def test_setup(hass: HomeAssistant, fritz: Mock):
@ -58,7 +62,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock):
assert state
assert state.attributes[ATTR_BATTERY_LEVEL] == 23
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 18
assert state.attributes[ATTR_FRIENDLY_NAME] == "fake_name"
assert state.attributes[ATTR_FRIENDLY_NAME] == CONF_FAKE_NAME
assert state.attributes[ATTR_HVAC_MODES] == [HVAC_MODE_HEAT, HVAC_MODE_OFF]
assert state.attributes[ATTR_MAX_TEMP] == 28
assert state.attributes[ATTR_MIN_TEMP] == 8
@ -71,8 +75,16 @@ async def test_setup(hass: HomeAssistant, fritz: Mock):
assert state.attributes[ATTR_STATE_SUMMER_MODE] == "fake_summer"
assert state.attributes[ATTR_STATE_WINDOW_OPEN] == "fake_window"
assert state.attributes[ATTR_TEMPERATURE] == 19.5
assert ATTR_STATE_CLASS not in state.attributes
assert state.state == HVAC_MODE_HEAT
state = hass.states.get(f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_battery")
assert state
assert state.state == "23"
assert state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Battery"
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == PERCENTAGE
assert ATTR_STATE_CLASS not in state.attributes
async def test_target_temperature_on(hass: HomeAssistant, fritz: Mock):
"""Test turn device on."""

View File

@ -21,14 +21,14 @@ from homeassistant.data_entry_flow import (
RESULT_TYPE_FORM,
)
from . import MOCK_CONFIG
from .const import CONF_FAKE_NAME, MOCK_CONFIG
from tests.common import MockConfigEntry
MOCK_USER_DATA = MOCK_CONFIG[DOMAIN][CONF_DEVICES][0]
MOCK_SSDP_DATA = {
ATTR_SSDP_LOCATION: "https://fake_host:12345/test",
ATTR_UPNP_FRIENDLY_NAME: "fake_name",
ATTR_UPNP_FRIENDLY_NAME: CONF_FAKE_NAME,
ATTR_UPNP_UDN: "uuid:only-a-test",
}
@ -192,7 +192,7 @@ async def test_ssdp(hass: HomeAssistant, fritz: Mock):
user_input={CONF_PASSWORD: "fake_pass", CONF_USERNAME: "fake_user"},
)
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
assert result["title"] == "fake_name"
assert result["title"] == CONF_FAKE_NAME
assert result["data"][CONF_HOST] == "fake_host"
assert result["data"][CONF_PASSWORD] == "fake_pass"
assert result["data"][CONF_USERNAME] == "fake_user"

View File

@ -7,6 +7,7 @@ from pyfritzhome import LoginError
from requests.exceptions import HTTPError
from homeassistant.components.fritzbox.const import DOMAIN as FB_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import (
@ -15,10 +16,13 @@ from homeassistant.const import (
CONF_PASSWORD,
CONF_USERNAME,
STATE_UNAVAILABLE,
TEMP_CELSIUS,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import MOCK_CONFIG, FritzDeviceSwitchMock, setup_config_entry
from . import FritzDeviceSwitchMock, setup_config_entry
from .const import CONF_FAKE_AIN, CONF_FAKE_NAME, MOCK_CONFIG
from tests.common import MockConfigEntry
@ -38,6 +42,58 @@ async def test_setup(hass: HomeAssistant, fritz: Mock):
]
async def test_update_unique_id(hass: HomeAssistant, fritz: Mock):
"""Test unique_id update of integration."""
entry = MockConfigEntry(
domain=FB_DOMAIN,
data=MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0],
unique_id="any",
)
entry.add_to_hass(hass)
entity_registry = er.async_get(hass)
entity = entity_registry.async_get_or_create(
SENSOR_DOMAIN,
FB_DOMAIN,
CONF_FAKE_AIN,
unit_of_measurement=TEMP_CELSIUS,
config_entry=entry,
)
assert entity.unique_id == CONF_FAKE_AIN
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
entity_migrated = entity_registry.async_get(entity.entity_id)
assert entity_migrated
assert entity_migrated.unique_id == f"{CONF_FAKE_AIN}_temperature"
async def test_update_unique_id_no_change(hass: HomeAssistant, fritz: Mock):
"""Test unique_id is not updated of integration."""
entry = MockConfigEntry(
domain=FB_DOMAIN,
data=MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0],
unique_id="any",
)
entry.add_to_hass(hass)
entity_registry = er.async_get(hass)
entity = entity_registry.async_get_or_create(
SENSOR_DOMAIN,
FB_DOMAIN,
f"{CONF_FAKE_AIN}_temperature",
unit_of_measurement=TEMP_CELSIUS,
config_entry=entry,
)
assert entity.unique_id == f"{CONF_FAKE_AIN}_temperature"
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
entity_migrated = entity_registry.async_get(entity.entity_id)
assert entity_migrated
assert entity_migrated.unique_id == f"{CONF_FAKE_AIN}_temperature"
async def test_coordinator_update_after_reboot(hass: HomeAssistant, fritz: Mock):
"""Test coordinator after reboot."""
entry = MockConfigEntry(
@ -74,7 +130,7 @@ async def test_coordinator_update_after_password_change(
async def test_unload_remove(hass: HomeAssistant, fritz: Mock):
"""Test unload and remove of integration."""
fritz().get_devices.return_value = [FritzDeviceSwitchMock()]
entity_id = f"{SWITCH_DOMAIN}.fake_name"
entity_id = f"{SWITCH_DOMAIN}.{CONF_FAKE_NAME}"
entry = MockConfigEntry(
domain=FB_DOMAIN,

View File

@ -9,7 +9,11 @@ from homeassistant.components.fritzbox.const import (
ATTR_STATE_LOCKED,
DOMAIN as FB_DOMAIN,
)
from homeassistant.components.sensor import DOMAIN
from homeassistant.components.sensor import (
ATTR_STATE_CLASS,
DOMAIN,
STATE_CLASS_MEASUREMENT,
)
from homeassistant.const import (
ATTR_FRIENDLY_NAME,
ATTR_UNIT_OF_MEASUREMENT,
@ -20,11 +24,12 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant
import homeassistant.util.dt as dt_util
from . import MOCK_CONFIG, FritzDeviceSensorMock, setup_config_entry
from . import FritzDeviceSensorMock, setup_config_entry
from .const import CONF_FAKE_NAME, MOCK_CONFIG
from tests.common import async_fire_time_changed
ENTITY_ID = f"{DOMAIN}.fake_name"
ENTITY_ID = f"{DOMAIN}.{CONF_FAKE_NAME}"
async def test_setup(hass: HomeAssistant, fritz: Mock):
@ -33,20 +38,23 @@ async def test_setup(hass: HomeAssistant, fritz: Mock):
assert await setup_config_entry(
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
state = hass.states.get(f"{ENTITY_ID}_temperature")
assert state
assert state.state == "1.23"
assert state.attributes[ATTR_FRIENDLY_NAME] == "fake_name"
assert state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Temperature"
assert state.attributes[ATTR_STATE_DEVICE_LOCKED] == "fake_locked_device"
assert state.attributes[ATTR_STATE_LOCKED] == "fake_locked"
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == TEMP_CELSIUS
assert state.attributes[ATTR_STATE_CLASS] == STATE_CLASS_MEASUREMENT
state = hass.states.get(f"{ENTITY_ID}_battery")
assert state
assert state.state == "23"
assert state.attributes[ATTR_FRIENDLY_NAME] == "fake_name Battery"
assert state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Battery"
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == PERCENTAGE
assert ATTR_STATE_CLASS not in state.attributes
async def test_update(hass: HomeAssistant, fritz: Mock):

View File

@ -12,11 +12,17 @@ from homeassistant.components.fritzbox.const import (
ATTR_TOTAL_CONSUMPTION_UNIT,
DOMAIN as FB_DOMAIN,
)
from homeassistant.components.sensor import (
ATTR_STATE_CLASS,
DOMAIN as SENSOR_DOMAIN,
STATE_CLASS_MEASUREMENT,
)
from homeassistant.components.switch import ATTR_CURRENT_POWER_W, DOMAIN
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_FRIENDLY_NAME,
ATTR_TEMPERATURE,
ATTR_UNIT_OF_MEASUREMENT,
CONF_DEVICES,
ENERGY_KILO_WATT_HOUR,
SERVICE_TURN_OFF,
@ -27,11 +33,12 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant
import homeassistant.util.dt as dt_util
from . import MOCK_CONFIG, FritzDeviceSwitchMock, setup_config_entry
from . import FritzDeviceSwitchMock, setup_config_entry
from .const import CONF_FAKE_NAME, MOCK_CONFIG
from tests.common import async_fire_time_changed
ENTITY_ID = f"{DOMAIN}.fake_name"
ENTITY_ID = f"{DOMAIN}.{CONF_FAKE_NAME}"
async def test_setup(hass: HomeAssistant, fritz: Mock):
@ -45,13 +52,23 @@ async def test_setup(hass: HomeAssistant, fritz: Mock):
assert state
assert state.state == STATE_ON
assert state.attributes[ATTR_CURRENT_POWER_W] == 5.678
assert state.attributes[ATTR_FRIENDLY_NAME] == "fake_name"
assert state.attributes[ATTR_FRIENDLY_NAME] == CONF_FAKE_NAME
assert state.attributes[ATTR_STATE_DEVICE_LOCKED] == "fake_locked_device"
assert state.attributes[ATTR_STATE_LOCKED] == "fake_locked"
assert state.attributes[ATTR_TEMPERATURE] == "135"
assert state.attributes[ATTR_TEMPERATURE] == "1.23"
assert state.attributes[ATTR_TEMPERATURE_UNIT] == TEMP_CELSIUS
assert state.attributes[ATTR_TOTAL_CONSUMPTION] == "1.234"
assert state.attributes[ATTR_TOTAL_CONSUMPTION_UNIT] == ENERGY_KILO_WATT_HOUR
assert ATTR_STATE_CLASS not in state.attributes
state = hass.states.get(f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_temperature")
assert state
assert state.state == "1.23"
assert state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Temperature"
assert state.attributes[ATTR_STATE_DEVICE_LOCKED] == "fake_locked_device"
assert state.attributes[ATTR_STATE_LOCKED] == "fake_locked"
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == TEMP_CELSIUS
assert state.attributes[ATTR_STATE_CLASS] == STATE_CLASS_MEASUREMENT
async def test_turn_on(hass: HomeAssistant, fritz: Mock):