Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion custom_components/sonoff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@


async def async_setup(hass: HomeAssistant, config: dict) -> bool:
if (MAJOR_VERSION, MINOR_VERSION) < (2023, 2):
if (MAJOR_VERSION, MINOR_VERSION) < (2025, 6):
raise Exception("unsupported hass version")

# init storage for registries
Expand Down
32 changes: 11 additions & 21 deletions custom_components/sonoff/alarm_control_panel.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from homeassistant.components.alarm_control_panel import (
AlarmControlPanelEntity,
AlarmControlPanelEntityFeature,
AlarmControlPanelState,
)
from homeassistant.const import MAJOR_VERSION, MINOR_VERSION

from .core.const import DOMAIN
from .core.entity import XEntity
Expand All @@ -21,28 +21,18 @@ async def async_setup_entry(hass, config_entry, add_entities):
)


if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 11):
from homeassistant.components.alarm_control_panel import AlarmControlPanelState
STATES = {
0: AlarmControlPanelState.DISARMED,
1: AlarmControlPanelState.ARMED_HOME,
2: AlarmControlPanelState.ARMED_AWAY,
3: AlarmControlPanelState.ARMED_NIGHT,
}

STATES = {
0: AlarmControlPanelState.DISARMED,
1: AlarmControlPanelState.ARMED_HOME,
2: AlarmControlPanelState.ARMED_AWAY,
3: AlarmControlPanelState.ARMED_NIGHT,
}

class XAlarmControlBase(XEntity, AlarmControlPanelEntity):
def set_state(self, params: dict):
if self.param in params:
self._attr_alarm_state = STATES.get(params[self.param])

else:
STATES = {0: "disarmed", 1: "armed_home", 2: "armed_away", 3: "armed_night"}

class XAlarmControlBase(XEntity, AlarmControlPanelEntity):
def set_state(self, params: dict):
if self.param in params:
self._attr_state = STATES.get(params[self.param])
class XAlarmControlBase(XEntity, AlarmControlPanelEntity):
def set_state(self, params: dict):
if self.param in params:
self._attr_alarm_state = STATES.get(params[self.param])


class XPanelAlarm(XAlarmControlBase):
Expand Down
72 changes: 26 additions & 46 deletions custom_components/sonoff/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
HVACMode,
HVACAction,
)
from homeassistant.const import MAJOR_VERSION, MINOR_VERSION, UnitOfTemperature
from homeassistant.const import UnitOfTemperature

from .core.const import DOMAIN
from .core.entity import XEntity
Expand Down Expand Up @@ -36,16 +36,12 @@ class XClimateTH(XEntity, ClimateEntity):
_attr_target_temperature_step = 1
_heat_mode_flag = False

# https://developers.home-assistant.io/blog/2024/01/24/climate-climateentityfeatures-expanded
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 2):
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
_enable_turn_on_off_backwards_compatibility = False
else:
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
_enable_turn_on_off_backwards_compatibility = False

heat: bool = None

Expand Down Expand Up @@ -157,16 +153,12 @@ class XClimateNS(XEntity, ClimateEntity):
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_target_temperature_step = 0.5

# https://developers.home-assistant.io/blog/2024/01/24/climate-climateentityfeatures-expanded
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 2):
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
_enable_turn_on_off_backwards_compatibility = False
else:
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
_enable_turn_on_off_backwards_compatibility = False

def __init__(self, ewelink, device: dict):
# copy mutable list so each instance has its own hvac_modes
Expand Down Expand Up @@ -258,19 +250,13 @@ class XThermostat(XEntity, ClimateEntity):
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_target_temperature_step = 0.5

# https://developers.home-assistant.io/blog/2024/01/24/climate-climateentityfeatures-expanded
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 2):
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
_enable_turn_on_off_backwards_compatibility = False
else:
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
)
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
_enable_turn_on_off_backwards_compatibility = False

def set_state(self, params: dict):
cache = self.device["params"]
Expand Down Expand Up @@ -342,18 +328,12 @@ class XThermostatTRVZB(XEntity, ClimateEntity):
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_target_temperature_step = 0.5

# https://developers.home-assistant.io/blog/2024/01/24/climate-climateentityfeatures-expanded
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 2):
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
_enable_turn_on_off_backwards_compatibility = False
else:
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
)
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
_enable_turn_on_off_backwards_compatibility = False

def set_state(self, params: dict):
cache = self.device["params"]
Expand Down
18 changes: 6 additions & 12 deletions custom_components/sonoff/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
FanEntity,
FanEntityFeature,
)
from homeassistant.const import MAJOR_VERSION, MINOR_VERSION

from .core.const import DOMAIN
from .core.entity import XEntity
Expand Down Expand Up @@ -31,15 +30,11 @@ class XFan(XEntity, FanEntity):
params = {"switches", "fan"}
_attr_speed_count = 3

# https://developers.home-assistant.io/blog/2024/07/19/fan-fanentityfeatures-turn-on_off/
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 8):
_attr_supported_features = (
FanEntityFeature.SET_SPEED
| FanEntityFeature.TURN_OFF
| FanEntityFeature.TURN_ON
)
else:
_attr_supported_features = FanEntityFeature.SET_SPEED
_attr_supported_features = (
FanEntityFeature.SET_SPEED
| FanEntityFeature.TURN_OFF
| FanEntityFeature.TURN_ON
)

def __init__(self, ewelink: XRegistry, device: XDevice) -> None:
super().__init__(ewelink, device)
Expand Down Expand Up @@ -176,8 +171,7 @@ async def async_set_percentage(self, percentage: int):

# noinspection PyAbstractClass
class XToggleFan(XEntity, FanEntity):
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 8):
_attr_supported_features = FanEntityFeature.TURN_OFF | FanEntityFeature.TURN_ON
_attr_supported_features = FanEntityFeature.TURN_OFF | FanEntityFeature.TURN_ON

@property
def is_on(self):
Expand Down
2 changes: 1 addition & 1 deletion hacs.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Sonoff LAN",
"homeassistant": "2023.2.0",
"homeassistant": "2025.6.0",
"render_readme": true
}
38 changes: 14 additions & 24 deletions tests/test_backward.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@


def test_backward():
# https://github.com/home-assistant/core/blob/2023.2.0/homeassistant/const.py
assert (MAJOR_VERSION, MINOR_VERSION) >= (2023, 2)
assert REQUIRED_PYTHON_VER >= (3, 10, 0)
# https://github.com/home-assistant/core/blob/2025.6.0/homeassistant/const.py
assert (MAJOR_VERSION, MINOR_VERSION) >= (2025, 6)
assert REQUIRED_PYTHON_VER >= (3, 13, 2)

assert async_setup_entry
assert async_get_config_entry_diagnostics
Expand Down Expand Up @@ -53,29 +53,19 @@ def test_2024_1_cached_properties():
def test_2024_2_climate():
_, entities = init({"extra": {"uiid": 15}})
climate: ClimateEntity = next(e for e in entities if isinstance(e, XClimateTH))
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 2):
assert climate.supported_features == (
ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
else:
assert (
climate.supported_features == ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
)
assert climate.supported_features == (
ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)


def test_2024_8_fan():
_, entities = init({"extra": {"uiid": 34}})
fan: FanEntity = next(e for e in entities if isinstance(e, XFan))
if (MAJOR_VERSION, MINOR_VERSION) >= (2024, 8):
assert fan.supported_features == (
FanEntityFeature.SET_SPEED
| FanEntityFeature.PRESET_MODE
| FanEntityFeature.TURN_OFF
| FanEntityFeature.TURN_ON
)
else:
assert fan.supported_features == (
FanEntityFeature.SET_SPEED | FanEntityFeature.PRESET_MODE
)
assert fan.supported_features == (
FanEntityFeature.SET_SPEED
| FanEntityFeature.PRESET_MODE
| FanEntityFeature.TURN_OFF
| FanEntityFeature.TURN_ON
)
Loading