diff --git a/homeassistant/components/zha/diagnostics.py b/homeassistant/components/zha/diagnostics.py index 234f10d59ae..6c5fcba1f8b 100644 --- a/homeassistant/components/zha/diagnostics.py +++ b/homeassistant/components/zha/diagnostics.py @@ -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) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 04f3658d924..ae337c2a5f5 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -21,7 +21,7 @@ "zha", "universal_silabs_flasher" ], - "requirements": ["zha==0.0.56"], + "requirements": ["zha==0.0.57"], "usb": [ { "vid": "10C4", diff --git a/homeassistant/components/zha/sensor.py b/homeassistant/components/zha/sensor.py index a8383857e57..73d773b1640 100644 --- a/homeassistant/components/zha/sensor.py +++ b/homeassistant/components/zha/sensor.py @@ -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.""" diff --git a/homeassistant/components/zha/strings.json b/homeassistant/components/zha/strings.json index 04b709af1a0..d6a812569f5 100644 --- a/homeassistant/components/zha/strings.json +++ b/homeassistant/components/zha/strings.json @@ -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" } } } diff --git a/requirements_all.txt b/requirements_all.txt index bebe46bb660..aae49abd837 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -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 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index eaf4c924cf8..0788977826f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -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 diff --git a/tests/components/zha/conftest.py b/tests/components/zha/conftest.py index 96a61a6628b..df61fb499d2 100644 --- a/tests/components/zha/conftest.py +++ b/tests/components/zha/conftest.py @@ -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) diff --git a/tests/components/zha/snapshots/test_diagnostics.ambr b/tests/components/zha/snapshots/test_diagnostics.ambr index 7a599b00a21..44fb913489d 100644 --- a/tests/components/zha/snapshots/test_diagnostics.ambr +++ b/tests/components/zha/snapshots/test_diagnostics.ambr @@ -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=, zcl_type=, access=, mandatory=True, is_manufacturer_specific=False)", - 'value': None, - }), - '0x0001': dict({ - 'attribute': "ZCLAttributeDef(id=0x0001, name='zone_type', type=, zcl_type=, access=, mandatory=True, is_manufacturer_specific=False)", - 'value': None, - }), - '0x0002': dict({ - 'attribute': "ZCLAttributeDef(id=0x0002, name='zone_status', type=, zcl_type=, access=, mandatory=True, is_manufacturer_specific=False)", - 'value': None, - }), - '0x0010': dict({ - 'attribute': "ZCLAttributeDef(id=0x0010, name='cie_addr', type=, zcl_type=, access=, 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=, zcl_type=, access=, 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=, zcl_type=, access=, 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=, zcl_type=, access=, 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=, zcl_type=, access=, 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=, zcl_type=, access=, 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, }) # --- diff --git a/tests/components/zha/test_cover.py b/tests/components/zha/test_cover.py index 4bc4d6c97cf..70fdac2c313 100644 --- a/tests/components/zha/test_cover.py +++ b/tests/components/zha/test_cover.py @@ -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, diff --git a/tests/components/zha/test_device_action.py b/tests/components/zha/test_device_action.py index 8bee821654d..6708250e448 100644 --- a/tests/components/zha/test_device_action.py +++ b/tests/components/zha/test_device_action.py @@ -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 diff --git a/tests/components/zha/test_device_trigger.py b/tests/components/zha/test_device_trigger.py index 09b2d155547..ace3029dac9 100644 --- a/tests/components/zha/test_device_trigger.py +++ b/tests/components/zha/test_device_trigger.py @@ -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}, diff --git a/tests/components/zha/test_sensor.py b/tests/components/zha/test_sensor.py index 88fb9974c1b..863ea3964ab 100644 --- a/tests/components/zha/test_sensor.py +++ b/tests/components/zha/test_sensor.py @@ -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(