mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Bump ZHA to 0.0.57 (#143963)
* Use new (internal) cluster handler IDs in unit tests * Always add a profile_id to created endpoints * Use new library decimal formatting * Implement the ENUM device class for sensors * Use the suggested display precision hint * Revert "Implement the ENUM device class for sensors" This reverts commit d11ab268121b7ffe67c81e45fdc46004fb57a22a. * Bump ZHA to 0.0.57 * Add strings for v2 quirk entities * Use ZHA library diagnostics * Update snapshot * Revert ZHA change that reports a cover state of `open` if either lift or tilt axes are `open` This is an interim change to address issues with some cover 'relay' type devices which falsely report support for both lift and tilt. In reality these only support one axes or the other, with users using yaml overrides to restrict functionality in HA. Devices that genuinely support both movement axes will behave the same as they did prior to https://github.com/zigpy/zha/pull/376 https://github.com/home-assistant/core/pull/141447 A subsequent PR will be made to allow users to override the covering type in a way that allows the entity handler to be aware of the configuration, calculating the state accordingly. * Spelling mistake --------- Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com> Co-authored-by: Jack <46714706+jeverley@users.noreply.github.com>
This commit is contained in:
parent
0f5d5ab0a2
commit
8760a82dfa
@ -6,26 +6,14 @@ import dataclasses
|
||||
from importlib.metadata import version
|
||||
from typing import Any
|
||||
|
||||
from zha.application.const import (
|
||||
ATTR_ATTRIBUTE,
|
||||
ATTR_DEVICE_TYPE,
|
||||
ATTR_IEEE,
|
||||
ATTR_IN_CLUSTERS,
|
||||
ATTR_OUT_CLUSTERS,
|
||||
ATTR_PROFILE_ID,
|
||||
ATTR_VALUE,
|
||||
UNKNOWN,
|
||||
)
|
||||
from zha.application.const import ATTR_IEEE
|
||||
from zha.application.gateway import Gateway
|
||||
from zha.zigbee.device import Device
|
||||
from zigpy.config import CONF_NWK_EXTENDED_PAN_ID
|
||||
from zigpy.profiles import PROFILES
|
||||
from zigpy.types import Channels
|
||||
from zigpy.zcl import Cluster
|
||||
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_ID, CONF_NAME, CONF_UNIQUE_ID
|
||||
from homeassistant.const import CONF_UNIQUE_ID
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
|
||||
@ -44,6 +32,7 @@ KEYS_TO_REDACT = {
|
||||
"network_key",
|
||||
CONF_NWK_EXTENDED_PAN_ID,
|
||||
"partner_ieee",
|
||||
"device_ieee",
|
||||
}
|
||||
|
||||
ATTRIBUTES = "attributes"
|
||||
@ -122,60 +111,5 @@ async def async_get_device_diagnostics(
|
||||
) -> dict[str, Any]:
|
||||
"""Return diagnostics for a device."""
|
||||
zha_device_proxy: ZHADeviceProxy = async_get_zha_device_proxy(hass, device.id)
|
||||
device_info: dict[str, Any] = zha_device_proxy.zha_device_info
|
||||
device_info[CLUSTER_DETAILS] = get_endpoint_cluster_attr_data(
|
||||
zha_device_proxy.device
|
||||
)
|
||||
return async_redact_data(device_info, KEYS_TO_REDACT)
|
||||
|
||||
|
||||
def get_endpoint_cluster_attr_data(zha_device: Device) -> dict:
|
||||
"""Return endpoint cluster attribute data."""
|
||||
cluster_details = {}
|
||||
for ep_id, endpoint in zha_device.device.endpoints.items():
|
||||
if ep_id == 0:
|
||||
continue
|
||||
endpoint_key = (
|
||||
f"{PROFILES.get(endpoint.profile_id).DeviceType(endpoint.device_type).name}"
|
||||
if PROFILES.get(endpoint.profile_id) is not None
|
||||
and endpoint.device_type is not None
|
||||
else UNKNOWN
|
||||
)
|
||||
cluster_details[ep_id] = {
|
||||
ATTR_DEVICE_TYPE: {
|
||||
CONF_NAME: endpoint_key,
|
||||
CONF_ID: endpoint.device_type,
|
||||
},
|
||||
ATTR_PROFILE_ID: endpoint.profile_id,
|
||||
ATTR_IN_CLUSTERS: {
|
||||
f"0x{cluster_id:04x}": {
|
||||
"endpoint_attribute": cluster.ep_attribute,
|
||||
**get_cluster_attr_data(cluster),
|
||||
}
|
||||
for cluster_id, cluster in endpoint.in_clusters.items()
|
||||
},
|
||||
ATTR_OUT_CLUSTERS: {
|
||||
f"0x{cluster_id:04x}": {
|
||||
"endpoint_attribute": cluster.ep_attribute,
|
||||
**get_cluster_attr_data(cluster),
|
||||
}
|
||||
for cluster_id, cluster in endpoint.out_clusters.items()
|
||||
},
|
||||
}
|
||||
return cluster_details
|
||||
|
||||
|
||||
def get_cluster_attr_data(cluster: Cluster) -> dict:
|
||||
"""Return cluster attribute data."""
|
||||
return {
|
||||
ATTRIBUTES: {
|
||||
f"0x{attr_id:04x}": {
|
||||
ATTR_ATTRIBUTE: repr(attr_def),
|
||||
ATTR_VALUE: cluster.get(attr_def.name),
|
||||
}
|
||||
for attr_id, attr_def in cluster.attributes.items()
|
||||
},
|
||||
UNSUPPORTED_ATTRIBUTES: sorted(
|
||||
cluster.unsupported_attributes, key=lambda v: (isinstance(v, str), v)
|
||||
),
|
||||
}
|
||||
diagnostics_json: dict[str, Any] = zha_device_proxy.device.get_diagnostics_json()
|
||||
return async_redact_data(diagnostics_json, KEYS_TO_REDACT)
|
||||
|
@ -21,7 +21,7 @@
|
||||
"zha",
|
||||
"universal_silabs_flasher"
|
||||
],
|
||||
"requirements": ["zha==0.0.56"],
|
||||
"requirements": ["zha==0.0.57"],
|
||||
"usb": [
|
||||
{
|
||||
"vid": "10C4",
|
||||
|
@ -138,6 +138,11 @@ class Sensor(ZHAEntity, SensorEntity):
|
||||
entity_description.device_class.value
|
||||
)
|
||||
|
||||
if entity.info_object.suggested_display_precision is not None:
|
||||
self._attr_suggested_display_precision = (
|
||||
entity.info_object.suggested_display_precision
|
||||
)
|
||||
|
||||
@property
|
||||
def native_value(self) -> StateType:
|
||||
"""Return the state of the entity."""
|
||||
|
@ -1128,6 +1128,15 @@
|
||||
},
|
||||
"water_interval": {
|
||||
"name": "Water interval"
|
||||
},
|
||||
"hush_duration": {
|
||||
"name": "Hush duration"
|
||||
},
|
||||
"temperature_control_accuracy": {
|
||||
"name": "Temperature control accuracy"
|
||||
},
|
||||
"external_temperature_sensor_value": {
|
||||
"name": "External temperature sensor value"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
@ -1349,6 +1358,15 @@
|
||||
},
|
||||
"speed": {
|
||||
"name": "Speed"
|
||||
},
|
||||
"led_brightness": {
|
||||
"name": "LED brightness"
|
||||
},
|
||||
"alarm_sound_level": {
|
||||
"name": "Alarm sound level"
|
||||
},
|
||||
"alarm_sound_mode": {
|
||||
"name": "Alarm sound mode"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
@ -1699,6 +1717,9 @@
|
||||
},
|
||||
"device_status": {
|
||||
"name": "Device status"
|
||||
},
|
||||
"lifetime": {
|
||||
"name": "Lifetime"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
@ -1908,6 +1929,12 @@
|
||||
},
|
||||
"auto_clean": {
|
||||
"name": "Auto clean"
|
||||
},
|
||||
"test_mode": {
|
||||
"name": "Test mode"
|
||||
},
|
||||
"external_temperature_sensor": {
|
||||
"name": "External temperature sensor"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
requirements_all.txt
generated
2
requirements_all.txt
generated
@ -3162,7 +3162,7 @@ zeroconf==0.146.5
|
||||
zeversolar==0.3.2
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha==0.0.56
|
||||
zha==0.0.57
|
||||
|
||||
# homeassistant.components.zhong_hong
|
||||
zhong-hong-hvac==1.0.13
|
||||
|
2
requirements_test_all.txt
generated
2
requirements_test_all.txt
generated
@ -2561,7 +2561,7 @@ zeroconf==0.146.5
|
||||
zeversolar==0.3.2
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha==0.0.56
|
||||
zha==0.0.57
|
||||
|
||||
# homeassistant.components.zwave_js
|
||||
zwave-js-server-python==0.63.0
|
||||
|
@ -17,6 +17,7 @@ from zigpy.const import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_PROFILE, SIG_EP_TYPE
|
||||
import zigpy.device
|
||||
import zigpy.group
|
||||
import zigpy.profiles
|
||||
from zigpy.profiles import zha
|
||||
import zigpy.quirks
|
||||
import zigpy.state
|
||||
import zigpy.types
|
||||
@ -173,6 +174,7 @@ async def zigpy_app_controller():
|
||||
dev.model = "Coordinator Model"
|
||||
|
||||
ep = dev.add_endpoint(1)
|
||||
ep.profile_id = zha.PROFILE_ID
|
||||
ep.add_input_cluster(Basic.cluster_id)
|
||||
ep.add_input_cluster(Groups.cluster_id)
|
||||
|
||||
|
@ -154,31 +154,21 @@
|
||||
# name: test_diagnostics_for_device
|
||||
dict({
|
||||
'active_coordinator': False,
|
||||
'area_id': None,
|
||||
'available': True,
|
||||
'cluster_details': dict({
|
||||
'device_type': 'EndDevice',
|
||||
'endpoints': dict({
|
||||
'1': dict({
|
||||
'device_type': dict({
|
||||
'id': 1025,
|
||||
'name': 'IAS_ANCILLARY_CONTROL',
|
||||
}),
|
||||
'in_clusters': dict({
|
||||
'0x0500': dict({
|
||||
'attributes': dict({
|
||||
'0x0000': dict({
|
||||
'attribute': "ZCLAttributeDef(id=0x0000, name='zone_state', type=<enum 'ZoneState'>, zcl_type=<DataTypeId.enum8: 48>, access=<ZCLAttributeAccess.Read: 1>, mandatory=True, is_manufacturer_specific=False)",
|
||||
'value': None,
|
||||
}),
|
||||
'0x0001': dict({
|
||||
'attribute': "ZCLAttributeDef(id=0x0001, name='zone_type', type=<enum 'ZoneType'>, zcl_type=<DataTypeId.uint16: 33>, access=<ZCLAttributeAccess.Read: 1>, mandatory=True, is_manufacturer_specific=False)",
|
||||
'value': None,
|
||||
}),
|
||||
'0x0002': dict({
|
||||
'attribute': "ZCLAttributeDef(id=0x0002, name='zone_status', type=<flag 'ZoneStatus'>, zcl_type=<DataTypeId.map16: 25>, access=<ZCLAttributeAccess.Read: 1>, mandatory=True, is_manufacturer_specific=False)",
|
||||
'value': None,
|
||||
}),
|
||||
'0x0010': dict({
|
||||
'attribute': "ZCLAttributeDef(id=0x0010, name='cie_addr', type=<class 'zigpy.types.named.EUI64'>, zcl_type=<DataTypeId.EUI64: 240>, access=<ZCLAttributeAccess.Read|Write: 3>, mandatory=True, is_manufacturer_specific=False)",
|
||||
'in_clusters': list([
|
||||
dict({
|
||||
'attributes': list([
|
||||
dict({
|
||||
'id': '0x0010',
|
||||
'name': 'cie_addr',
|
||||
'unsupported': False,
|
||||
'value': list([
|
||||
50,
|
||||
79,
|
||||
@ -189,61 +179,82 @@
|
||||
21,
|
||||
0,
|
||||
]),
|
||||
'zcl_type': 'EUI64',
|
||||
}),
|
||||
'0x0011': dict({
|
||||
'attribute': "ZCLAttributeDef(id=0x0011, name='zone_id', type=<class 'zigpy.types.basic.uint8_t'>, zcl_type=<DataTypeId.uint8: 32>, access=<ZCLAttributeAccess.Read: 1>, mandatory=True, is_manufacturer_specific=False)",
|
||||
dict({
|
||||
'id': '0x0013',
|
||||
'name': 'current_zone_sensitivity_level',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'uint8',
|
||||
}),
|
||||
'0x0012': dict({
|
||||
'attribute': "ZCLAttributeDef(id=0x0012, name='num_zone_sensitivity_levels_supported', type=<class 'zigpy.types.basic.uint8_t'>, zcl_type=<DataTypeId.uint8: 32>, access=<ZCLAttributeAccess.Read: 1>, mandatory=False, is_manufacturer_specific=False)",
|
||||
dict({
|
||||
'id': '0x0012',
|
||||
'name': 'num_zone_sensitivity_levels_supported',
|
||||
'unsupported': True,
|
||||
'value': None,
|
||||
'zcl_type': 'uint8',
|
||||
}),
|
||||
'0x0013': dict({
|
||||
'attribute': "ZCLAttributeDef(id=0x0013, name='current_zone_sensitivity_level', type=<class 'zigpy.types.basic.uint8_t'>, zcl_type=<DataTypeId.uint8: 32>, access=<ZCLAttributeAccess.Read|Write: 3>, mandatory=False, is_manufacturer_specific=False)",
|
||||
dict({
|
||||
'id': '0x0011',
|
||||
'name': 'zone_id',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'uint8',
|
||||
}),
|
||||
}),
|
||||
dict({
|
||||
'id': '0x0000',
|
||||
'name': 'zone_state',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'enum8',
|
||||
}),
|
||||
dict({
|
||||
'id': '0x0002',
|
||||
'name': 'zone_status',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'map16',
|
||||
}),
|
||||
dict({
|
||||
'id': '0x0001',
|
||||
'name': 'zone_type',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'uint16',
|
||||
}),
|
||||
]),
|
||||
'cluster_id': '0x0500',
|
||||
'endpoint_attribute': 'ias_zone',
|
||||
'unsupported_attributes': list([
|
||||
18,
|
||||
'current_zone_sensitivity_level',
|
||||
]),
|
||||
}),
|
||||
'0x0501': dict({
|
||||
'attributes': dict({
|
||||
'0xfffd': dict({
|
||||
'attribute': "ZCLAttributeDef(id=0xFFFD, name='cluster_revision', type=<class 'zigpy.types.basic.uint16_t'>, zcl_type=<DataTypeId.uint16: 33>, access=<ZCLAttributeAccess.Read: 1>, mandatory=True, is_manufacturer_specific=False)",
|
||||
dict({
|
||||
'attributes': list([
|
||||
dict({
|
||||
'id': '0xfffd',
|
||||
'name': 'cluster_revision',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'uint16',
|
||||
}),
|
||||
'0xfffe': dict({
|
||||
'attribute': "ZCLAttributeDef(id=0xFFFE, name='reporting_status', type=<enum 'AttributeReportingStatus'>, zcl_type=<DataTypeId.enum8: 48>, access=<ZCLAttributeAccess.Read: 1>, mandatory=False, is_manufacturer_specific=False)",
|
||||
dict({
|
||||
'id': '0xfffe',
|
||||
'name': 'reporting_status',
|
||||
'unsupported': False,
|
||||
'value': None,
|
||||
'zcl_type': 'enum8',
|
||||
}),
|
||||
}),
|
||||
]),
|
||||
'cluster_id': '0x0501',
|
||||
'endpoint_attribute': 'ias_ace',
|
||||
'unsupported_attributes': list([
|
||||
4096,
|
||||
'unknown_attribute_name',
|
||||
]),
|
||||
}),
|
||||
}),
|
||||
'out_clusters': dict({
|
||||
}),
|
||||
]),
|
||||
'out_clusters': list([
|
||||
]),
|
||||
'profile_id': 260,
|
||||
}),
|
||||
}),
|
||||
'device_type': 'EndDevice',
|
||||
'endpoint_names': list([
|
||||
dict({
|
||||
'name': 'IAS_ANCILLARY_CONTROL',
|
||||
}),
|
||||
]),
|
||||
'entities': list([
|
||||
dict({
|
||||
'entity_id': 'alarm_control_panel.fakemanufacturer_fakemodel_alarm_control_panel',
|
||||
'name': 'FakeManufacturer FakeModel',
|
||||
}),
|
||||
]),
|
||||
'friendly_manufacturer': 'FakeManufacturer',
|
||||
'friendly_model': 'FakeModel',
|
||||
'ieee': '**REDACTED**',
|
||||
'lqi': None,
|
||||
'manufacturer': 'FakeManufacturer',
|
||||
@ -252,7 +263,22 @@
|
||||
'name': 'FakeManufacturer FakeModel',
|
||||
'neighbors': list([
|
||||
]),
|
||||
'nwk': 47004,
|
||||
'node_descriptor': dict({
|
||||
'aps_flags': 0,
|
||||
'complex_descriptor_available': False,
|
||||
'descriptor_capability_field': 0,
|
||||
'frequency_band': 8,
|
||||
'logical_type': 'EndDevice',
|
||||
'mac_capability_flags': 140,
|
||||
'manufacturer_code': 4098,
|
||||
'maximum_buffer_size': 82,
|
||||
'maximum_incoming_transfer_size': 82,
|
||||
'maximum_outgoing_transfer_size': 82,
|
||||
'reserved': 0,
|
||||
'server_mask': 0,
|
||||
'user_descriptor_available': False,
|
||||
}),
|
||||
'nwk': '0xB79C',
|
||||
'power_source': 'Mains',
|
||||
'quirk_applied': False,
|
||||
'quirk_class': 'zigpy.device.Device',
|
||||
@ -260,37 +286,100 @@
|
||||
'routes': list([
|
||||
]),
|
||||
'rssi': None,
|
||||
'signature': dict({
|
||||
'endpoints': dict({
|
||||
'1': dict({
|
||||
'device_type': '0x0401',
|
||||
'input_clusters': list([
|
||||
'0x0500',
|
||||
'0x0501',
|
||||
]),
|
||||
'output_clusters': list([
|
||||
]),
|
||||
'profile_id': '0x0104',
|
||||
'version': 1,
|
||||
'zha_lib_entities': dict({
|
||||
'alarm_control_panel': list([
|
||||
dict({
|
||||
'info_object': dict({
|
||||
'available': True,
|
||||
'class_name': 'AlarmControlPanel',
|
||||
'cluster_handlers': list([
|
||||
dict({
|
||||
'class_name': 'IasAceClusterHandler',
|
||||
'cluster': dict({
|
||||
'id': 1281,
|
||||
'name': 'IAS Ancillary Control Equipment',
|
||||
'type': 'server',
|
||||
}),
|
||||
'endpoint_id': 1,
|
||||
'generic_id': 'cluster_handler_0x0501',
|
||||
'id': '1:0x0501',
|
||||
'status': 'INITIALIZED',
|
||||
'unique_id': '**REDACTED**',
|
||||
'value_attribute': None,
|
||||
}),
|
||||
]),
|
||||
'code_arm_required': False,
|
||||
'code_format': 'number',
|
||||
'device_class': None,
|
||||
'device_ieee': '**REDACTED**',
|
||||
'enabled': True,
|
||||
'endpoint_id': 1,
|
||||
'entity_category': None,
|
||||
'entity_registry_enabled_default': True,
|
||||
'fallback_name': None,
|
||||
'group_id': None,
|
||||
'migrate_unique_ids': list([
|
||||
]),
|
||||
'platform': 'alarm_control_panel',
|
||||
'primary': False,
|
||||
'state_class': None,
|
||||
'supported_features': 15,
|
||||
'translation_key': 'alarm_control_panel',
|
||||
'unique_id': '**REDACTED**',
|
||||
}),
|
||||
'state': dict({
|
||||
'available': True,
|
||||
'class_name': 'AlarmControlPanel',
|
||||
'state': 'disarmed',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'manufacturer': 'FakeManufacturer',
|
||||
'model': 'FakeModel',
|
||||
'node_descriptor': dict({
|
||||
'aps_flags': 0,
|
||||
'complex_descriptor_available': 0,
|
||||
'descriptor_capability_field': 0,
|
||||
'frequency_band': 8,
|
||||
'logical_type': 2,
|
||||
'mac_capability_flags': 140,
|
||||
'manufacturer_code': 4098,
|
||||
'maximum_buffer_size': 82,
|
||||
'maximum_incoming_transfer_size': 82,
|
||||
'maximum_outgoing_transfer_size': 82,
|
||||
'reserved': 0,
|
||||
'server_mask': 0,
|
||||
'user_descriptor_available': 0,
|
||||
}),
|
||||
]),
|
||||
'binary_sensor': list([
|
||||
dict({
|
||||
'info_object': dict({
|
||||
'attribute_name': 'zone_status',
|
||||
'available': True,
|
||||
'class_name': 'IASZone',
|
||||
'cluster_handlers': list([
|
||||
dict({
|
||||
'class_name': 'IASZoneClusterHandler',
|
||||
'cluster': dict({
|
||||
'id': 1280,
|
||||
'name': 'IAS Zone',
|
||||
'type': 'server',
|
||||
}),
|
||||
'endpoint_id': 1,
|
||||
'generic_id': 'cluster_handler_0x0500',
|
||||
'id': '1:0x0500',
|
||||
'status': 'INITIALIZED',
|
||||
'unique_id': '**REDACTED**',
|
||||
'value_attribute': None,
|
||||
}),
|
||||
]),
|
||||
'device_class': None,
|
||||
'device_ieee': '**REDACTED**',
|
||||
'enabled': True,
|
||||
'endpoint_id': 1,
|
||||
'entity_category': None,
|
||||
'entity_registry_enabled_default': True,
|
||||
'fallback_name': None,
|
||||
'group_id': None,
|
||||
'migrate_unique_ids': list([
|
||||
]),
|
||||
'platform': 'binary_sensor',
|
||||
'primary': True,
|
||||
'state_class': None,
|
||||
'translation_key': 'ias_zone',
|
||||
'unique_id': '**REDACTED**',
|
||||
}),
|
||||
'state': dict({
|
||||
'available': True,
|
||||
'class_name': 'IASZone',
|
||||
'state': False,
|
||||
}),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
'user_given_name': None,
|
||||
})
|
||||
# ---
|
||||
|
@ -80,8 +80,8 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None:
|
||||
# load up cover domain
|
||||
cluster = zigpy_device.endpoints[1].window_covering
|
||||
cluster.PLUGGED_ATTR_READS = {
|
||||
WCAttrs.current_position_lift_percentage.name: 0,
|
||||
WCAttrs.current_position_tilt_percentage.name: 100,
|
||||
WCAttrs.current_position_lift_percentage.name: 0, # Zigbee open %
|
||||
WCAttrs.current_position_tilt_percentage.name: 100, # Zigbee closed %
|
||||
WCAttrs.window_covering_type.name: WCT.Tilt_blind_tilt_and_lift,
|
||||
WCAttrs.config_status.name: WCCS(~WCCS.Open_up_commands_reversed),
|
||||
}
|
||||
@ -114,8 +114,8 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None:
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == CoverState.OPEN
|
||||
assert state.attributes[ATTR_CURRENT_POSITION] == 100
|
||||
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 0
|
||||
assert state.attributes[ATTR_CURRENT_POSITION] == 100 # HA open %
|
||||
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 0 # HA closed %
|
||||
|
||||
# test that the state has changed from open to closed
|
||||
await send_attributes_report(
|
||||
@ -164,7 +164,9 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None:
|
||||
await send_attributes_report(
|
||||
hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 0}
|
||||
)
|
||||
assert hass.states.get(entity_id).state == CoverState.OPEN
|
||||
assert (
|
||||
hass.states.get(entity_id).state == CoverState.CLOSED
|
||||
) # CLOSED lift state currently takes precedence over OPEN tilt
|
||||
with patch("zigpy.zcl.Cluster.request", return_value=[0x1, zcl_f.Status.SUCCESS]):
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
|
@ -209,7 +209,7 @@ async def test_action(
|
||||
cluster_handler = (
|
||||
gateway.get_device(zigpy_device.ieee)
|
||||
.endpoints[1]
|
||||
.client_cluster_handlers["1:0x0006"]
|
||||
.client_cluster_handlers["1:0x0006_client"]
|
||||
)
|
||||
cluster_handler.zha_send_event(COMMAND_SINGLE, [])
|
||||
await hass.async_block_till_done()
|
||||
@ -252,7 +252,7 @@ async def test_invalid_zha_event_type(
|
||||
cluster_handler = (
|
||||
gateway.get_device(zigpy_device.ieee)
|
||||
.endpoints[1]
|
||||
.client_cluster_handlers["1:0x0006"]
|
||||
.client_cluster_handlers["1:0x0006_client"]
|
||||
)
|
||||
|
||||
# `zha_send_event` accepts only zigpy responses, lists, and dicts
|
||||
|
@ -199,6 +199,7 @@ async def test_if_fires_on_event(
|
||||
)
|
||||
ep = zigpy_device.add_endpoint(1)
|
||||
ep.add_output_cluster(0x0006)
|
||||
ep.profile_id = zigpy.profiles.zha.PROFILE_ID
|
||||
|
||||
zigpy_device.device_automation_triggers = {
|
||||
(SHAKEN, SHAKEN): {COMMAND: COMMAND_SHAKE},
|
||||
|
@ -62,10 +62,10 @@ async def async_test_temperature(hass: HomeAssistant, cluster: Cluster, entity_i
|
||||
async def async_test_pressure(hass: HomeAssistant, cluster: Cluster, entity_id: str):
|
||||
"""Test pressure sensor."""
|
||||
await send_attributes_report(hass, cluster, {1: 1, 0: 1000, 2: 10000})
|
||||
assert_state(hass, entity_id, "1000", UnitOfPressure.HPA)
|
||||
assert_state(hass, entity_id, "1000.0", UnitOfPressure.HPA)
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1000, 20: -1, 16: 10000})
|
||||
assert_state(hass, entity_id, "1000", UnitOfPressure.HPA)
|
||||
assert_state(hass, entity_id, "1000.0", UnitOfPressure.HPA)
|
||||
|
||||
|
||||
async def async_test_illuminance(hass: HomeAssistant, cluster: Cluster, entity_id: str):
|
||||
@ -167,14 +167,14 @@ async def async_test_electrical_measurement(
|
||||
# update divisor cached value
|
||||
await send_attributes_report(hass, cluster, {"ac_power_divisor": 1})
|
||||
await send_attributes_report(hass, cluster, {0: 1, 1291: 100, 10: 1000})
|
||||
assert_state(hass, entity_id, "100", UnitOfPower.WATT)
|
||||
assert_state(hass, entity_id, "100.0", UnitOfPower.WATT)
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 1291: 99, 10: 1000})
|
||||
assert_state(hass, entity_id, "99", UnitOfPower.WATT)
|
||||
assert_state(hass, entity_id, "99.0", UnitOfPower.WATT)
|
||||
|
||||
await send_attributes_report(hass, cluster, {"ac_power_divisor": 10})
|
||||
await send_attributes_report(hass, cluster, {0: 1, 1291: 1000, 10: 5000})
|
||||
assert_state(hass, entity_id, "100", UnitOfPower.WATT)
|
||||
assert_state(hass, entity_id, "100.0", UnitOfPower.WATT)
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 1291: 99, 10: 5000})
|
||||
assert_state(hass, entity_id, "9.9", UnitOfPower.WATT)
|
||||
@ -191,14 +191,14 @@ async def async_test_em_apparent_power(
|
||||
# update divisor cached value
|
||||
await send_attributes_report(hass, cluster, {"ac_power_divisor": 1})
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x050F: 100, 10: 1000})
|
||||
assert_state(hass, entity_id, "100", UnitOfApparentPower.VOLT_AMPERE)
|
||||
assert_state(hass, entity_id, "100.0", UnitOfApparentPower.VOLT_AMPERE)
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x050F: 99, 10: 1000})
|
||||
assert_state(hass, entity_id, "99", UnitOfApparentPower.VOLT_AMPERE)
|
||||
assert_state(hass, entity_id, "99.0", UnitOfApparentPower.VOLT_AMPERE)
|
||||
|
||||
await send_attributes_report(hass, cluster, {"ac_power_divisor": 10})
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x050F: 1000, 10: 5000})
|
||||
assert_state(hass, entity_id, "100", UnitOfApparentPower.VOLT_AMPERE)
|
||||
assert_state(hass, entity_id, "100.0", UnitOfApparentPower.VOLT_AMPERE)
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x050F: 99, 10: 5000})
|
||||
assert_state(hass, entity_id, "9.9", UnitOfApparentPower.VOLT_AMPERE)
|
||||
@ -211,17 +211,17 @@ async def async_test_em_power_factor(
|
||||
# update divisor cached value
|
||||
await send_attributes_report(hass, cluster, {"ac_power_divisor": 1})
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0510: 100, 10: 1000})
|
||||
assert_state(hass, entity_id, "100", PERCENTAGE)
|
||||
assert_state(hass, entity_id, "100.0", PERCENTAGE)
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0510: 99, 10: 1000})
|
||||
assert_state(hass, entity_id, "99", PERCENTAGE)
|
||||
assert_state(hass, entity_id, "99.0", PERCENTAGE)
|
||||
|
||||
await send_attributes_report(hass, cluster, {"ac_power_divisor": 10})
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0510: 100, 10: 5000})
|
||||
assert_state(hass, entity_id, "100", PERCENTAGE)
|
||||
assert_state(hass, entity_id, "100.0", PERCENTAGE)
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0510: 99, 10: 5000})
|
||||
assert_state(hass, entity_id, "99", PERCENTAGE)
|
||||
assert_state(hass, entity_id, "99.0", PERCENTAGE)
|
||||
|
||||
|
||||
async def async_test_em_rms_current(
|
||||
@ -230,14 +230,14 @@ async def async_test_em_rms_current(
|
||||
"""Test electrical measurement RMS Current sensor."""
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0508: 1234, 10: 1000})
|
||||
assert_state(hass, entity_id, "1.2", UnitOfElectricCurrent.AMPERE)
|
||||
assert_state(hass, entity_id, "1.234", UnitOfElectricCurrent.AMPERE)
|
||||
|
||||
await send_attributes_report(hass, cluster, {"ac_current_divisor": 10})
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0508: 236, 10: 1000})
|
||||
assert_state(hass, entity_id, "23.6", UnitOfElectricCurrent.AMPERE)
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0508: 1236, 10: 1000})
|
||||
assert_state(hass, entity_id, "124", UnitOfElectricCurrent.AMPERE)
|
||||
assert_state(hass, entity_id, "123.6", UnitOfElectricCurrent.AMPERE)
|
||||
|
||||
assert "rms_current_max" not in hass.states.get(entity_id).attributes
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x050A: 88, 10: 5000})
|
||||
@ -250,18 +250,18 @@ async def async_test_em_rms_voltage(
|
||||
"""Test electrical measurement RMS Voltage sensor."""
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0505: 1234, 10: 1000})
|
||||
assert_state(hass, entity_id, "123", UnitOfElectricPotential.VOLT)
|
||||
assert_state(hass, entity_id, "123.4", UnitOfElectricPotential.VOLT)
|
||||
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0505: 234, 10: 1000})
|
||||
assert_state(hass, entity_id, "23.4", UnitOfElectricPotential.VOLT)
|
||||
|
||||
await send_attributes_report(hass, cluster, {"ac_voltage_divisor": 100})
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0505: 2236, 10: 1000})
|
||||
assert_state(hass, entity_id, "22.4", UnitOfElectricPotential.VOLT)
|
||||
assert_state(hass, entity_id, "22.36", UnitOfElectricPotential.VOLT)
|
||||
|
||||
assert "rms_voltage_max" not in hass.states.get(entity_id).attributes
|
||||
await send_attributes_report(hass, cluster, {0: 1, 0x0507: 888, 10: 5000})
|
||||
assert hass.states.get(entity_id).attributes["rms_voltage_max"] == 8.9
|
||||
assert hass.states.get(entity_id).attributes["rms_voltage_max"] == 8.88
|
||||
|
||||
|
||||
async def async_test_powerconfiguration(
|
||||
@ -269,7 +269,7 @@ async def async_test_powerconfiguration(
|
||||
):
|
||||
"""Test powerconfiguration/battery sensor."""
|
||||
await send_attributes_report(hass, cluster, {33: 98})
|
||||
assert_state(hass, entity_id, "49", "%")
|
||||
assert_state(hass, entity_id, "49.0", "%")
|
||||
assert hass.states.get(entity_id).attributes["battery_voltage"] == 2.9
|
||||
assert hass.states.get(entity_id).attributes["battery_quantity"] == 3
|
||||
assert hass.states.get(entity_id).attributes["battery_size"] == "AAA"
|
||||
@ -288,7 +288,7 @@ async def async_test_powerconfiguration2(
|
||||
assert_state(hass, entity_id, STATE_UNKNOWN, "%")
|
||||
|
||||
await send_attributes_report(hass, cluster, {33: 98})
|
||||
assert_state(hass, entity_id, "49", "%")
|
||||
assert_state(hass, entity_id, "49.0", "%")
|
||||
|
||||
|
||||
async def async_test_device_temperature(
|
||||
@ -317,7 +317,7 @@ async def async_test_pi_heating_demand(
|
||||
await send_attributes_report(
|
||||
hass, cluster, {Thermostat.AttributeDefs.pi_heating_demand.id: 1}
|
||||
)
|
||||
assert_state(hass, entity_id, "1", "%")
|
||||
assert_state(hass, entity_id, "1.0", "%")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
Loading…
x
Reference in New Issue
Block a user