This commit is contained in:
Paulus Schoutsen 2024-02-26 11:17:13 -05:00 committed by GitHub
commit aabaa30fa7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 151 additions and 38 deletions

View File

@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/caldav", "documentation": "https://www.home-assistant.io/integrations/caldav",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"loggers": ["caldav", "vobject"], "loggers": ["caldav", "vobject"],
"requirements": ["caldav==1.3.8"] "requirements": ["caldav==1.3.9"]
} }

View File

@ -5,5 +5,5 @@
"documentation": "https://www.home-assistant.io/integrations/enigma2", "documentation": "https://www.home-assistant.io/integrations/enigma2",
"iot_class": "local_polling", "iot_class": "local_polling",
"loggers": ["openwebif"], "loggers": ["openwebif"],
"requirements": ["openwebifpy==4.2.1"] "requirements": ["openwebifpy==4.2.4"]
} }

View File

@ -107,7 +107,7 @@ async def async_setup_platform(
device = OpenWebIfDevice( device = OpenWebIfDevice(
host=session, host=session,
turn_off_to_deep=config.get(CONF_DEEP_STANDBY), turn_off_to_deep=config.get(CONF_DEEP_STANDBY, False),
source_bouquet=config.get(CONF_SOURCE_BOUQUET), source_bouquet=config.get(CONF_SOURCE_BOUQUET),
) )

View File

@ -396,7 +396,7 @@ class SensorGroup(GroupEntity, SensorEntity):
self._state_incorrect.add(entity_id) self._state_incorrect.add(entity_id)
_LOGGER.warning( _LOGGER.warning(
"Unable to use state. Only entities with correct unit of measurement" "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" " entity %s, value %s with device class %s"
" and unit of measurement %s excluded from calculation in %s", " and unit of measurement %s excluded from calculation in %s",
entity_id, entity_id,
@ -548,19 +548,28 @@ class SensorGroup(GroupEntity, SensorEntity):
# Ensure only valid unit of measurements for the specific device class can be used # Ensure only valid unit of measurements for the specific device class can be used
if ( if (
(
# Test if uom's in device class is convertible # Test if uom's in device class is convertible
(device_class := self.device_class) in UNIT_CONVERTERS (device_class := self.device_class) in UNIT_CONVERTERS
and all( and all(
uom in UNIT_CONVERTERS[device_class].VALID_UNITS uom in UNIT_CONVERTERS[device_class].VALID_UNITS
for uom in unit_of_measurements for uom in unit_of_measurements
) )
) or ( )
or (
# Test if uom's in device class is not convertible # Test if uom's in device class is not convertible
device_class device_class
and device_class not in UNIT_CONVERTERS and device_class not in UNIT_CONVERTERS
and device_class in DEVICE_CLASS_UNITS and device_class in DEVICE_CLASS_UNITS
and all( and all(
uom in DEVICE_CLASS_UNITS[device_class] for uom in unit_of_measurements 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( async_delete_issue(
@ -608,6 +617,7 @@ class SensorGroup(GroupEntity, SensorEntity):
"""Return valid units. """Return valid units.
If device class is set and compatible unit of measurements. If device class is set and compatible unit of measurements.
If device class is not set, use one unit of measurement.
""" """
if ( if (
device_class := self.device_class device_class := self.device_class
@ -621,4 +631,6 @@ class SensorGroup(GroupEntity, SensorEntity):
): ):
valid_uoms: set = DEVICE_CLASS_UNITS[device_class] valid_uoms: set = DEVICE_CLASS_UNITS[device_class]
return valid_uoms return valid_uoms
if device_class is None and self.native_unit_of_measurement:
return {self.native_unit_of_measurement}
return set() return set()

View File

@ -257,7 +257,7 @@
}, },
"uoms_not_matching_no_device_class": { "uoms_not_matching_no_device_class": {
"title": "Unit of measurements is not correct", "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": { "device_classes_not_matching": {
"title": "Device classes is not correct", "title": "Device classes is not correct",

View File

@ -43,6 +43,7 @@ class LutronSwitch(LutronDevice, SwitchEntity):
"""Representation of a Lutron Switch.""" """Representation of a Lutron Switch."""
_lutron_device: Output _lutron_device: Output
_attr_name = None
def turn_on(self, **kwargs: Any) -> None: def turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on.""" """Turn the switch on."""

View File

@ -7,5 +7,5 @@
"documentation": "https://www.home-assistant.io/integrations/opower", "documentation": "https://www.home-assistant.io/integrations/opower",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"loggers": ["opower"], "loggers": ["opower"],
"requirements": ["opower==0.2.0"] "requirements": ["opower==0.3.1"]
} }

View File

@ -5,5 +5,9 @@
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/profiler", "documentation": "https://www.home-assistant.io/integrations/profiler",
"quality_scale": "internal", "quality_scale": "internal",
"requirements": ["pyprof2calltree==1.4.5", "guppy3==3.1.4", "objgraph==3.5.0"] "requirements": [
"pyprof2calltree==1.4.5",
"guppy3==3.1.4.post1",
"objgraph==3.5.0"
]
} }

View File

@ -24,7 +24,7 @@
"documentation": "https://www.home-assistant.io/integrations/roomba", "documentation": "https://www.home-assistant.io/integrations/roomba",
"iot_class": "local_push", "iot_class": "local_push",
"loggers": ["paho_mqtt", "roombapy"], "loggers": ["paho_mqtt", "roombapy"],
"requirements": ["roombapy==1.6.12"], "requirements": ["roombapy==1.6.13"],
"zeroconf": [ "zeroconf": [
{ {
"type": "_amzn-alexa._tcp.local.", "type": "_amzn-alexa._tcp.local.",

View File

@ -15,7 +15,7 @@ from homeassistant.data_entry_flow import FlowResult
from .const import DOMAIN from .const import DOMAIN
from .data import WyomingService from .data import WyomingService
_LOGGER = logging.getLogger() _LOGGER = logging.getLogger(__name__)
STEP_USER_DATA_SCHEMA = vol.Schema( STEP_USER_DATA_SCHEMA = vol.Schema(
{ {
@ -64,6 +64,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self, discovery_info: hassio.HassioServiceInfo self, discovery_info: hassio.HassioServiceInfo
) -> FlowResult: ) -> FlowResult:
"""Handle Supervisor add-on discovery.""" """Handle Supervisor add-on discovery."""
_LOGGER.debug("Supervisor discovery info: %s", discovery_info)
await self.async_set_unique_id(discovery_info.uuid) await self.async_set_unique_id(discovery_info.uuid)
self._abort_if_unique_id_configured() self._abort_if_unique_id_configured()
@ -105,7 +106,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self, discovery_info: zeroconf.ZeroconfServiceInfo self, discovery_info: zeroconf.ZeroconfServiceInfo
) -> FlowResult: ) -> FlowResult:
"""Handle zeroconf discovery.""" """Handle zeroconf discovery."""
_LOGGER.debug("Discovery info: %s", discovery_info) _LOGGER.debug("Zeroconf discovery info: %s", discovery_info)
if discovery_info.port is None: if discovery_info.port is None:
return self.async_abort(reason="no_port") return self.async_abort(reason="no_port")

View File

@ -16,7 +16,7 @@ from .helpers.deprecation import (
APPLICATION_NAME: Final = "HomeAssistant" APPLICATION_NAME: Final = "HomeAssistant"
MAJOR_VERSION: Final = 2024 MAJOR_VERSION: Final = 2024
MINOR_VERSION: Final = 2 MINOR_VERSION: Final = 2
PATCH_VERSION: Final = "3" PATCH_VERSION: Final = "4"
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__: Final = f"{__short_version__}.{PATCH_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 11, 0) REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 11, 0)

View File

@ -36,7 +36,7 @@ janus==1.0.0
Jinja2==3.1.3 Jinja2==3.1.3
lru-dict==1.3.0 lru-dict==1.3.0
mutagen==1.47.0 mutagen==1.47.0
orjson==3.9.14 orjson==3.9.15
packaging>=23.1 packaging>=23.1
paho-mqtt==1.6.1 paho-mqtt==1.6.1
Pillow==10.2.0 Pillow==10.2.0

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "homeassistant" name = "homeassistant"
version = "2024.2.3" version = "2024.2.4"
license = {text = "Apache-2.0"} license = {text = "Apache-2.0"}
description = "Open-source home automation platform running on Python 3." description = "Open-source home automation platform running on Python 3."
readme = "README.rst" readme = "README.rst"
@ -46,7 +46,7 @@ dependencies = [
"cryptography==42.0.2", "cryptography==42.0.2",
# pyOpenSSL 23.2.0 is required to work with cryptography 41+ # pyOpenSSL 23.2.0 is required to work with cryptography 41+
"pyOpenSSL==24.0.0", "pyOpenSSL==24.0.0",
"orjson==3.9.14", "orjson==3.9.15",
"packaging>=23.1", "packaging>=23.1",
"pip>=21.3.1", "pip>=21.3.1",
"python-slugify==8.0.1", "python-slugify==8.0.1",

View File

@ -22,7 +22,7 @@ lru-dict==1.3.0
PyJWT==2.8.0 PyJWT==2.8.0
cryptography==42.0.2 cryptography==42.0.2
pyOpenSSL==24.0.0 pyOpenSSL==24.0.0
orjson==3.9.14 orjson==3.9.15
packaging>=23.1 packaging>=23.1
pip>=21.3.1 pip>=21.3.1
python-slugify==8.0.1 python-slugify==8.0.1

View File

@ -624,7 +624,7 @@ buienradar==1.0.5
cached_ipaddress==0.3.0 cached_ipaddress==0.3.0
# homeassistant.components.caldav # homeassistant.components.caldav
caldav==1.3.8 caldav==1.3.9
# homeassistant.components.circuit # homeassistant.components.circuit
circuit-webhook==1.0.1 circuit-webhook==1.0.1
@ -997,7 +997,7 @@ gspread==5.5.0
gstreamer-player==1.1.2 gstreamer-player==1.1.2
# homeassistant.components.profiler # homeassistant.components.profiler
guppy3==3.1.4 guppy3==3.1.4.post1
# homeassistant.components.iaqualink # homeassistant.components.iaqualink
h2==4.1.0 h2==4.1.0
@ -1459,7 +1459,7 @@ openhomedevice==2.2.0
opensensemap-api==0.2.0 opensensemap-api==0.2.0
# homeassistant.components.enigma2 # homeassistant.components.enigma2
openwebifpy==4.2.1 openwebifpy==4.2.4
# homeassistant.components.luci # homeassistant.components.luci
openwrt-luci-rpc==1.1.16 openwrt-luci-rpc==1.1.16
@ -1468,7 +1468,7 @@ openwrt-luci-rpc==1.1.16
openwrt-ubus-rpc==0.0.2 openwrt-ubus-rpc==0.0.2
# homeassistant.components.opower # homeassistant.components.opower
opower==0.2.0 opower==0.3.1
# homeassistant.components.oralb # homeassistant.components.oralb
oralb-ble==0.17.6 oralb-ble==0.17.6
@ -2450,7 +2450,7 @@ rokuecp==0.19.1
romy==0.0.7 romy==0.0.7
# homeassistant.components.roomba # homeassistant.components.roomba
roombapy==1.6.12 roombapy==1.6.13
# homeassistant.components.roon # homeassistant.components.roon
roonapi==0.1.6 roonapi==0.1.6

View File

@ -523,7 +523,7 @@ buienradar==1.0.5
cached_ipaddress==0.3.0 cached_ipaddress==0.3.0
# homeassistant.components.caldav # homeassistant.components.caldav
caldav==1.3.8 caldav==1.3.9
# homeassistant.components.coinbase # homeassistant.components.coinbase
coinbase==2.1.0 coinbase==2.1.0
@ -805,7 +805,7 @@ growattServer==1.3.0
gspread==5.5.0 gspread==5.5.0
# homeassistant.components.profiler # homeassistant.components.profiler
guppy3==3.1.4 guppy3==3.1.4.post1
# homeassistant.components.iaqualink # homeassistant.components.iaqualink
h2==4.1.0 h2==4.1.0
@ -1156,7 +1156,7 @@ openerz-api==0.3.0
openhomedevice==2.2.0 openhomedevice==2.2.0
# homeassistant.components.opower # homeassistant.components.opower
opower==0.2.0 opower==0.3.1
# homeassistant.components.oralb # homeassistant.components.oralb
oralb-ble==0.17.6 oralb-ble==0.17.6
@ -1872,7 +1872,7 @@ rokuecp==0.19.1
romy==0.0.7 romy==0.0.7
# homeassistant.components.roomba # homeassistant.components.roomba
roombapy==1.6.12 roombapy==1.6.13
# homeassistant.components.roon # homeassistant.components.roon
roonapi==0.1.6 roonapi==0.1.6

View File

@ -424,6 +424,101 @@ async def test_sensor_calculated_properties(hass: HomeAssistant) -> None:
assert state.state == str(float(sum(VALUES))) 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( async def test_sensor_calculated_properties_not_same(
hass: HomeAssistant, issue_registry: ir.IssueRegistry hass: HomeAssistant, issue_registry: ir.IssueRegistry
) -> None: ) -> None:
@ -616,7 +711,7 @@ async def test_sensor_calculated_properties_not_convertible_device_class(
assert ( assert (
"Unable to use state. Only entities with correct unit of measurement is" "Unable to use state. Only entities with correct unit of measurement is"
" supported when having a device class" " supported"
) not in caplog.text ) not in caplog.text
hass.states.async_set( hass.states.async_set(
@ -637,7 +732,7 @@ async def test_sensor_calculated_properties_not_convertible_device_class(
assert ( assert (
"Unable to use state. Only entities with correct unit of measurement is" "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" " device class humidity and unit of measurement None excluded from calculation"
" in sensor.test_sum" " in sensor.test_sum"
) in caplog.text ) in caplog.text