diff --git a/homeassistant/components/group/sensor.py b/homeassistant/components/group/sensor.py index 8e1a0a24207..7334831211d 100644 --- a/homeassistant/components/group/sensor.py +++ b/homeassistant/components/group/sensor.py @@ -396,7 +396,7 @@ class SensorGroup(GroupEntity, SensorEntity): self._state_incorrect.add(entity_id) _LOGGER.warning( "Unable to use state. Only entities with correct unit of measurement" - " is supported when having a device class," + " is supported," " entity %s, value %s with device class %s" " and unit of measurement %s excluded from calculation in %s", entity_id, @@ -548,19 +548,28 @@ class SensorGroup(GroupEntity, SensorEntity): # Ensure only valid unit of measurements for the specific device class can be used if ( - # Test if uom's in device class is convertible - (device_class := self.device_class) in UNIT_CONVERTERS - and all( - uom in UNIT_CONVERTERS[device_class].VALID_UNITS - for uom in unit_of_measurements + ( + # Test if uom's in device class is convertible + (device_class := self.device_class) in UNIT_CONVERTERS + and all( + uom in UNIT_CONVERTERS[device_class].VALID_UNITS + for uom in unit_of_measurements + ) ) - ) or ( - # Test if uom's in device class is not convertible - device_class - and device_class not in UNIT_CONVERTERS - and device_class in DEVICE_CLASS_UNITS - and all( - uom in DEVICE_CLASS_UNITS[device_class] for uom in unit_of_measurements + or ( + # Test if uom's in device class is not convertible + device_class + and device_class not in UNIT_CONVERTERS + and device_class in DEVICE_CLASS_UNITS + and all( + uom in DEVICE_CLASS_UNITS[device_class] + for uom in unit_of_measurements + ) + ) + or ( + # Test no device class and all uom's are same + device_class is None + and all(x == unit_of_measurements[0] for x in unit_of_measurements) ) ): async_delete_issue( @@ -608,6 +617,7 @@ class SensorGroup(GroupEntity, SensorEntity): """Return valid units. If device class is set and compatible unit of measurements. + If device class is not set, use one unit of measurement. """ if ( device_class := self.device_class @@ -621,4 +631,6 @@ class SensorGroup(GroupEntity, SensorEntity): ): valid_uoms: set = DEVICE_CLASS_UNITS[device_class] return valid_uoms + if device_class is None and self.native_unit_of_measurement: + return {self.native_unit_of_measurement} return set() diff --git a/homeassistant/components/group/strings.json b/homeassistant/components/group/strings.json index ba571bb1008..f9039fb896e 100644 --- a/homeassistant/components/group/strings.json +++ b/homeassistant/components/group/strings.json @@ -257,7 +257,7 @@ }, "uoms_not_matching_no_device_class": { "title": "Unit of measurements is not correct", - "description": "Unit of measurements `{uoms}` of input sensors `{source_entities}` are not compatible using no device class of sensor group `{entity_id}`.\n\nPlease correct the unit of measurements on the source entities or set a proper device class on the sensor group and reload the group sensor to fix this issue." + "description": "Unit of measurements `{uoms}` of input sensors `{source_entities}` are not compatible when not using a device class on sensor group `{entity_id}`.\n\nPlease correct the unit of measurements on the source entities or set a proper device class on the sensor group and reload the group sensor to fix this issue." }, "device_classes_not_matching": { "title": "Device classes is not correct", diff --git a/tests/components/group/test_sensor.py b/tests/components/group/test_sensor.py index ec6905a500f..fb3c1b6d215 100644 --- a/tests/components/group/test_sensor.py +++ b/tests/components/group/test_sensor.py @@ -424,6 +424,101 @@ async def test_sensor_calculated_properties(hass: HomeAssistant) -> None: assert state.state == str(float(sum(VALUES))) +async def test_sensor_with_uoms_but_no_device_class( + hass: HomeAssistant, + issue_registry: ir.IssueRegistry, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test the sensor works with same uom when there is no device class.""" + config = { + SENSOR_DOMAIN: { + "platform": GROUP_DOMAIN, + "name": "test_sum", + "type": "sum", + "entities": ["sensor.test_1", "sensor.test_2", "sensor.test_3"], + "unique_id": "very_unique_id_last_sensor", + } + } + + entity_ids = config["sensor"]["entities"] + + hass.states.async_set( + entity_ids[0], + VALUES[0], + { + "device_class": SensorDeviceClass.POWER, + "state_class": SensorStateClass.MEASUREMENT, + "unit_of_measurement": "W", + }, + ) + hass.states.async_set( + entity_ids[1], + VALUES[1], + { + "device_class": SensorDeviceClass.POWER, + "state_class": SensorStateClass.MEASUREMENT, + "unit_of_measurement": "W", + }, + ) + hass.states.async_set( + entity_ids[2], + VALUES[2], + { + "unit_of_measurement": "W", + }, + ) + + await hass.async_block_till_done() + + assert await async_setup_component(hass, "sensor", config) + await hass.async_block_till_done() + + state = hass.states.get("sensor.test_sum") + assert state.attributes.get("device_class") is None + assert state.attributes.get("state_class") is None + assert state.attributes.get("unit_of_measurement") == "W" + assert state.state == str(float(sum(VALUES))) + + assert not issue_registry.issues + + hass.states.async_set( + entity_ids[0], + VALUES[0], + { + "device_class": SensorDeviceClass.POWER, + "state_class": SensorStateClass.MEASUREMENT, + "unit_of_measurement": "kW", + }, + ) + await hass.async_block_till_done() + state = hass.states.get("sensor.test_sum") + assert state.attributes.get("device_class") is None + assert state.attributes.get("state_class") is None + assert state.attributes.get("unit_of_measurement") == "W" + assert state.state == STATE_UNKNOWN + + assert ( + "Unable to use state. Only entities with correct unit of measurement is supported" + in caplog.text + ) + + hass.states.async_set( + entity_ids[0], + VALUES[0], + { + "device_class": SensorDeviceClass.POWER, + "state_class": SensorStateClass.MEASUREMENT, + "unit_of_measurement": "W", + }, + ) + await hass.async_block_till_done() + state = hass.states.get("sensor.test_sum") + assert state.attributes.get("device_class") is None + assert state.attributes.get("state_class") is None + assert state.attributes.get("unit_of_measurement") == "W" + assert state.state == str(float(sum(VALUES))) + + async def test_sensor_calculated_properties_not_same( hass: HomeAssistant, issue_registry: ir.IssueRegistry ) -> None: @@ -616,7 +711,7 @@ async def test_sensor_calculated_properties_not_convertible_device_class( assert ( "Unable to use state. Only entities with correct unit of measurement is" - " supported when having a device class" + " supported" ) not in caplog.text hass.states.async_set( @@ -637,7 +732,7 @@ async def test_sensor_calculated_properties_not_convertible_device_class( assert ( "Unable to use state. Only entities with correct unit of measurement is" - " supported when having a device class, entity sensor.test_3, value 15.3 with" + " supported, entity sensor.test_3, value 15.3 with" " device class humidity and unit of measurement None excluded from calculation" " in sensor.test_sum" ) in caplog.text