mirror of
https://github.com/elisspace/core.git
synced 2026-10-01 14:59:53 +00:00
Add KNX interface device with diagnostic entities (#89213)
This commit is contained in:
@@ -6,7 +6,7 @@ from unittest.mock import DEFAULT, AsyncMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
from xknx import XKNX
|
||||
from xknx.core import XknxConnectionState
|
||||
from xknx.core import XknxConnectionState, XknxConnectionType
|
||||
from xknx.dpt import DPTArray, DPTBinary
|
||||
from xknx.io import DEFAULT_MCAST_GRP, DEFAULT_MCAST_PORT
|
||||
from xknx.telegram import Telegram, TelegramDirection
|
||||
@@ -67,7 +67,8 @@ class KNXTestKit:
|
||||
# set XknxConnectionState.CONNECTED to avoid `unavailable` entities at startup
|
||||
# and start StateUpdater. This would be awaited on normal startup too.
|
||||
await self.xknx.connection_manager.connection_state_changed(
|
||||
XknxConnectionState.CONNECTED
|
||||
state=XknxConnectionState.CONNECTED,
|
||||
connection_type=XknxConnectionType.TUNNEL_TCP,
|
||||
)
|
||||
|
||||
def knx_ip_interface_mock():
|
||||
|
||||
@@ -38,7 +38,6 @@ async def test_binary_sensor_entity_category(
|
||||
]
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
await knx.assert_read("1/1/1")
|
||||
await knx.receive_response("1/1/1", True)
|
||||
@@ -65,7 +64,6 @@ async def test_binary_sensor(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
]
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 2
|
||||
|
||||
# StateUpdater initialize state
|
||||
await knx.assert_read("1/1/1")
|
||||
@@ -103,8 +101,6 @@ async def test_binary_sensor_ignore_internal_state(
|
||||
hass: HomeAssistant, knx: KNXTestKit
|
||||
) -> None:
|
||||
"""Test KNX binary_sensor with ignore_internal_state."""
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
|
||||
await knx.setup_integration(
|
||||
{
|
||||
BinarySensorSchema.PLATFORM: [
|
||||
@@ -122,39 +118,36 @@ async def test_binary_sensor_ignore_internal_state(
|
||||
]
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 2
|
||||
# binary_sensor defaults to STATE_OFF - state change form None
|
||||
assert len(events) == 2
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
|
||||
# receive initial ON telegram
|
||||
await knx.receive_write("1/1/1", True)
|
||||
await knx.receive_write("2/2/2", True)
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 4
|
||||
assert len(events) == 2
|
||||
|
||||
# receive second ON telegram - ignore_internal_state shall force state_changed event
|
||||
await knx.receive_write("1/1/1", True)
|
||||
await knx.receive_write("2/2/2", True)
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 5
|
||||
assert len(events) == 3
|
||||
|
||||
# receive first OFF telegram
|
||||
await knx.receive_write("1/1/1", False)
|
||||
await knx.receive_write("2/2/2", False)
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 7
|
||||
assert len(events) == 5
|
||||
|
||||
# receive second OFF telegram - ignore_internal_state shall force state_changed event
|
||||
await knx.receive_write("1/1/1", False)
|
||||
await knx.receive_write("2/2/2", False)
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 8
|
||||
assert len(events) == 6
|
||||
|
||||
|
||||
async def test_binary_sensor_counter(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
"""Test KNX binary_sensor with context timeout."""
|
||||
async_fire_time_changed(hass, dt.utcnow())
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
context_timeout = 1
|
||||
|
||||
await knx.setup_integration(
|
||||
@@ -169,9 +162,7 @@ async def test_binary_sensor_counter(hass: HomeAssistant, knx: KNXTestKit) -> No
|
||||
]
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(events) == 1
|
||||
events.pop()
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
|
||||
# receive initial ON telegram
|
||||
await knx.receive_write("2/2/2", True)
|
||||
@@ -236,7 +227,6 @@ async def test_binary_sensor_reset(hass: HomeAssistant, knx: KNXTestKit) -> None
|
||||
]
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
# receive ON telegram
|
||||
await knx.receive_write("2/2/2", True)
|
||||
|
||||
@@ -18,7 +18,6 @@ from tests.common import async_capture_events, async_fire_time_changed
|
||||
|
||||
async def test_button_simple(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
"""Test KNX button with default payload."""
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
await knx.setup_integration(
|
||||
{
|
||||
ButtonSchema.PLATFORM: {
|
||||
@@ -27,9 +26,7 @@ async def test_button_simple(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(events) == 1
|
||||
events.pop()
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
|
||||
# press button
|
||||
await hass.services.async_call(
|
||||
|
||||
@@ -20,7 +20,6 @@ async def test_climate_basic_temperature_set(
|
||||
hass: HomeAssistant, knx: KNXTestKit
|
||||
) -> None:
|
||||
"""Test KNX climate basic."""
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
await knx.setup_integration(
|
||||
{
|
||||
ClimateSchema.PLATFORM: {
|
||||
@@ -31,9 +30,7 @@ async def test_climate_basic_temperature_set(
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(events) == 1
|
||||
events.pop()
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
|
||||
# read temperature
|
||||
await knx.assert_read("1/2/3")
|
||||
@@ -57,7 +54,6 @@ async def test_climate_basic_temperature_set(
|
||||
|
||||
async def test_climate_hvac_mode(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
"""Test KNX climate hvac mode."""
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
await knx.setup_integration(
|
||||
{
|
||||
ClimateSchema.PLATFORM: {
|
||||
@@ -72,9 +68,7 @@ async def test_climate_hvac_mode(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(events) == 1
|
||||
events.pop()
|
||||
async_capture_events(hass, "state_changed")
|
||||
|
||||
await hass.async_block_till_done()
|
||||
# read states state updater
|
||||
@@ -112,7 +106,6 @@ async def test_climate_preset_mode(
|
||||
hass: HomeAssistant, knx: KNXTestKit, entity_registry: er.EntityRegistry
|
||||
) -> None:
|
||||
"""Test KNX climate preset mode."""
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
await knx.setup_integration(
|
||||
{
|
||||
ClimateSchema.PLATFORM: {
|
||||
@@ -125,9 +118,7 @@ async def test_climate_preset_mode(
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(events) == 1
|
||||
events.pop()
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
|
||||
await hass.async_block_till_done()
|
||||
# read states state updater
|
||||
@@ -177,7 +168,6 @@ async def test_climate_preset_mode(
|
||||
|
||||
async def test_update_entity(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
"""Test update climate entity for KNX."""
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
await knx.setup_integration(
|
||||
{
|
||||
ClimateSchema.PLATFORM: {
|
||||
@@ -192,9 +182,7 @@ async def test_update_entity(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
)
|
||||
assert await async_setup_component(hass, "homeassistant", {})
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(events) == 1
|
||||
events.pop()
|
||||
async_capture_events(hass, "state_changed")
|
||||
|
||||
await hass.async_block_till_done()
|
||||
# read states state updater
|
||||
|
||||
@@ -11,7 +11,6 @@ from tests.common import async_capture_events
|
||||
|
||||
async def test_cover_basic(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
"""Test KNX cover basic."""
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
await knx.setup_integration(
|
||||
{
|
||||
CoverSchema.PLATFORM: {
|
||||
@@ -25,9 +24,7 @@ async def test_cover_basic(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
assert len(events) == 1
|
||||
events.pop()
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
|
||||
# read position state address and angle state address
|
||||
await knx.assert_read("1/0/2")
|
||||
|
||||
@@ -28,7 +28,6 @@ async def test_binary_expose(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
},
|
||||
)
|
||||
assert not hass.states.async_all()
|
||||
|
||||
# Change state to on
|
||||
hass.states.async_set(entity_id, "on", {})
|
||||
@@ -57,7 +56,6 @@ async def test_expose_attribute(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
},
|
||||
)
|
||||
assert not hass.states.async_all()
|
||||
|
||||
# Before init no response shall be sent
|
||||
await knx.receive_read("1/1/8")
|
||||
@@ -105,7 +103,6 @@ async def test_expose_attribute_with_default(
|
||||
}
|
||||
},
|
||||
)
|
||||
assert not hass.states.async_all()
|
||||
|
||||
# Before init default value shall be sent as response
|
||||
await knx.receive_read("1/1/8")
|
||||
@@ -152,7 +149,6 @@ async def test_expose_string(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
},
|
||||
)
|
||||
assert not hass.states.async_all()
|
||||
|
||||
# Before init default value shall be sent as response
|
||||
await knx.receive_read("1/1/8")
|
||||
@@ -185,7 +181,6 @@ async def test_expose_cooldown(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
},
|
||||
)
|
||||
assert not hass.states.async_all()
|
||||
# Change state to 1
|
||||
hass.states.async_set(entity_id, "1", {})
|
||||
await knx.assert_write("1/1/8", (1,))
|
||||
@@ -220,7 +215,6 @@ async def test_expose_conversion_exception(
|
||||
}
|
||||
},
|
||||
)
|
||||
assert not hass.states.async_all()
|
||||
|
||||
# Before init default value shall be sent as response
|
||||
await knx.receive_read("1/1/8")
|
||||
@@ -253,7 +247,6 @@ async def test_expose_with_date(
|
||||
}
|
||||
}
|
||||
)
|
||||
assert not hass.states.async_all()
|
||||
|
||||
await knx.assert_write("1/1/8", (0x7A, 0x1, 0x7, 0xE9, 0xD, 0xE, 0x20, 0x80))
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ async def test_fan_percent(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
# turn on fan with default speed (50%)
|
||||
await hass.services.async_call(
|
||||
@@ -63,7 +62,6 @@ async def test_fan_step(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
# turn on fan with default speed (50% - step 2)
|
||||
await hass.services.async_call(
|
||||
@@ -116,7 +114,6 @@ async def test_fan_oscillation(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
# turn on oscillation
|
||||
await hass.services.async_call(
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
"""Test KNX scene."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from xknx.core import XknxConnectionState, XknxConnectionType
|
||||
from xknx.telegram import IndividualAddress
|
||||
|
||||
from homeassistant.components.knx.sensor import SCAN_INTERVAL
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import dt
|
||||
|
||||
from .conftest import KNXTestKit
|
||||
|
||||
from tests.common import async_capture_events, async_fire_time_changed
|
||||
|
||||
|
||||
async def test_diagnostic_entities(
|
||||
hass: HomeAssistant, knx: KNXTestKit, entity_registry: er.EntityRegistry
|
||||
) -> None:
|
||||
"""Test diagnostic entities."""
|
||||
await knx.setup_integration({})
|
||||
|
||||
for entity_id in [
|
||||
"sensor.knx_interface_individual_address",
|
||||
"sensor.knx_interface_connected_since",
|
||||
"sensor.knx_interface_connection_type",
|
||||
"sensor.knx_interface_telegrams_incoming",
|
||||
"sensor.knx_interface_telegrams_incoming_error",
|
||||
"sensor.knx_interface_telegrams_outgoing",
|
||||
"sensor.knx_interface_telegrams_outgoing_error",
|
||||
"sensor.knx_interface_telegrams",
|
||||
]:
|
||||
entity = entity_registry.async_get(entity_id)
|
||||
assert entity.entity_category is EntityCategory.DIAGNOSTIC
|
||||
|
||||
for entity_id in [
|
||||
"sensor.knx_interface_telegrams_incoming",
|
||||
"sensor.knx_interface_telegrams_outgoing",
|
||||
]:
|
||||
entity = entity_registry.async_get(entity_id)
|
||||
assert entity.disabled is True
|
||||
|
||||
knx.xknx.connection_manager.cemi_count_incoming = 20
|
||||
knx.xknx.connection_manager.cemi_count_incoming_error = 1
|
||||
knx.xknx.connection_manager.cemi_count_outgoing = 10
|
||||
knx.xknx.connection_manager.cemi_count_outgoing_error = 2
|
||||
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
async_fire_time_changed(hass, dt.utcnow() + SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(events) == 3 # 5 polled sensors - 2 disabled
|
||||
events.clear()
|
||||
|
||||
for entity_id, test_state in [
|
||||
("sensor.knx_interface_individual_address", "0.0.0"),
|
||||
("sensor.knx_interface_connection_type", "Tunnel TCP"),
|
||||
# skipping connected_since timestamp
|
||||
("sensor.knx_interface_telegrams_incoming_error", "1"),
|
||||
("sensor.knx_interface_telegrams_outgoing_error", "2"),
|
||||
("sensor.knx_interface_telegrams", "31"),
|
||||
]:
|
||||
assert hass.states.get(entity_id).state == test_state
|
||||
|
||||
await knx.xknx.connection_manager.connection_state_changed(
|
||||
state=XknxConnectionState.DISCONNECTED
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 4 # 3 not always_available + 3 force_update - 2 disabled
|
||||
events.clear()
|
||||
|
||||
knx.xknx.current_address = IndividualAddress("1.1.1")
|
||||
await knx.xknx.connection_manager.connection_state_changed(
|
||||
state=XknxConnectionState.CONNECTED,
|
||||
connection_type=XknxConnectionType.TUNNEL_UDP,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 6 # all diagnostic sensors - counters are reset on connect
|
||||
|
||||
for entity_id, test_state in [
|
||||
("sensor.knx_interface_individual_address", "1.1.1"),
|
||||
("sensor.knx_interface_connection_type", "Tunnel UDP"),
|
||||
# skipping connected_since timestamp
|
||||
("sensor.knx_interface_telegrams_incoming_error", "0"),
|
||||
("sensor.knx_interface_telegrams_outgoing_error", "0"),
|
||||
("sensor.knx_interface_telegrams", "0"),
|
||||
]:
|
||||
assert hass.states.get(entity_id).state == test_state
|
||||
|
||||
|
||||
async def test_removed_entity(
|
||||
hass: HomeAssistant, knx: KNXTestKit, entity_registry: er.EntityRegistry
|
||||
) -> None:
|
||||
"""Test unregister callback when entity is removed."""
|
||||
await knx.setup_integration({})
|
||||
|
||||
with patch.object(
|
||||
knx.xknx.connection_manager, "unregister_connection_state_changed_cb"
|
||||
) as unregister_mock:
|
||||
entity_registry.async_update_entity(
|
||||
"sensor.knx_interface_connected_since",
|
||||
disabled_by=er.RegistryEntryDisabler.USER,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
unregister_mock.assert_called_once()
|
||||
@@ -36,7 +36,6 @@ async def test_light_simple(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
knx.assert_state("light.test", STATE_OFF)
|
||||
# turn on light
|
||||
|
||||
@@ -9,7 +9,9 @@ from homeassistant.helpers import entity_registry as er
|
||||
from .conftest import KNXTestKit
|
||||
|
||||
|
||||
async def test_activate_knx_scene(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
async def test_activate_knx_scene(
|
||||
hass: HomeAssistant, knx: KNXTestKit, entity_registry: er.EntityRegistry
|
||||
) -> None:
|
||||
"""Test KNX scene."""
|
||||
await knx.setup_integration(
|
||||
{
|
||||
@@ -23,10 +25,8 @@ async def test_activate_knx_scene(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
]
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
registry = er.async_get(hass)
|
||||
entity = registry.async_get("scene.test")
|
||||
entity = entity_registry.async_get("scene.test")
|
||||
assert entity.entity_category is EntityCategory.DIAGNOSTIC
|
||||
assert entity.unique_id == "1/1/1_24"
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ async def test_select_dpt_2_simple(hass: HomeAssistant, knx: KNXTestKit) -> None
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
state = hass.states.get("select.test")
|
||||
assert state.state is STATE_UNKNOWN
|
||||
|
||||
@@ -152,7 +151,6 @@ async def test_select_dpt_20_103_all_options(
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
state = hass.states.get("select.test")
|
||||
assert state.state is STATE_UNKNOWN
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ async def test_sensor(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
state = hass.states.get("sensor.test")
|
||||
assert state.state is STATE_UNKNOWN
|
||||
|
||||
@@ -44,7 +43,6 @@ async def test_sensor(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
async def test_always_callback(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
"""Test KNX sensor with always_callback."""
|
||||
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
await knx.setup_integration(
|
||||
{
|
||||
SensorSchema.PLATFORM: [
|
||||
@@ -64,32 +62,30 @@ async def test_always_callback(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
]
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 2
|
||||
# state changes form None to "unknown"
|
||||
assert len(events) == 2
|
||||
events = async_capture_events(hass, "state_changed")
|
||||
|
||||
# receive initial telegram
|
||||
await knx.receive_write("1/1/1", (0x42,))
|
||||
await knx.receive_write("2/2/2", (0x42,))
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 4
|
||||
assert len(events) == 2
|
||||
|
||||
# receive second telegram with identical payload
|
||||
# always_callback shall force state_changed event
|
||||
await knx.receive_write("1/1/1", (0x42,))
|
||||
await knx.receive_write("2/2/2", (0x42,))
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 5
|
||||
assert len(events) == 3
|
||||
|
||||
# receive telegram with different payload
|
||||
await knx.receive_write("1/1/1", (0xFA,))
|
||||
await knx.receive_write("2/2/2", (0xFA,))
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 7
|
||||
assert len(events) == 5
|
||||
|
||||
# receive telegram with second payload again
|
||||
# always_callback shall force state_changed event
|
||||
await knx.receive_write("1/1/1", (0xFA,))
|
||||
await knx.receive_write("2/2/2", (0xFA,))
|
||||
await hass.async_block_till_done()
|
||||
assert len(events) == 8
|
||||
assert len(events) == 6
|
||||
|
||||
@@ -23,7 +23,6 @@ async def test_switch_simple(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
# turn on switch
|
||||
await hass.services.async_call(
|
||||
@@ -66,7 +65,6 @@ async def test_switch_state(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
},
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
|
||||
# StateUpdater initialize state
|
||||
await knx.assert_read(_STATE_ADDRESS)
|
||||
|
||||
@@ -35,7 +35,6 @@ async def test_weather(hass: HomeAssistant, knx: KNXTestKit) -> None:
|
||||
}
|
||||
}
|
||||
)
|
||||
assert len(hass.states.async_all()) == 1
|
||||
state = hass.states.get("weather.test")
|
||||
assert state.state is ATTR_CONDITION_EXCEPTIONAL
|
||||
|
||||
|
||||
Reference in New Issue
Block a user