Enable strict type checks for onewire (#50422)

This commit is contained in:
epenet 2021-05-11 17:28:17 +02:00 committed by GitHub
parent efa5c59559
commit d6c99a3db9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 202 additions and 84 deletions

View File

@ -31,6 +31,7 @@ homeassistant.components.media_player.*
homeassistant.components.nam.*
homeassistant.components.notify.*
homeassistant.components.number.*
homeassistant.components.onewire.*
homeassistant.components.persistent_notification.*
homeassistant.components.proximity.*
homeassistant.components.recorder.purge

View File

@ -13,7 +13,7 @@ from .onewirehub import CannotConnect, OneWireHub
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry):
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Set up a 1-Wire proxy for a config entry."""
hass.data.setdefault(DOMAIN, {})
@ -65,7 +65,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry):
return True
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry):
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(
config_entry, PLATFORMS

View File

@ -1,14 +1,21 @@
"""Support for 1-Wire binary sensors."""
from __future__ import annotations
import os
from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_TYPE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import CONF_TYPE_OWSERVER, DOMAIN, SENSOR_TYPE_SENSED
from .onewire_entities import OneWireProxyEntity
from .model import DeviceComponentDescription
from .onewire_entities import OneWireBaseEntity, OneWireProxyEntity
from .onewirehub import OneWireHub
DEVICE_BINARY_SENSORS = {
DEVICE_BINARY_SENSORS: dict[str, list[DeviceComponentDescription]] = {
# Family : { path, sensor_type }
"12": [
{
@ -77,7 +84,11 @@ DEVICE_BINARY_SENSORS = {
}
async def async_setup_entry(hass, config_entry, async_add_entities):
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up 1-Wire platform."""
# Only OWServer implementation works with binary sensors
if config_entry.data[CONF_TYPE] == CONF_TYPE_OWSERVER:
@ -87,9 +98,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async_add_entities(entities, True)
def get_entities(onewirehub: OneWireHub):
def get_entities(onewirehub: OneWireHub) -> list[OneWireBaseEntity]:
"""Get a list of entities."""
entities = []
if not onewirehub.devices:
return []
entities: list[OneWireBaseEntity] = []
for device in onewirehub.devices:
family = device["family"]
@ -98,7 +112,7 @@ def get_entities(onewirehub: OneWireHub):
if family not in DEVICE_BINARY_SENSORS:
continue
device_info = {
device_info: DeviceInfo = {
"identifiers": {(DOMAIN, device_id)},
"manufacturer": "Maxim Integrated",
"model": device_type,
@ -126,6 +140,6 @@ class OneWireProxyBinarySensor(OneWireProxyEntity, BinarySensorEntity):
"""Implementation of a 1-Wire binary sensor."""
@property
def is_on(self):
def is_on(self) -> bool:
"""Return true if sensor is on."""
return self._state
return bool(self._state)

View File

@ -1,9 +1,14 @@
"""Config flow for 1-Wire component."""
from __future__ import annotations
from typing import Any
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TYPE
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult
from .const import (
CONF_MOUNT_DIR,
@ -32,7 +37,9 @@ DATA_SCHEMA_MOUNTDIR = vol.Schema(
)
async def validate_input_owserver(hass: HomeAssistant, data):
async def validate_input_owserver(
hass: HomeAssistant, data: dict[str, Any]
) -> dict[str, str]:
"""Validate the user input allows us to connect.
Data has the keys from DATA_SCHEMA_OWSERVER with values provided by the user.
@ -49,7 +56,9 @@ async def validate_input_owserver(hass: HomeAssistant, data):
return {"title": host}
def is_duplicate_owserver_entry(hass: HomeAssistant, user_input):
def is_duplicate_owserver_entry(
hass: HomeAssistant, user_input: dict[str, Any]
) -> bool:
"""Check existing entries for matching host and port."""
for config_entry in hass.config_entries.async_entries(DOMAIN):
if (
@ -61,7 +70,9 @@ def is_duplicate_owserver_entry(hass: HomeAssistant, user_input):
return False
async def validate_input_mount_dir(hass: HomeAssistant, data):
async def validate_input_mount_dir(
hass: HomeAssistant, data: dict[str, Any]
) -> dict[str, str]:
"""Validate the user input allows us to connect.
Data has the keys from DATA_SCHEMA_MOUNTDIR with values provided by the user.
@ -82,16 +93,18 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN):
VERSION = 1
def __init__(self):
def __init__(self) -> None:
"""Initialize 1-Wire config flow."""
self.onewire_config = {}
self.onewire_config: dict[str, Any] = {}
async def async_step_user(self, user_input=None):
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle 1-Wire config flow start.
Let user manually input configuration.
"""
errors = {}
errors: dict[str, str] = {}
if user_input is not None:
self.onewire_config.update(user_input)
if CONF_TYPE_OWSERVER == user_input[CONF_TYPE]:
@ -105,7 +118,9 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN):
errors=errors,
)
async def async_step_owserver(self, user_input=None):
async def async_step_owserver(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle OWServer configuration."""
errors = {}
if user_input:
@ -130,7 +145,9 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN):
errors=errors,
)
async def async_step_mount_dir(self, user_input=None):
async def async_step_mount_dir(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle SysBus configuration."""
errors = {}
if user_input:
@ -157,7 +174,7 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN):
errors=errors,
)
async def async_step_import(self, platform_config):
async def async_step_import(self, platform_config: dict[str, Any]) -> FlowResult:
"""Handle import configuration from YAML."""
# OWServer
if platform_config[CONF_TYPE] == CONF_TYPE_OWSERVER:

View File

@ -1,4 +1,6 @@
"""Constants for 1-Wire component."""
from __future__ import annotations
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
@ -44,7 +46,7 @@ SENSOR_TYPE_WETNESS = "wetness"
SWITCH_TYPE_LATCH = "latch"
SWITCH_TYPE_PIO = "pio"
SENSOR_TYPES = {
SENSOR_TYPES: dict[str, list[str | None]] = {
# SensorType: [ Unit, DeviceClass ]
SENSOR_TYPE_TEMPERATURE: [TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE],
SENSOR_TYPE_HUMIDITY: [PERCENTAGE, DEVICE_CLASS_HUMIDITY],

View File

@ -0,0 +1,21 @@
"""Type definitions for 1-Wire integration."""
from __future__ import annotations
from typing import TypedDict
class DeviceComponentDescription(TypedDict, total=False):
"""Device component description class."""
path: str
name: str
type: str
default_disabled: bool
class OWServerDeviceDescription(TypedDict):
"""OWServer device description class."""
path: str
family: str
type: str

View File

@ -7,6 +7,7 @@ from typing import Any
from pyownet import protocol
from homeassistant.helpers.entity import DeviceInfo, Entity
from homeassistant.helpers.typing import StateType
from .const import (
SENSOR_TYPE_COUNT,
@ -15,6 +16,7 @@ from .const import (
SWITCH_TYPE_LATCH,
SWITCH_TYPE_PIO,
)
from .model import DeviceComponentDescription
_LOGGER = logging.getLogger(__name__)
@ -24,13 +26,13 @@ class OneWireBaseEntity(Entity):
def __init__(
self,
name,
device_file,
name: str,
device_file: str,
entity_type: str,
entity_name: str = None,
device_info: DeviceInfo | None = None,
default_disabled: bool = False,
unique_id: str = None,
entity_name: str,
device_info: DeviceInfo,
default_disabled: bool,
unique_id: str,
):
"""Initialize the entity."""
self._name = f"{name} {entity_name or entity_type.capitalize()}"
@ -39,10 +41,10 @@ class OneWireBaseEntity(Entity):
self._device_class = SENSOR_TYPES[entity_type][1]
self._unit_of_measurement = SENSOR_TYPES[entity_type][0]
self._device_info = device_info
self._state = None
self._value_raw = None
self._state: StateType = None
self._value_raw: float | None = None
self._default_disabled = default_disabled
self._unique_id = unique_id or device_file
self._unique_id = unique_id
@property
def name(self) -> str | None:
@ -84,7 +86,7 @@ class OneWireProxyEntity(OneWireBaseEntity):
device_name: str,
device_info: DeviceInfo,
entity_path: str,
entity_specs: dict[str, Any],
entity_specs: DeviceComponentDescription,
owproxy: protocol._Proxy,
):
"""Initialize the sensor."""
@ -99,31 +101,30 @@ class OneWireProxyEntity(OneWireBaseEntity):
)
self._owproxy = owproxy
def _read_value_ownet(self):
def _read_value_ownet(self) -> str:
"""Read a value from the owserver."""
return self._owproxy.read(self._device_file).decode().lstrip()
read_bytes: bytes = self._owproxy.read(self._device_file)
return read_bytes.decode().lstrip()
def _write_value_ownet(self, value: bytes):
def _write_value_ownet(self, value: bytes) -> None:
"""Write a value to the owserver."""
return self._owproxy.write(self._device_file, value)
self._owproxy.write(self._device_file, value)
def update(self):
def update(self) -> None:
"""Get the latest data from the device."""
value = None
try:
self._value_raw = float(self._read_value_ownet())
except protocol.Error as exc:
_LOGGER.error("Owserver failure in read(), got: %s", exc)
self._state = None
else:
if self._entity_type == SENSOR_TYPE_COUNT:
value = int(self._value_raw)
self._state = int(self._value_raw)
elif self._entity_type in [
SENSOR_TYPE_SENSED,
SWITCH_TYPE_LATCH,
SWITCH_TYPE_PIO,
]:
value = int(self._value_raw) == 1
self._state = int(self._value_raw) == 1
else:
value = round(self._value_raw, 1)
self._state = value
self._state = round(self._value_raw, 1)

View File

@ -1,4 +1,6 @@
"""Hub for communication with 1-Wire server or mount_dir."""
from __future__ import annotations
import os
from pi1wire import Pi1Wire
@ -10,6 +12,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from .const import CONF_MOUNT_DIR, CONF_TYPE_OWSERVER, CONF_TYPE_SYSBUS
from .model import OWServerDeviceDescription
DEVICE_COUPLERS = {
# Family : [branches]
@ -23,10 +26,10 @@ class OneWireHub:
def __init__(self, hass: HomeAssistant):
"""Initialize."""
self.hass = hass
self.type: str = None
self.pi1proxy: Pi1Wire = None
self.owproxy: protocol._Proxy = None
self.devices = None
self.type: str | None = None
self.pi1proxy: Pi1Wire | None = None
self.owproxy: protocol._Proxy | None = None
self.devices: list | None = None
async def connect(self, host: str, port: int) -> None:
"""Connect to the owserver host."""
@ -54,10 +57,11 @@ class OneWireHub:
await self.connect(host, port)
await self.discover_devices()
async def discover_devices(self):
async def discover_devices(self) -> None:
"""Discover all devices."""
if self.devices is None:
if self.type == CONF_TYPE_SYSBUS:
assert self.pi1proxy
self.devices = await self.hass.async_add_executor_job(
self.pi1proxy.find_all_sensors
)
@ -65,11 +69,13 @@ class OneWireHub:
self.devices = await self.hass.async_add_executor_job(
self._discover_devices_owserver
)
return self.devices
def _discover_devices_owserver(self, path="/"):
def _discover_devices_owserver(
self, path: str = "/"
) -> list[OWServerDeviceDescription]:
"""Discover all owserver devices."""
devices = []
assert self.owproxy
for device_path in self.owproxy.dir(path):
device_family = self.owproxy.read(f"{device_path}family").decode()
device_type = self.owproxy.read(f"{device_path}type").decode()

View File

@ -4,15 +4,20 @@ from __future__ import annotations
import asyncio
import logging
import os
from types import MappingProxyType
from typing import Any
from pi1wire import InvalidCRCException, UnsupportResponseException
from pi1wire import InvalidCRCException, OneWireInterface, UnsupportResponseException
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.config_entries import SOURCE_IMPORT
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_TYPE
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import DiscoveryInfoType, StateType
from .const import (
CONF_MOUNT_DIR,
@ -32,12 +37,13 @@ from .const import (
SENSOR_TYPE_VOLTAGE,
SENSOR_TYPE_WETNESS,
)
from .model import DeviceComponentDescription
from .onewire_entities import OneWireBaseEntity, OneWireProxyEntity
from .onewirehub import OneWireHub
_LOGGER = logging.getLogger(__name__)
DEVICE_SENSORS = {
DEVICE_SENSORS: dict[str, list[DeviceComponentDescription]] = {
# Family : { SensorType: owfs path }
"10": [
{"path": "temperature", "name": "Temperature", "type": SENSOR_TYPE_TEMPERATURE}
@ -145,7 +151,7 @@ DEVICE_SUPPORT_SYSBUS = ["10", "22", "28", "3B", "42"]
# These can only be read by OWFS. Currently this driver only supports them
# via owserver (network protocol)
HOBBYBOARD_EF = {
HOBBYBOARD_EF: dict[str, list[DeviceComponentDescription]] = {
"HobbyBoards_EF": [
{
"path": "humidity/humidity_corrected",
@ -189,7 +195,7 @@ HOBBYBOARD_EF = {
# 7E sensors are special sensors by Embedded Data Systems
EDS_SENSORS = {
EDS_SENSORS: dict[str, list[DeviceComponentDescription]] = {
"EDS0068": [
{
"path": "EDS0068/temperature",
@ -225,7 +231,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
)
def get_sensor_types(device_sub_type):
def get_sensor_types(device_sub_type: str) -> dict[str, Any]:
"""Return the proper info array for the device type."""
if "HobbyBoard" in device_sub_type:
return HOBBYBOARD_EF
@ -234,7 +240,12 @@ def get_sensor_types(device_sub_type):
return DEVICE_SENSORS
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
async def async_setup_platform(
hass: HomeAssistant,
config: dict[str, Any],
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Old way of setting up 1-Wire platform."""
_LOGGER.warning(
"Loading 1-Wire via platform setup is deprecated. "
@ -253,7 +264,11 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
)
async def async_setup_entry(hass, config_entry, async_add_entities):
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up 1-Wire platform."""
onewirehub = hass.data[DOMAIN][config_entry.entry_id]
entities = await hass.async_add_executor_job(
@ -262,9 +277,14 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async_add_entities(entities, True)
def get_entities(onewirehub: OneWireHub, config):
def get_entities(
onewirehub: OneWireHub, config: MappingProxyType[str, Any]
) -> list[OneWireBaseEntity]:
"""Get a list of entities."""
entities = []
if not onewirehub.devices:
return []
entities: list[OneWireBaseEntity] = []
device_names = {}
if CONF_NAMES in config and isinstance(config[CONF_NAMES], dict):
device_names = config[CONF_NAMES]
@ -272,6 +292,7 @@ def get_entities(onewirehub: OneWireHub, config):
conf_type = config[CONF_TYPE]
# We have an owserver on a remote(or local) host/port
if conf_type == CONF_TYPE_OWSERVER:
assert onewirehub.owproxy
for device in onewirehub.devices:
family = device["family"]
device_type = device["type"]
@ -292,7 +313,7 @@ def get_entities(onewirehub: OneWireHub, config):
device_id,
)
continue
device_info = {
device_info: DeviceInfo = {
"identifiers": {(DOMAIN, device_id)},
"manufacturer": "Maxim Integrated",
"model": device_type,
@ -384,9 +405,23 @@ class OneWireProxySensor(OneWireProxyEntity, OneWireSensor):
class OneWireDirectSensor(OneWireSensor):
"""Implementation of a 1-Wire sensor directly connected to RPI GPIO."""
def __init__(self, name, device_file, device_info, owsensor):
def __init__(
self,
name: str,
device_file: str,
device_info: DeviceInfo,
owsensor: OneWireInterface,
) -> None:
"""Initialize the sensor."""
super().__init__(name, device_file, "temperature", "Temperature", device_info)
super().__init__(
name,
device_file,
"temperature",
"Temperature",
device_info,
False,
device_file,
)
self._owsensor = owsensor
@property
@ -394,7 +429,7 @@ class OneWireDirectSensor(OneWireSensor):
"""Return the state of the entity."""
return self._state
async def get_temperature(self):
async def get_temperature(self) -> float:
"""Get the latest data from the device."""
attempts = 1
while True:
@ -414,16 +449,15 @@ class OneWireDirectSensor(OneWireSensor):
if attempts > 10:
raise
async def async_update(self):
async def async_update(self) -> None:
"""Get the latest data from the device."""
value = None
try:
self._value_raw = await self.get_temperature()
value = round(float(self._value_raw), 1)
self._state = round(self._value_raw, 1)
except (
FileNotFoundError,
InvalidCRCException,
UnsupportResponseException,
) as ex:
_LOGGER.warning("Cannot read from sensor %s: %s", self._device_file, ex)
self._state = value
self._state = None

View File

@ -1,15 +1,23 @@
"""Support for 1-Wire environment switches."""
from __future__ import annotations
import logging
import os
from typing import Any
from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_TYPE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import CONF_TYPE_OWSERVER, DOMAIN, SWITCH_TYPE_LATCH, SWITCH_TYPE_PIO
from .onewire_entities import OneWireProxyEntity
from .model import DeviceComponentDescription
from .onewire_entities import OneWireBaseEntity, OneWireProxyEntity
from .onewirehub import OneWireHub
DEVICE_SWITCHES = {
DEVICE_SWITCHES: dict[str, list[DeviceComponentDescription]] = {
# Family : { owfs path }
"12": [
{
@ -140,7 +148,11 @@ DEVICE_SWITCHES = {
LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass, config_entry, async_add_entities):
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up 1-Wire platform."""
# Only OWServer implementation works with switches
if config_entry.data[CONF_TYPE] == CONF_TYPE_OWSERVER:
@ -150,9 +162,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async_add_entities(entities, True)
def get_entities(onewirehub: OneWireHub):
def get_entities(onewirehub: OneWireHub) -> list[OneWireBaseEntity]:
"""Get a list of entities."""
entities = []
if not onewirehub.devices:
return []
entities: list[OneWireBaseEntity] = []
for device in onewirehub.devices:
family = device["family"]
@ -162,7 +177,7 @@ def get_entities(onewirehub: OneWireHub):
if family not in DEVICE_SWITCHES:
continue
device_info = {
device_info: DeviceInfo = {
"identifiers": {(DOMAIN, device_id)},
"manufacturer": "Maxim Integrated",
"model": device_type,
@ -190,14 +205,14 @@ class OneWireProxySwitch(OneWireProxyEntity, SwitchEntity):
"""Implementation of a 1-Wire switch."""
@property
def is_on(self):
def is_on(self) -> bool:
"""Return true if sensor is on."""
return self._state
return bool(self._state)
def turn_on(self, **kwargs) -> None:
def turn_on(self, **kwargs: Any) -> None:
"""Turn the entity on."""
self._write_value_ownet(b"1")
def turn_off(self, **kwargs) -> None:
def turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off."""
self._write_value_ownet(b"0")

View File

@ -352,6 +352,17 @@ no_implicit_optional = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.onewire.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
no_implicit_optional = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.persistent_notification.*]
check_untyped_defs = true
disallow_incomplete_defs = true
@ -1008,9 +1019,6 @@ ignore_errors = true
[mypy-homeassistant.components.ondilo_ico.*]
ignore_errors = true
[mypy-homeassistant.components.onewire.*]
ignore_errors = true
[mypy-homeassistant.components.onvif.*]
ignore_errors = true

View File

@ -152,7 +152,6 @@ IGNORED_MODULES: Final[list[str]] = [
"homeassistant.components.omnilogic.*",
"homeassistant.components.onboarding.*",
"homeassistant.components.ondilo_ico.*",
"homeassistant.components.onewire.*",
"homeassistant.components.onvif.*",
"homeassistant.components.ovo_energy.*",
"homeassistant.components.ozw.*",

View File

@ -884,7 +884,7 @@ MOCK_SYSBUS_DEVICES = {
{
"entity_id": "sensor.42_111111111112_temperature",
"unique_id": "/sys/bus/w1/devices/42-111111111112/w1_slave",
"injected_value": [UnsupportResponseException] * 9 + ["27.993"],
"injected_value": [UnsupportResponseException] * 9 + [27.993],
"result": "28.0",
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,
@ -902,7 +902,7 @@ MOCK_SYSBUS_DEVICES = {
{
"entity_id": "sensor.42_111111111113_temperature",
"unique_id": "/sys/bus/w1/devices/42-111111111113/w1_slave",
"injected_value": [UnsupportResponseException] * 10 + ["27.993"],
"injected_value": [UnsupportResponseException] * 10 + [27.993],
"result": "unknown",
"unit": TEMP_CELSIUS,
"class": DEVICE_CLASS_TEMPERATURE,