mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 20:27:08 +00:00
Homekit Update, Support for TempSensor (°F) (#12676)
* Changed version of "HAP-python" to "v1.1.7" * Updated acc file to simplify init calls * Code refactored and '°F' temp Sensors added * Changed call to 'HomeAccessory' and 'HomeBridge' * Extended function of 'add_preload_service' to add additional characteristics * Added function to override characteristic property values * TemperatureSensor * Added unit * Added calc_temperature * Updated tests
This commit is contained in:
parent
347ba1a2d8
commit
27b1d448a3
@ -11,7 +11,8 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, CONF_PORT,
|
ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, CONF_PORT,
|
||||||
TEMP_CELSIUS, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)
|
TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
||||||
|
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)
|
||||||
from homeassistant.util import get_local_ip
|
from homeassistant.util import get_local_ip
|
||||||
from homeassistant.util.decorator import Registry
|
from homeassistant.util.decorator import Registry
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
_RE_VALID_PINCODE = re.compile(r"^(\d{3}-\d{2}-\d{3})$")
|
_RE_VALID_PINCODE = re.compile(r"^(\d{3}-\d{2}-\d{3})$")
|
||||||
|
|
||||||
DOMAIN = 'homekit'
|
DOMAIN = 'homekit'
|
||||||
REQUIREMENTS = ['HAP-python==1.1.5']
|
REQUIREMENTS = ['HAP-python==1.1.7']
|
||||||
|
|
||||||
BRIDGE_NAME = 'Home Assistant'
|
BRIDGE_NAME = 'Home Assistant'
|
||||||
CONF_PIN_CODE = 'pincode'
|
CONF_PIN_CODE = 'pincode'
|
||||||
@ -74,7 +75,8 @@ def import_types():
|
|||||||
def get_accessory(hass, state):
|
def get_accessory(hass, state):
|
||||||
"""Take state and return an accessory object if supported."""
|
"""Take state and return an accessory object if supported."""
|
||||||
if state.domain == 'sensor':
|
if state.domain == 'sensor':
|
||||||
if state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS:
|
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||||
|
if unit == TEMP_CELSIUS or unit == TEMP_FAHRENHEIT:
|
||||||
_LOGGER.debug("Add \"%s\" as \"%s\"",
|
_LOGGER.debug("Add \"%s\" as \"%s\"",
|
||||||
state.entity_id, 'TemperatureSensor')
|
state.entity_id, 'TemperatureSensor')
|
||||||
return TYPES['TemperatureSensor'](hass, state.entity_id,
|
return TYPES['TemperatureSensor'](hass, state.entity_id,
|
||||||
@ -103,8 +105,7 @@ class HomeKit():
|
|||||||
def setup_bridge(self, pin):
|
def setup_bridge(self, pin):
|
||||||
"""Setup the bridge component to track all accessories."""
|
"""Setup the bridge component to track all accessories."""
|
||||||
from .accessories import HomeBridge
|
from .accessories import HomeBridge
|
||||||
self.bridge = HomeBridge(BRIDGE_NAME, pincode=pin)
|
self.bridge = HomeBridge(BRIDGE_NAME, 'homekit.bridge', pin)
|
||||||
self.bridge.set_accessory_info('homekit.bridge')
|
|
||||||
|
|
||||||
def start_driver(self, event):
|
def start_driver(self, event):
|
||||||
"""Start the accessory driver."""
|
"""Start the accessory driver."""
|
||||||
|
@ -1,55 +1,62 @@
|
|||||||
"""Extend the basic Accessory and Bridge functions."""
|
"""Extend the basic Accessory and Bridge functions."""
|
||||||
|
import logging
|
||||||
|
|
||||||
from pyhap.accessory import Accessory, Bridge, Category
|
from pyhap.accessory import Accessory, Bridge, Category
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
SERVICES_ACCESSORY_INFO, MANUFACTURER,
|
SERV_ACCESSORY_INFO, MANUFACTURER,
|
||||||
CHAR_MODEL, CHAR_MANUFACTURER, CHAR_SERIAL_NUMBER)
|
CHAR_MODEL, CHAR_MANUFACTURER, CHAR_SERIAL_NUMBER)
|
||||||
|
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def set_accessory_info(acc, model, manufacturer=MANUFACTURER,
|
||||||
|
serial_number='0000'):
|
||||||
|
"""Set the default accessory information."""
|
||||||
|
service = acc.get_service(SERV_ACCESSORY_INFO)
|
||||||
|
service.get_characteristic(CHAR_MODEL).set_value(model)
|
||||||
|
service.get_characteristic(CHAR_MANUFACTURER).set_value(manufacturer)
|
||||||
|
service.get_characteristic(CHAR_SERIAL_NUMBER).set_value(serial_number)
|
||||||
|
|
||||||
|
|
||||||
|
def add_preload_service(acc, service, chars=None, opt_chars=None):
|
||||||
|
"""Define and return a service to be available for the accessory."""
|
||||||
|
from pyhap.loader import get_serv_loader, get_char_loader
|
||||||
|
service = get_serv_loader().get(service)
|
||||||
|
if chars:
|
||||||
|
chars = chars if isinstance(chars, list) else [chars]
|
||||||
|
for char_name in chars:
|
||||||
|
char = get_char_loader().get(char_name)
|
||||||
|
service.add_characteristic(char)
|
||||||
|
if opt_chars:
|
||||||
|
opt_chars = opt_chars if isinstance(opt_chars, list) else [opt_chars]
|
||||||
|
for opt_char_name in opt_chars:
|
||||||
|
opt_char = get_char_loader().get(opt_char_name)
|
||||||
|
service.add_opt_characteristic(opt_char)
|
||||||
|
acc.add_service(service)
|
||||||
|
return service
|
||||||
|
|
||||||
|
|
||||||
|
def override_properties(char, new_properties):
|
||||||
|
"""Override characteristic property values."""
|
||||||
|
char.properties.update(new_properties)
|
||||||
|
|
||||||
|
|
||||||
class HomeAccessory(Accessory):
|
class HomeAccessory(Accessory):
|
||||||
"""Class to extend the Accessory class."""
|
"""Class to extend the Accessory class."""
|
||||||
|
|
||||||
ALL_CATEGORIES = Category
|
def __init__(self, display_name, model, category='OTHER'):
|
||||||
|
|
||||||
def __init__(self, display_name):
|
|
||||||
"""Initialize a Accessory object."""
|
"""Initialize a Accessory object."""
|
||||||
super().__init__(display_name)
|
super().__init__(display_name)
|
||||||
|
set_accessory_info(self, model)
|
||||||
def set_category(self, category):
|
self.category = getattr(Category, category, Category.OTHER)
|
||||||
"""Set the category of the accessory."""
|
|
||||||
self.category = category
|
|
||||||
|
|
||||||
def add_preload_service(self, service):
|
|
||||||
"""Define the services to be available for the accessory."""
|
|
||||||
from pyhap.loader import get_serv_loader
|
|
||||||
self.add_service(get_serv_loader().get(service))
|
|
||||||
|
|
||||||
def set_accessory_info(self, model, manufacturer=MANUFACTURER,
|
|
||||||
serial_number='0000'):
|
|
||||||
"""Set the default accessory information."""
|
|
||||||
service_info = self.get_service(SERVICES_ACCESSORY_INFO)
|
|
||||||
service_info.get_characteristic(CHAR_MODEL) \
|
|
||||||
.set_value(model)
|
|
||||||
service_info.get_characteristic(CHAR_MANUFACTURER) \
|
|
||||||
.set_value(manufacturer)
|
|
||||||
service_info.get_characteristic(CHAR_SERIAL_NUMBER) \
|
|
||||||
.set_value(serial_number)
|
|
||||||
|
|
||||||
|
|
||||||
class HomeBridge(Bridge):
|
class HomeBridge(Bridge):
|
||||||
"""Class to extend the Bridge class."""
|
"""Class to extend the Bridge class."""
|
||||||
|
|
||||||
def __init__(self, display_name, pincode):
|
def __init__(self, display_name, model, pincode):
|
||||||
"""Initialize a Bridge object."""
|
"""Initialize a Bridge object."""
|
||||||
super().__init__(display_name, pincode=pincode)
|
super().__init__(display_name, pincode=pincode)
|
||||||
|
set_accessory_info(self, model)
|
||||||
def set_accessory_info(self, model, manufacturer=MANUFACTURER,
|
|
||||||
serial_number='0000'):
|
|
||||||
"""Set the default accessory information."""
|
|
||||||
service_info = self.get_service(SERVICES_ACCESSORY_INFO)
|
|
||||||
service_info.get_characteristic(CHAR_MODEL) \
|
|
||||||
.set_value(model)
|
|
||||||
service_info.get_characteristic(CHAR_MANUFACTURER) \
|
|
||||||
.set_value(manufacturer)
|
|
||||||
service_info.get_characteristic(CHAR_SERIAL_NUMBER) \
|
|
||||||
.set_value(serial_number)
|
|
||||||
|
@ -2,17 +2,20 @@
|
|||||||
MANUFACTURER = 'HomeAssistant'
|
MANUFACTURER = 'HomeAssistant'
|
||||||
|
|
||||||
# Service: AccessoryInfomation
|
# Service: AccessoryInfomation
|
||||||
SERVICES_ACCESSORY_INFO = 'AccessoryInformation'
|
SERV_ACCESSORY_INFO = 'AccessoryInformation'
|
||||||
CHAR_MODEL = 'Model'
|
CHAR_MODEL = 'Model'
|
||||||
CHAR_MANUFACTURER = 'Manufacturer'
|
CHAR_MANUFACTURER = 'Manufacturer'
|
||||||
CHAR_SERIAL_NUMBER = 'SerialNumber'
|
CHAR_SERIAL_NUMBER = 'SerialNumber'
|
||||||
|
|
||||||
# Service: TemperatureSensor
|
# Service: TemperatureSensor
|
||||||
SERVICES_TEMPERATURE_SENSOR = 'TemperatureSensor'
|
SERV_TEMPERATURE_SENSOR = 'TemperatureSensor'
|
||||||
CHAR_CURRENT_TEMPERATURE = 'CurrentTemperature'
|
CHAR_CURRENT_TEMPERATURE = 'CurrentTemperature'
|
||||||
|
|
||||||
# Service: WindowCovering
|
# Service: WindowCovering
|
||||||
SERVICES_WINDOW_COVERING = 'WindowCovering'
|
SERV_WINDOW_COVERING = 'WindowCovering'
|
||||||
CHAR_CURRENT_POSITION = 'CurrentPosition'
|
CHAR_CURRENT_POSITION = 'CurrentPosition'
|
||||||
CHAR_TARGET_POSITION = 'TargetPosition'
|
CHAR_TARGET_POSITION = 'TargetPosition'
|
||||||
CHAR_POSITION_STATE = 'PositionState'
|
CHAR_POSITION_STATE = 'PositionState'
|
||||||
|
|
||||||
|
# Properties
|
||||||
|
PROP_CELSIUS = {'minValue': -273, 'maxValue': 999}
|
||||||
|
@ -5,9 +5,9 @@ from homeassistant.components.cover import ATTR_CURRENT_POSITION
|
|||||||
from homeassistant.helpers.event import async_track_state_change
|
from homeassistant.helpers.event import async_track_state_change
|
||||||
|
|
||||||
from . import TYPES
|
from . import TYPES
|
||||||
from .accessories import HomeAccessory
|
from .accessories import HomeAccessory, add_preload_service
|
||||||
from .const import (
|
from .const import (
|
||||||
SERVICES_WINDOW_COVERING, CHAR_CURRENT_POSITION,
|
SERV_WINDOW_COVERING, CHAR_CURRENT_POSITION,
|
||||||
CHAR_TARGET_POSITION, CHAR_POSITION_STATE)
|
CHAR_TARGET_POSITION, CHAR_POSITION_STATE)
|
||||||
|
|
||||||
|
|
||||||
@ -23,10 +23,7 @@ class Window(HomeAccessory):
|
|||||||
|
|
||||||
def __init__(self, hass, entity_id, display_name):
|
def __init__(self, hass, entity_id, display_name):
|
||||||
"""Initialize a Window accessory object."""
|
"""Initialize a Window accessory object."""
|
||||||
super().__init__(display_name)
|
super().__init__(display_name, entity_id, 'WINDOW')
|
||||||
self.set_category(self.ALL_CATEGORIES.WINDOW)
|
|
||||||
self.set_accessory_info(entity_id)
|
|
||||||
self.add_preload_service(SERVICES_WINDOW_COVERING)
|
|
||||||
|
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._entity_id = entity_id
|
self._entity_id = entity_id
|
||||||
@ -34,12 +31,12 @@ class Window(HomeAccessory):
|
|||||||
self.current_position = None
|
self.current_position = None
|
||||||
self.homekit_target = None
|
self.homekit_target = None
|
||||||
|
|
||||||
self.service_cover = self.get_service(SERVICES_WINDOW_COVERING)
|
self.serv_cover = add_preload_service(self, SERV_WINDOW_COVERING)
|
||||||
self.char_current_position = self.service_cover. \
|
self.char_current_position = self.serv_cover. \
|
||||||
get_characteristic(CHAR_CURRENT_POSITION)
|
get_characteristic(CHAR_CURRENT_POSITION)
|
||||||
self.char_target_position = self.service_cover. \
|
self.char_target_position = self.serv_cover. \
|
||||||
get_characteristic(CHAR_TARGET_POSITION)
|
get_characteristic(CHAR_TARGET_POSITION)
|
||||||
self.char_position_state = self.service_cover. \
|
self.char_position_state = self.serv_cover. \
|
||||||
get_characteristic(CHAR_POSITION_STATE)
|
get_characteristic(CHAR_POSITION_STATE)
|
||||||
|
|
||||||
self.char_target_position.setter_callback = self.move_cover
|
self.char_target_position.setter_callback = self.move_cover
|
||||||
@ -53,7 +50,7 @@ class Window(HomeAccessory):
|
|||||||
self._hass, self._entity_id, self.update_cover_position)
|
self._hass, self._entity_id, self.update_cover_position)
|
||||||
|
|
||||||
def move_cover(self, value):
|
def move_cover(self, value):
|
||||||
"""Move cover to value if call came from homekit."""
|
"""Move cover to value if call came from HomeKit."""
|
||||||
if value != self.current_position:
|
if value != self.current_position:
|
||||||
_LOGGER.debug("%s: Set position to %d", self._entity_id, value)
|
_LOGGER.debug("%s: Set position to %d", self._entity_id, value)
|
||||||
self.homekit_target = value
|
self.homekit_target = value
|
||||||
|
@ -1,38 +1,55 @@
|
|||||||
"""Class to hold all sensor accessories."""
|
"""Class to hold all sensor accessories."""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant.const import STATE_UNKNOWN
|
from homeassistant.const import (
|
||||||
|
STATE_UNKNOWN, ATTR_UNIT_OF_MEASUREMENT, TEMP_FAHRENHEIT, TEMP_CELSIUS)
|
||||||
from homeassistant.helpers.event import async_track_state_change
|
from homeassistant.helpers.event import async_track_state_change
|
||||||
|
|
||||||
from . import TYPES
|
from . import TYPES
|
||||||
from .accessories import HomeAccessory
|
from .accessories import (
|
||||||
|
HomeAccessory, add_preload_service, override_properties)
|
||||||
from .const import (
|
from .const import (
|
||||||
SERVICES_TEMPERATURE_SENSOR, CHAR_CURRENT_TEMPERATURE)
|
SERV_TEMPERATURE_SENSOR, CHAR_CURRENT_TEMPERATURE, PROP_CELSIUS)
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def calc_temperature(state, unit=TEMP_CELSIUS):
|
||||||
|
"""Calculate temperature from state and unit.
|
||||||
|
|
||||||
|
Always return temperature as Celsius value.
|
||||||
|
Conversion is handled on the device.
|
||||||
|
"""
|
||||||
|
if state == STATE_UNKNOWN:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if unit == TEMP_FAHRENHEIT:
|
||||||
|
value = round((float(state) - 32) / 1.8, 2)
|
||||||
|
else:
|
||||||
|
value = float(state)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
@TYPES.register('TemperatureSensor')
|
@TYPES.register('TemperatureSensor')
|
||||||
class TemperatureSensor(HomeAccessory):
|
class TemperatureSensor(HomeAccessory):
|
||||||
"""Generate a TemperatureSensor accessory for a temperature sensor.
|
"""Generate a TemperatureSensor accessory for a temperature sensor.
|
||||||
|
|
||||||
Sensor entity must return either temperature in °C or STATE_UNKNOWN.
|
Sensor entity must return temperature in °C, °F or STATE_UNKNOWN.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, hass, entity_id, display_name):
|
def __init__(self, hass, entity_id, display_name):
|
||||||
"""Initialize a TemperatureSensor accessory object."""
|
"""Initialize a TemperatureSensor accessory object."""
|
||||||
super().__init__(display_name)
|
super().__init__(display_name, entity_id, 'SENSOR')
|
||||||
self.set_category(self.ALL_CATEGORIES.SENSOR)
|
|
||||||
self.set_accessory_info(entity_id)
|
|
||||||
self.add_preload_service(SERVICES_TEMPERATURE_SENSOR)
|
|
||||||
|
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._entity_id = entity_id
|
self._entity_id = entity_id
|
||||||
|
|
||||||
self.service_temp = self.get_service(SERVICES_TEMPERATURE_SENSOR)
|
self.serv_temp = add_preload_service(self, SERV_TEMPERATURE_SENSOR)
|
||||||
self.char_temp = self.service_temp. \
|
self.char_temp = self.serv_temp. \
|
||||||
get_characteristic(CHAR_CURRENT_TEMPERATURE)
|
get_characteristic(CHAR_CURRENT_TEMPERATURE)
|
||||||
|
override_properties(self.char_temp, PROP_CELSIUS)
|
||||||
|
self.unit = None
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Method called be object after driver is started."""
|
"""Method called be object after driver is started."""
|
||||||
@ -48,6 +65,9 @@ class TemperatureSensor(HomeAccessory):
|
|||||||
if new_state is None:
|
if new_state is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
temperature = new_state.state
|
unit = new_state.attributes[ATTR_UNIT_OF_MEASUREMENT]
|
||||||
if temperature != STATE_UNKNOWN:
|
temperature = calc_temperature(new_state.state, unit)
|
||||||
self.char_temp.set_value(float(temperature))
|
if temperature is not None:
|
||||||
|
self.char_temp.set_value(temperature)
|
||||||
|
_LOGGER.debug("%s: Current temperature set to %d°C",
|
||||||
|
self._entity_id, temperature)
|
||||||
|
@ -24,7 +24,7 @@ attrs==17.4.0
|
|||||||
DoorBirdPy==0.1.2
|
DoorBirdPy==0.1.2
|
||||||
|
|
||||||
# homeassistant.components.homekit
|
# homeassistant.components.homekit
|
||||||
HAP-python==1.1.5
|
HAP-python==1.1.7
|
||||||
|
|
||||||
# homeassistant.components.isy994
|
# homeassistant.components.isy994
|
||||||
PyISY==1.1.0
|
PyISY==1.1.0
|
||||||
|
@ -19,7 +19,7 @@ asynctest>=0.11.1
|
|||||||
|
|
||||||
|
|
||||||
# homeassistant.components.homekit
|
# homeassistant.components.homekit
|
||||||
HAP-python==1.1.5
|
HAP-python==1.1.7
|
||||||
|
|
||||||
# homeassistant.components.notify.html5
|
# homeassistant.components.notify.html5
|
||||||
PyJWT==1.5.3
|
PyJWT==1.5.3
|
||||||
|
@ -1,13 +1,25 @@
|
|||||||
"""Test different accessory types: Sensors."""
|
"""Test different accessory types: Sensors."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.components.homekit.sensors import TemperatureSensor
|
from homeassistant.components.homekit.sensors import (
|
||||||
|
TemperatureSensor, calc_temperature)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS, STATE_UNKNOWN)
|
ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS, TEMP_FAHRENHEIT, STATE_UNKNOWN)
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
|
||||||
|
def test_calc_temperature():
|
||||||
|
"""Test if temperature in Celsius is calculated correctly."""
|
||||||
|
assert calc_temperature(STATE_UNKNOWN) is None
|
||||||
|
|
||||||
|
assert calc_temperature('20') == 20
|
||||||
|
assert calc_temperature('20.12', TEMP_CELSIUS) == 20.12
|
||||||
|
|
||||||
|
assert calc_temperature('75.2', TEMP_FAHRENHEIT) == 24
|
||||||
|
assert calc_temperature('-20.6', TEMP_FAHRENHEIT) == -29.22
|
||||||
|
|
||||||
|
|
||||||
class TestHomekitSensors(unittest.TestCase):
|
class TestHomekitSensors(unittest.TestCase):
|
||||||
"""Test class for all accessory types regarding sensors."""
|
"""Test class for all accessory types regarding sensors."""
|
||||||
|
|
||||||
@ -16,7 +28,7 @@ class TestHomekitSensors(unittest.TestCase):
|
|||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Stop down everthing that was started."""
|
"""Stop down everything that was started."""
|
||||||
self.hass.stop()
|
self.hass.stop()
|
||||||
|
|
||||||
def test_temperature_celsius(self):
|
def test_temperature_celsius(self):
|
||||||
@ -32,6 +44,12 @@ class TestHomekitSensors(unittest.TestCase):
|
|||||||
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
|
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
self.hass.states.set(temperature_sensor, '20')
|
self.hass.states.set(temperature_sensor, '20',
|
||||||
|
{ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
self.assertEqual(acc.char_temp.value, 20)
|
self.assertEqual(acc.char_temp.value, 20)
|
||||||
|
|
||||||
|
self.hass.states.set(temperature_sensor, '75.2',
|
||||||
|
{ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT})
|
||||||
|
self.hass.block_till_done()
|
||||||
|
self.assertEqual(acc.char_temp.value, 24)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user