Fix handling of attribute reports in ZHA sensors and binary sensors (#32776)
* Update sensor tests. * Update light tests. * Update binary_sensor tests. * Update cover tests. * Update device tracker tests. * Update fan tests. * Update lock tests. * Update switch tests. * add sensor attr to sensors * add sensor attr to binary sensors * cleanup extra var Co-authored-by: Alexei Chetroi <alexei.chetroi@outlook.com>
This commit is contained in:
parent
0788bbd629
commit
706607f1d2
11 changed files with 77 additions and 104 deletions
|
@ -64,6 +64,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
class BinarySensor(ZhaEntity, BinarySensorDevice):
|
||||
"""ZHA BinarySensor."""
|
||||
|
||||
SENSOR_ATTR = None
|
||||
DEVICE_CLASS = None
|
||||
|
||||
def __init__(self, unique_id, zha_device, channels, **kwargs):
|
||||
|
@ -105,6 +106,8 @@ class BinarySensor(ZhaEntity, BinarySensorDevice):
|
|||
@callback
|
||||
def async_set_state(self, attr_id, attr_name, value):
|
||||
"""Set the state."""
|
||||
if self.SENSOR_ATTR is None or self.SENSOR_ATTR != attr_name:
|
||||
return
|
||||
self._state = bool(value)
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
@ -121,6 +124,7 @@ class BinarySensor(ZhaEntity, BinarySensorDevice):
|
|||
class Accelerometer(BinarySensor):
|
||||
"""ZHA BinarySensor."""
|
||||
|
||||
SENSOR_ATTR = "acceleration"
|
||||
DEVICE_CLASS = DEVICE_CLASS_MOVING
|
||||
|
||||
|
||||
|
@ -128,6 +132,7 @@ class Accelerometer(BinarySensor):
|
|||
class Occupancy(BinarySensor):
|
||||
"""ZHA BinarySensor."""
|
||||
|
||||
SENSOR_ATTR = "occupancy"
|
||||
DEVICE_CLASS = DEVICE_CLASS_OCCUPANCY
|
||||
|
||||
|
||||
|
@ -135,6 +140,7 @@ class Occupancy(BinarySensor):
|
|||
class Opening(BinarySensor):
|
||||
"""ZHA BinarySensor."""
|
||||
|
||||
SENSOR_ATTR = "on_off"
|
||||
DEVICE_CLASS = DEVICE_CLASS_OPENING
|
||||
|
||||
|
||||
|
@ -142,6 +148,8 @@ class Opening(BinarySensor):
|
|||
class IASZone(BinarySensor):
|
||||
"""ZHA IAS BinarySensor."""
|
||||
|
||||
SENSOR_ATTR = "zone_status"
|
||||
|
||||
async def get_device_class(self) -> None:
|
||||
"""Get the HA device class from the channel."""
|
||||
zone_type = await self._channel.get_attribute_value("zone_type")
|
||||
|
|
|
@ -83,6 +83,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
class Sensor(ZhaEntity):
|
||||
"""Base ZHA sensor."""
|
||||
|
||||
SENSOR_ATTR = None
|
||||
_decimals = 1
|
||||
_device_class = None
|
||||
_divisor = 1
|
||||
|
@ -126,6 +127,8 @@ class Sensor(ZhaEntity):
|
|||
@callback
|
||||
def async_set_state(self, attr_id, attr_name, value):
|
||||
"""Handle state update from channel."""
|
||||
if self.SENSOR_ATTR is None or self.SENSOR_ATTR != attr_name:
|
||||
return
|
||||
if value is not None:
|
||||
value = self.formatter(value)
|
||||
self._state = value
|
||||
|
@ -154,6 +157,7 @@ class Sensor(ZhaEntity):
|
|||
class AnalogInput(Sensor):
|
||||
"""Sensor that displays analog input values."""
|
||||
|
||||
SENSOR_ATTR = "present_value"
|
||||
pass
|
||||
|
||||
|
||||
|
@ -161,6 +165,7 @@ class AnalogInput(Sensor):
|
|||
class Battery(Sensor):
|
||||
"""Battery sensor of power configuration cluster."""
|
||||
|
||||
SENSOR_ATTR = "battery_percentage_remaining"
|
||||
_device_class = DEVICE_CLASS_BATTERY
|
||||
_unit = UNIT_PERCENTAGE
|
||||
|
||||
|
@ -198,6 +203,7 @@ class Battery(Sensor):
|
|||
class ElectricalMeasurement(Sensor):
|
||||
"""Active power measurement."""
|
||||
|
||||
SENSOR_ATTR = "active_power"
|
||||
_device_class = DEVICE_CLASS_POWER
|
||||
_divisor = 10
|
||||
_unit = POWER_WATT
|
||||
|
@ -232,6 +238,7 @@ class Text(Sensor):
|
|||
class Humidity(Sensor):
|
||||
"""Humidity sensor."""
|
||||
|
||||
SENSOR_ATTR = "measured_value"
|
||||
_device_class = DEVICE_CLASS_HUMIDITY
|
||||
_divisor = 100
|
||||
_unit = UNIT_PERCENTAGE
|
||||
|
@ -241,6 +248,7 @@ class Humidity(Sensor):
|
|||
class Illuminance(Sensor):
|
||||
"""Illuminance Sensor."""
|
||||
|
||||
SENSOR_ATTR = "measured_value"
|
||||
_device_class = DEVICE_CLASS_ILLUMINANCE
|
||||
_unit = "lx"
|
||||
|
||||
|
@ -254,6 +262,7 @@ class Illuminance(Sensor):
|
|||
class SmartEnergyMetering(Sensor):
|
||||
"""Metering sensor."""
|
||||
|
||||
SENSOR_ATTR = "instantaneous_demand"
|
||||
_device_class = DEVICE_CLASS_POWER
|
||||
|
||||
def formatter(self, value):
|
||||
|
@ -270,6 +279,7 @@ class SmartEnergyMetering(Sensor):
|
|||
class Pressure(Sensor):
|
||||
"""Pressure sensor."""
|
||||
|
||||
SENSOR_ATTR = "measured_value"
|
||||
_device_class = DEVICE_CLASS_PRESSURE
|
||||
_decimals = 0
|
||||
_unit = "hPa"
|
||||
|
@ -279,6 +289,7 @@ class Pressure(Sensor):
|
|||
class Temperature(Sensor):
|
||||
"""Temperature Sensor."""
|
||||
|
||||
SENSOR_ATTR = "measured_value"
|
||||
_device_class = DEVICE_CLASS_TEMPERATURE
|
||||
_divisor = 100
|
||||
_unit = TEMP_CELSIUS
|
||||
|
|
|
@ -102,6 +102,23 @@ def make_attribute(attrid, value, status=0):
|
|||
return attr
|
||||
|
||||
|
||||
def send_attribute_report(hass, cluster, attrid, value):
|
||||
"""Send a single attribute report."""
|
||||
return send_attributes_report(hass, cluster, {attrid: value})
|
||||
|
||||
|
||||
async def send_attributes_report(hass, cluster: int, attributes: dict):
|
||||
"""Cause the sensor to receive an attribute report from the network.
|
||||
|
||||
This is to simulate the normal device communication that happens when a
|
||||
device is paired to the zigbee network.
|
||||
"""
|
||||
attrs = [make_attribute(attrid, value) for attrid, value in attributes.items()]
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [attrs])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def find_entity_id(domain, zha_device, hass):
|
||||
"""Find the entity id under the testing.
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import pytest
|
||||
import zigpy.zcl.clusters.measurement as measurement
|
||||
import zigpy.zcl.clusters.security as security
|
||||
import zigpy.zcl.foundation as zcl_f
|
||||
|
||||
from homeassistant.components.binary_sensor import DOMAIN
|
||||
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE
|
||||
|
@ -11,8 +10,7 @@ from .common import (
|
|||
async_enable_traffic,
|
||||
async_test_rejoin,
|
||||
find_entity_id,
|
||||
make_attribute,
|
||||
make_zcl_header,
|
||||
send_attributes_report,
|
||||
)
|
||||
|
||||
DEVICE_IAS = {
|
||||
|
@ -36,17 +34,11 @@ DEVICE_OCCUPANCY = {
|
|||
async def async_test_binary_sensor_on_off(hass, cluster, entity_id):
|
||||
"""Test getting on and off messages for binary sensors."""
|
||||
# binary sensor on
|
||||
attr = make_attribute(0, 1)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 0, 0: 1, 2: 2})
|
||||
assert hass.states.get(entity_id).state == STATE_ON
|
||||
|
||||
# binary sensor off
|
||||
attr.value.value = 0
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 1, 0: 0, 2: 2})
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
|
||||
|
|
|
@ -14,8 +14,7 @@ from .common import (
|
|||
async_enable_traffic,
|
||||
async_test_rejoin,
|
||||
find_entity_id,
|
||||
make_attribute,
|
||||
make_zcl_header,
|
||||
send_attributes_report,
|
||||
)
|
||||
|
||||
from tests.common import mock_coro
|
||||
|
@ -64,19 +63,12 @@ async def test_cover(m1, hass, zha_device_joined_restored, zigpy_cover_device):
|
|||
await async_enable_traffic(hass, [zha_device])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
attr = make_attribute(8, 100)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# test that the state has changed from unavailable to off
|
||||
await send_attributes_report(hass, cluster, {0: 0, 8: 100, 1: 1})
|
||||
assert hass.states.get(entity_id).state == STATE_CLOSED
|
||||
|
||||
# test to see if it opens
|
||||
attr = make_attribute(8, 0)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {0: 1, 8: 0, 1: 100})
|
||||
assert hass.states.get(entity_id).state == STATE_OPEN
|
||||
|
||||
# close from UI
|
||||
|
|
|
@ -4,7 +4,6 @@ import time
|
|||
|
||||
import pytest
|
||||
import zigpy.zcl.clusters.general as general
|
||||
import zigpy.zcl.foundation as zcl_f
|
||||
|
||||
from homeassistant.components.device_tracker import DOMAIN, SOURCE_TYPE_ROUTER
|
||||
from homeassistant.components.zha.core.registries import (
|
||||
|
@ -17,8 +16,7 @@ from .common import (
|
|||
async_enable_traffic,
|
||||
async_test_rejoin,
|
||||
find_entity_id,
|
||||
make_attribute,
|
||||
make_zcl_header,
|
||||
send_attributes_report,
|
||||
)
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
|
@ -66,12 +64,9 @@ async def test_device_tracker(hass, zha_device_joined_restored, zigpy_device_dt)
|
|||
assert hass.states.get(entity_id).state == STATE_NOT_HOME
|
||||
|
||||
# turn state flip
|
||||
attr = make_attribute(0x0020, 23)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
|
||||
attr = make_attribute(0x0021, 200)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await send_attributes_report(
|
||||
hass, cluster, {0x0000: 0, 0x0020: 23, 0x0021: 200, 0x0001: 2}
|
||||
)
|
||||
|
||||
zigpy_device_dt.last_seen = time.time() + 10
|
||||
next_update = dt_util.utcnow() + timedelta(seconds=30)
|
||||
|
|
|
@ -3,7 +3,6 @@ from unittest.mock import call
|
|||
|
||||
import pytest
|
||||
import zigpy.zcl.clusters.hvac as hvac
|
||||
import zigpy.zcl.foundation as zcl_f
|
||||
|
||||
from homeassistant.components import fan
|
||||
from homeassistant.components.fan import ATTR_SPEED, DOMAIN, SERVICE_SET_SPEED
|
||||
|
@ -20,8 +19,7 @@ from .common import (
|
|||
async_enable_traffic,
|
||||
async_test_rejoin,
|
||||
find_entity_id,
|
||||
make_attribute,
|
||||
make_zcl_header,
|
||||
send_attributes_report,
|
||||
)
|
||||
|
||||
|
||||
|
@ -52,16 +50,11 @@ async def test_fan(hass, zha_device_joined_restored, zigpy_device):
|
|||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
# turn on at fan
|
||||
attr = make_attribute(0, 1)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 2, 0: 1, 2: 3})
|
||||
assert hass.states.get(entity_id).state == STATE_ON
|
||||
|
||||
# turn off at fan
|
||||
attr.value.value = 0
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 1, 0: 0, 2: 2})
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
# turn on from HA
|
||||
|
|
|
@ -19,8 +19,7 @@ from .common import (
|
|||
async_enable_traffic,
|
||||
async_test_rejoin,
|
||||
find_entity_id,
|
||||
make_attribute,
|
||||
make_zcl_header,
|
||||
send_attributes_report,
|
||||
)
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
|
@ -190,26 +189,18 @@ async def test_light(
|
|||
async def async_test_on_off_from_light(hass, cluster, entity_id):
|
||||
"""Test on off functionality from the light."""
|
||||
# turn on at light
|
||||
attr = make_attribute(0, 1)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 0, 0: 1, 2: 3})
|
||||
assert hass.states.get(entity_id).state == STATE_ON
|
||||
|
||||
# turn off at light
|
||||
attr.value.value = 0
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 1, 0: 0, 2: 3})
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
|
||||
async def async_test_on_from_light(hass, cluster, entity_id):
|
||||
"""Test on off functionality from the light."""
|
||||
# turn on at light
|
||||
attr = make_attribute(0, 1)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: -1, 0: 1, 2: 2})
|
||||
assert hass.states.get(entity_id).state == STATE_ON
|
||||
|
||||
|
||||
|
@ -316,10 +307,10 @@ async def async_test_level_on_off_from_hass(
|
|||
|
||||
async def async_test_dimmer_from_light(hass, cluster, entity_id, level, expected_state):
|
||||
"""Test dimmer functionality from the light."""
|
||||
attr = make_attribute(0, level)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await send_attributes_report(
|
||||
hass, cluster, {1: level + 10, 0: level, 2: level - 10 or 22}
|
||||
)
|
||||
assert hass.states.get(entity_id).state == expected_state
|
||||
# hass uses None for brightness of 0 in state attributes
|
||||
if level == 0:
|
||||
|
|
|
@ -10,12 +10,7 @@ import zigpy.zcl.foundation as zcl_f
|
|||
from homeassistant.components.lock import DOMAIN
|
||||
from homeassistant.const import STATE_LOCKED, STATE_UNAVAILABLE, STATE_UNLOCKED
|
||||
|
||||
from .common import (
|
||||
async_enable_traffic,
|
||||
find_entity_id,
|
||||
make_attribute,
|
||||
make_zcl_header,
|
||||
)
|
||||
from .common import async_enable_traffic, find_entity_id, send_attributes_report
|
||||
|
||||
from tests.common import mock_coro
|
||||
|
||||
|
@ -58,16 +53,11 @@ async def test_lock(hass, lock):
|
|||
assert hass.states.get(entity_id).state == STATE_UNLOCKED
|
||||
|
||||
# set state to locked
|
||||
attr = make_attribute(0, 1)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 0, 0: 1, 2: 2})
|
||||
assert hass.states.get(entity_id).state == STATE_LOCKED
|
||||
|
||||
# set state to unlocked
|
||||
attr.value.value = 2
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 0, 0: 2, 2: 3})
|
||||
assert hass.states.get(entity_id).state == STATE_UNLOCKED
|
||||
|
||||
# lock from HA
|
||||
|
|
|
@ -6,7 +6,6 @@ import zigpy.zcl.clusters.general as general
|
|||
import zigpy.zcl.clusters.homeautomation as homeautomation
|
||||
import zigpy.zcl.clusters.measurement as measurement
|
||||
import zigpy.zcl.clusters.smartenergy as smartenergy
|
||||
import zigpy.zcl.foundation as zcl_f
|
||||
|
||||
from homeassistant.components.sensor import DOMAIN
|
||||
import homeassistant.config as config_util
|
||||
|
@ -28,38 +27,41 @@ from .common import (
|
|||
async_enable_traffic,
|
||||
async_test_rejoin,
|
||||
find_entity_id,
|
||||
make_attribute,
|
||||
make_zcl_header,
|
||||
send_attribute_report,
|
||||
send_attributes_report,
|
||||
)
|
||||
|
||||
|
||||
async def async_test_humidity(hass, cluster, entity_id):
|
||||
"""Test humidity sensor."""
|
||||
await send_attribute_report(hass, cluster, 0, 1000)
|
||||
await send_attributes_report(hass, cluster, {1: 1, 0: 1000, 2: 100})
|
||||
assert_state(hass, entity_id, "10.0", UNIT_PERCENTAGE)
|
||||
|
||||
|
||||
async def async_test_temperature(hass, cluster, entity_id):
|
||||
"""Test temperature sensor."""
|
||||
await send_attribute_report(hass, cluster, 0, 2900)
|
||||
await send_attributes_report(hass, cluster, {1: 1, 0: 2900, 2: 100})
|
||||
assert_state(hass, entity_id, "29.0", "°C")
|
||||
|
||||
|
||||
async def async_test_pressure(hass, cluster, entity_id):
|
||||
"""Test pressure sensor."""
|
||||
await send_attribute_report(hass, cluster, 0, 1000)
|
||||
await send_attributes_report(hass, cluster, {1: 1, 0: 1000, 2: 10000})
|
||||
assert_state(hass, entity_id, "1000", "hPa")
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1000, 20: -1, 16: 10000})
|
||||
assert_state(hass, entity_id, "1000", "hPa")
|
||||
|
||||
|
||||
async def async_test_illuminance(hass, cluster, entity_id):
|
||||
"""Test illuminance sensor."""
|
||||
await send_attribute_report(hass, cluster, 0, 10)
|
||||
await send_attributes_report(hass, cluster, {1: 1, 0: 10, 2: 20})
|
||||
assert_state(hass, entity_id, "1.0", "lx")
|
||||
|
||||
|
||||
async def async_test_metering(hass, cluster, entity_id):
|
||||
"""Test metering sensor."""
|
||||
await send_attribute_report(hass, cluster, 1024, 12345)
|
||||
await send_attributes_report(hass, cluster, {1025: 1, 1024: 12345, 1026: 100})
|
||||
assert_state(hass, entity_id, "12345.0", "unknown")
|
||||
|
||||
|
||||
|
@ -73,17 +75,17 @@ async def async_test_electrical_measurement(hass, cluster, entity_id):
|
|||
new_callable=mock.PropertyMock,
|
||||
) as divisor_mock:
|
||||
divisor_mock.return_value = 1
|
||||
await send_attribute_report(hass, cluster, 1291, 100)
|
||||
await send_attributes_report(hass, cluster, {0: 1, 1291: 100, 10: 1000})
|
||||
assert_state(hass, entity_id, "100", "W")
|
||||
|
||||
await send_attribute_report(hass, cluster, 1291, 99)
|
||||
await send_attributes_report(hass, cluster, {0: 1, 1291: 99, 10: 1000})
|
||||
assert_state(hass, entity_id, "99", "W")
|
||||
|
||||
divisor_mock.return_value = 10
|
||||
await send_attribute_report(hass, cluster, 1291, 1000)
|
||||
await send_attributes_report(hass, cluster, {0: 1, 1291: 1000, 10: 5000})
|
||||
assert_state(hass, entity_id, "100", "W")
|
||||
|
||||
await send_attribute_report(hass, cluster, 1291, 99)
|
||||
await send_attributes_report(hass, cluster, {0: 1, 1291: 99, 10: 5000})
|
||||
assert_state(hass, entity_id, "9.9", "W")
|
||||
|
||||
|
||||
|
@ -141,18 +143,6 @@ async def test_sensor(
|
|||
await async_test_rejoin(hass, zigpy_device, [cluster], (report_count,))
|
||||
|
||||
|
||||
async def send_attribute_report(hass, cluster, attrid, value):
|
||||
"""Cause the sensor to receive an attribute report from the network.
|
||||
|
||||
This is to simulate the normal device communication that happens when a
|
||||
device is paired to the zigbee network.
|
||||
"""
|
||||
attr = make_attribute(attrid, value)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
def assert_state(hass, entity_id, state, unit_of_measurement):
|
||||
"""Check that the state is what is expected.
|
||||
|
||||
|
|
|
@ -12,8 +12,7 @@ from .common import (
|
|||
async_enable_traffic,
|
||||
async_test_rejoin,
|
||||
find_entity_id,
|
||||
make_attribute,
|
||||
make_zcl_header,
|
||||
send_attributes_report,
|
||||
)
|
||||
|
||||
from tests.common import mock_coro
|
||||
|
@ -53,16 +52,11 @@ async def test_switch(hass, zha_device_joined_restored, zigpy_device):
|
|||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
# turn on at switch
|
||||
attr = make_attribute(0, 1)
|
||||
hdr = make_zcl_header(zcl_f.Command.Report_Attributes)
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 0, 0: 1, 2: 2})
|
||||
assert hass.states.get(entity_id).state == STATE_ON
|
||||
|
||||
# turn off at switch
|
||||
attr.value.value = 0
|
||||
cluster.handle_message(hdr, [[attr]])
|
||||
await hass.async_block_till_done()
|
||||
await send_attributes_report(hass, cluster, {1: 1, 0: 0, 2: 2})
|
||||
assert hass.states.get(entity_id).state == STATE_OFF
|
||||
|
||||
# turn on from HA
|
||||
|
|
Loading…
Add table
Reference in a new issue