From fa71fd39926a4a7394a85b02d051448e87d0d7e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 07:46:11 +0100 Subject: [PATCH 1/4] Bump actions/stale from 10.1.1 to 10.2.0 (#163223) --- .github/workflows/stale.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index e24c2762aaaab6..95ae4c4a314547 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -27,7 +27,7 @@ jobs: # - No PRs marked as no-stale # - No issues (-1) - name: 60 days stale PRs policy - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 + uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 60 @@ -67,7 +67,7 @@ jobs: # - No issues marked as no-stale or help-wanted # - No PRs (-1) - name: 90 days stale issues - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 + uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 with: repo-token: ${{ steps.token.outputs.token }} days-before-stale: 90 @@ -97,7 +97,7 @@ jobs: # - No Issues marked as no-stale or help-wanted # - No PRs (-1) - name: Needs more information stale issues policy - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 + uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 with: repo-token: ${{ steps.token.outputs.token }} only-labels: "needs-more-information" From d777c1c5426975bd26c433cc988263d19c50e6f8 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Tue, 17 Feb 2026 23:19:38 -0800 Subject: [PATCH 2/4] Bump pyrainbird to 6.0.5 (#163333) --- homeassistant/components/rainbird/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/rainbird/manifest.json b/homeassistant/components/rainbird/manifest.json index 93b4f21d7cbeba..c4eb2beb4a2ab2 100644 --- a/homeassistant/components/rainbird/manifest.json +++ b/homeassistant/components/rainbird/manifest.json @@ -7,5 +7,5 @@ "integration_type": "hub", "iot_class": "local_polling", "loggers": ["pyrainbird"], - "requirements": ["pyrainbird==6.0.1"] + "requirements": ["pyrainbird==6.0.5"] } diff --git a/requirements_all.txt b/requirements_all.txt index 4876cb3055f978..ce085bf85d0153 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2390,7 +2390,7 @@ pyqwikswitch==0.93 pyrail==0.4.1 # homeassistant.components.rainbird -pyrainbird==6.0.1 +pyrainbird==6.0.5 # homeassistant.components.playstation_network pyrate-limiter==3.9.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1001db6ec9e31e..5b4e7aeeabb094 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2037,7 +2037,7 @@ pyqwikswitch==0.93 pyrail==0.4.1 # homeassistant.components.rainbird -pyrainbird==6.0.1 +pyrainbird==6.0.5 # homeassistant.components.playstation_network pyrate-limiter==3.9.0 From 392fc7ff9192aa9b744b5674e7cd05242b0adf9a Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Wed, 18 Feb 2026 08:35:28 +0100 Subject: [PATCH 3/4] Use shorthand attributes in osramlightify (#163296) --- .../components/osramlightify/light.py | 63 +++++-------------- 1 file changed, 15 insertions(+), 48 deletions(-) diff --git a/homeassistant/components/osramlightify/light.py b/homeassistant/components/osramlightify/light.py index 42af6c74e45125..a55ed36518c1a5 100644 --- a/homeassistant/components/osramlightify/light.py +++ b/homeassistant/components/osramlightify/light.py @@ -187,13 +187,8 @@ def __init__(self, luminary, update_func, changed): self._luminary = luminary self._changed = changed - self._unique_id = None - self._effect_list = [] - self._is_on = False - self._available = True - self._brightness = None + self._attr_is_on = False self._rgb_color = None - self._device_attributes = None self.update_static_attributes() self.update_dynamic_attributes() @@ -253,36 +248,6 @@ def hs_color(self): """Return last hs color value set.""" return color_util.color_RGB_to_hs(*self._rgb_color) - @property - def brightness(self): - """Return brightness of the luminary (0..255).""" - return self._brightness - - @property - def is_on(self): - """Return True if the device is on.""" - return self._is_on - - @property - def effect_list(self): - """List of supported effects.""" - return self._effect_list - - @property - def unique_id(self): - """Return a unique ID.""" - return self._unique_id - - @property - def extra_state_attributes(self): - """Return device specific state attributes.""" - return self._device_attributes - - @property - def available(self) -> bool: - """Return True if entity is available.""" - return self._available - def play_effect(self, effect, transition): """Play selected effect.""" if effect == EFFECT_RANDOM: @@ -313,19 +278,19 @@ def turn_on(self, **kwargs: Any) -> None: self._attr_color_temp_kelvin = color_temp_kelvin self._luminary.set_temperature(color_temp_kelvin, transition) - self._is_on = True + self._attr_is_on = True if ATTR_BRIGHTNESS in kwargs: - self._brightness = kwargs[ATTR_BRIGHTNESS] - self._luminary.set_luminance(int(self._brightness / 2.55), transition) + self._attr_brightness = kwargs[ATTR_BRIGHTNESS] + self._luminary.set_luminance(int(self._attr_brightness / 2.55), transition) else: self._luminary.set_onoff(True) def turn_off(self, **kwargs: Any) -> None: """Turn the device off.""" - self._is_on = False + self._attr_is_on = False if ATTR_TRANSITION in kwargs: transition = int(kwargs[ATTR_TRANSITION] * 10) - self._brightness = DEFAULT_BRIGHTNESS + self._attr_brightness = DEFAULT_BRIGHTNESS self._luminary.set_luminance(0, transition) else: self._luminary.set_onoff(False) @@ -337,10 +302,10 @@ def update_luminary(self, luminary): def update_static_attributes(self) -> None: """Update static attributes of the luminary.""" - self._unique_id = self._get_unique_id() + self._attr_unique_id = self._get_unique_id() self._attr_supported_color_modes = self._get_supported_color_modes() self._attr_supported_features = self._get_supported_features() - self._effect_list = self._get_effect_list() + self._attr_effect_list = self._get_effect_list() if ColorMode.COLOR_TEMP in self._attr_supported_color_modes: self._attr_max_color_temp_kelvin = ( self._luminary.max_temp() or DEFAULT_KELVIN @@ -354,10 +319,12 @@ def update_static_attributes(self) -> None: def update_dynamic_attributes(self): """Update dynamic attributes of the luminary.""" - self._is_on = self._luminary.on() - self._available = self._luminary.reachable() and not self._luminary.deleted() + self._attr_is_on = self._luminary.on() + self._attr_available = ( + self._luminary.reachable() and not self._luminary.deleted() + ) if brightness_supported(self._attr_supported_color_modes): - self._brightness = int(self._luminary.lum() * 2.55) + self._attr_brightness = int(self._luminary.lum() * 2.55) if ColorMode.COLOR_TEMP in self._attr_supported_color_modes: self._attr_color_temp_kelvin = self._luminary.temp() or DEFAULT_KELVIN @@ -399,7 +366,7 @@ def update_static_attributes(self): if self._luminary.devicetype().name == "SENSOR": attrs["sensor_values"] = self._luminary.raw_values() - self._device_attributes = attrs + self._attr_extra_state_attributes = attrs class OsramLightifyGroup(Luminary): @@ -444,4 +411,4 @@ def play_effect(self, effect, transition): def update_static_attributes(self): """Update static attributes of the luminary.""" super().update_static_attributes() - self._device_attributes = {"lights": self._luminary.light_names()} + self._attr_extra_state_attributes = {"lights": self._luminary.light_names()} From fdd753e70c195f8712621dddd317da9d49aa759e Mon Sep 17 00:00:00 2001 From: Nic Eggert Date: Wed, 18 Feb 2026 01:44:01 -0600 Subject: [PATCH 4/4] Add support for voltage sensors to eGauge integration (#163206) --- homeassistant/components/egauge/sensor.py | 18 +++++- tests/components/egauge/conftest.py | 3 + .../egauge/snapshots/test_sensor.ambr | 59 ++++++++++++++++++- 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/egauge/sensor.py b/homeassistant/components/egauge/sensor.py index f5cd776ca35493..2abd1c6886d654 100644 --- a/homeassistant/components/egauge/sensor.py +++ b/homeassistant/components/egauge/sensor.py @@ -5,7 +5,7 @@ from collections.abc import Callable from dataclasses import dataclass -from egauge_async.json.models import RegisterType +from egauge_async.json.models import RegisterInfo, RegisterType from homeassistant.components.sensor import ( SensorDeviceClass, @@ -13,7 +13,7 @@ SensorEntityDescription, SensorStateClass, ) -from homeassistant.const import UnitOfEnergy, UnitOfPower +from homeassistant.const import UnitOfElectricPotential, UnitOfEnergy, UnitOfPower from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback @@ -27,6 +27,7 @@ class EgaugeSensorEntityDescription(SensorEntityDescription): native_value_fn: Callable[[EgaugeData, str], float] available_fn: Callable[[EgaugeData, str], bool] + supported_fn: Callable[[RegisterInfo], bool] SENSORS: tuple[EgaugeSensorEntityDescription, ...] = ( @@ -37,6 +38,7 @@ class EgaugeSensorEntityDescription(SensorEntityDescription): native_unit_of_measurement=UnitOfPower.WATT, native_value_fn=lambda data, register: data.measurements[register], available_fn=lambda data, register: register in data.measurements, + supported_fn=lambda register_info: register_info.type == RegisterType.POWER, ), EgaugeSensorEntityDescription( key="energy", @@ -46,6 +48,16 @@ class EgaugeSensorEntityDescription(SensorEntityDescription): suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, native_value_fn=lambda data, register: data.counters[register], available_fn=lambda data, register: register in data.counters, + supported_fn=lambda register_info: register_info.type == RegisterType.POWER, + ), + EgaugeSensorEntityDescription( + key="voltage", + device_class=SensorDeviceClass.VOLTAGE, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfElectricPotential.VOLT, + native_value_fn=lambda data, register: data.measurements[register], + available_fn=lambda data, register: register in data.measurements, + supported_fn=lambda register_info: register_info.type == RegisterType.VOLTAGE, ), ) @@ -61,7 +73,7 @@ async def async_setup_entry( EgaugeSensor(coordinator, register_name, sensor) for sensor in SENSORS for register_name, register_info in coordinator.data.register_info.items() - if register_info.type == RegisterType.POWER + if sensor.supported_fn(register_info) ) diff --git a/tests/components/egauge/conftest.py b/tests/components/egauge/conftest.py index 5a65ca2c68118d..c78ee0a723321f 100644 --- a/tests/components/egauge/conftest.py +++ b/tests/components/egauge/conftest.py @@ -65,6 +65,7 @@ def mock_egauge_client() -> Generator[MagicMock]: "Temp": RegisterInfo( name="Temp", type=RegisterType.TEMPERATURE, idx=2, did=None ), + "L1": RegisterInfo(name="L1", type=RegisterType.VOLTAGE, idx=3, did=None), } # Dynamic measurements @@ -72,11 +73,13 @@ def mock_egauge_client() -> Generator[MagicMock]: "Grid": 1500.0, "Solar": -2500.0, "Temp": 45.0, + "L1": 123.4, } client.get_current_counters.return_value = { "Grid": 450000000.0, # 125 kWh in Ws "Solar": 315000000.0, # 87.5 kWh in Ws "Temp": 0.0, + "L1": 12345678.0, } yield client diff --git a/tests/components/egauge/snapshots/test_sensor.ambr b/tests/components/egauge/snapshots/test_sensor.ambr index fd4086e58d1de2..9a939b1419d755 100644 --- a/tests/components/egauge/snapshots/test_sensor.ambr +++ b/tests/components/egauge/snapshots/test_sensor.ambr @@ -1,5 +1,5 @@ # serializer version: 1 -# name: test_sensors.8 +# name: test_sensors.10 DeviceRegistryEntrySnapshot({ 'area_id': None, 'config_entries': , @@ -147,6 +147,63 @@ 'state': '1500.0', }) # --- +# name: test_sensors[sensor.egauge_home_l1_voltage-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.egauge_home_l1_voltage', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Voltage', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Voltage', + 'platform': 'egauge', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': 'ABC123456_L1_voltage', + 'unit_of_measurement': , + }) +# --- +# name: test_sensors[sensor.egauge_home_l1_voltage-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'voltage', + 'friendly_name': 'egauge-home L1 Voltage', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.egauge_home_l1_voltage', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '123.4', + }) +# --- # name: test_sensors[sensor.egauge_home_solar_energy-entry] EntityRegistryEntrySnapshot({ 'aliases': set({