diff --git a/homeassistant/components/zwave_js/discovery_data_template.py b/homeassistant/components/zwave_js/discovery_data_template.py index 974cd2bfa44..23482bd33fe 100644 --- a/homeassistant/components/zwave_js/discovery_data_template.py +++ b/homeassistant/components/zwave_js/discovery_data_template.py @@ -201,7 +201,7 @@ class NumericSensorDataTemplate(BaseDiscoverySchemaDataTemplate): ): return ENTITY_DESC_KEY_TOTAL_INCREASING # We do this because even though these are power scales, they don't meet - # the unit requirements for the energy power class. + # the unit requirements for the power device class. if scale_type == ElectricScale.KILOVOLT_AMPERE_REACTIVE: return ENTITY_DESC_KEY_MEASUREMENT diff --git a/tests/components/zwave_js/test_sensor.py b/tests/components/zwave_js/test_sensor.py index b595b6462b3..fe17b071175 100644 --- a/tests/components/zwave_js/test_sensor.py +++ b/tests/components/zwave_js/test_sensor.py @@ -1,17 +1,24 @@ """Test the Z-Wave JS sensor platform.""" +import copy + +from zwave_js_server.const.command_class.meter import MeterType from zwave_js_server.event import Event +from zwave_js_server.model.node import Node from homeassistant.components.sensor import ( + ATTR_STATE_CLASS, STATE_CLASS_MEASUREMENT, STATE_CLASS_TOTAL_INCREASING, ) from homeassistant.components.zwave_js.const import ( ATTR_METER_TYPE, + ATTR_METER_TYPE_NAME, ATTR_VALUE, DOMAIN, SERVICE_RESET_METER, ) from homeassistant.const import ( + ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, @@ -268,3 +275,85 @@ async def test_reset_meter( assert args["args"] == [{"type": 1, "targetValue": 2}] client.async_send_command_no_wait.reset_mock() + + +async def test_meter_attributes( + hass, + client, + aeon_smart_switch_6, + integration, +): + """Test meter entity attributes.""" + state = hass.states.get(METER_ENERGY_SENSOR) + assert state + assert state.attributes[ATTR_METER_TYPE] == MeterType.ELECTRIC.value + assert state.attributes[ATTR_METER_TYPE_NAME] == MeterType.ELECTRIC.name + assert state.attributes[ATTR_DEVICE_CLASS] == DEVICE_CLASS_ENERGY + assert state.attributes[ATTR_STATE_CLASS] == STATE_CLASS_TOTAL_INCREASING + + +async def test_special_meters(hass, aeon_smart_switch_6_state, client, integration): + """Test meters that have special handling.""" + node_data = copy.deepcopy( + aeon_smart_switch_6_state + ) # Copy to allow modification in tests. + # Add an ElectricScale.KILOVOLT_AMPERE_HOUR value to the state so we can test that + # it is handled differently (no device class) + node_data["values"].append( + { + "endpoint": 10, + "commandClass": 50, + "commandClassName": "Meter", + "property": "value", + "propertyKey": 65537, + "propertyName": "value", + "propertyKeyName": "Electric_kVah_Consumed", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": True, + "writeable": False, + "label": "Electric Consumed [kVah]", + "unit": "kVah", + "ccSpecific": {"meterType": 1, "rateType": 1, "scale": 1}, + }, + "value": 659.813, + }, + ) + # Add an ElectricScale.KILOVOLT_AMPERE_REACTIVE value to the state so we can test that + # it is handled differently (no device class) + node_data["values"].append( + { + "endpoint": 11, + "commandClass": 50, + "commandClassName": "Meter", + "property": "value", + "propertyKey": 65537, + "propertyName": "value", + "propertyKeyName": "Electric_kVa_reactive_Consumed", + "ccVersion": 3, + "metadata": { + "type": "number", + "readable": True, + "writeable": False, + "label": "Electric Consumed [kVa reactive]", + "unit": "kVa reactive", + "ccSpecific": {"meterType": 1, "rateType": 1, "scale": 7}, + }, + "value": 659.813, + }, + ) + node = Node(client, node_data) + event = {"node": node} + client.driver.controller.emit("node added", event) + await hass.async_block_till_done() + + state = hass.states.get("sensor.smart_switch_6_electric_consumed_kvah_10") + assert state + assert ATTR_DEVICE_CLASS not in state.attributes + assert state.attributes[ATTR_STATE_CLASS] == STATE_CLASS_TOTAL_INCREASING + + state = hass.states.get("sensor.smart_switch_6_electric_consumed_kva_reactive_11") + assert state + assert ATTR_DEVICE_CLASS not in state.attributes + assert state.attributes[ATTR_STATE_CLASS] == STATE_CLASS_MEASUREMENT