-
-
Notifications
You must be signed in to change notification settings - Fork 28.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Freebox Home alarm panel #102607
Merged
Merged
Add Freebox Home alarm panel #102607
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
e1527d7
add alarm control panel
nachonam 2b59f0e
optimize update node
nachonam aa13549
Modify comment
nachonam 5d2316d
move const to alarm
nachonam 157bc71
add alarm panel tests
nachonam 8a59acd
tests modified
nachonam d7e4af4
add file into coveragerc
nachonam 3b2f5f6
Review: DATA_HOME_GET_VALUES -> DATA_HOME_PIR_GET_VALUES
Quentame a1c4cc4
Review: commands rename
Quentame 956bc68
Review: precise what "alarm2" is for features
Quentame 27b5d69
Review: remove custom attributes & properties that exists in parent
Quentame d4da1a4
Review: Avoid duplicates of async_write_ha_state()
Quentame a451be7
make functions private
Quentame 55a9168
Review: initial state never works
Quentame 9a6ab03
Review: remove extra attrs
Quentame 9aee0dd
Review: fix tests
Quentame dc2d5bd
Fix tests
Quentame 798ef91
Remove line in .coveragerc
Quentame File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
138 changes: 138 additions & 0 deletions
138
homeassistant/components/freebox/alarm_control_panel.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
"""Support for Freebox alarms.""" | ||
import logging | ||
from typing import Any | ||
|
||
from homeassistant.components.alarm_control_panel import ( | ||
AlarmControlPanelEntity, | ||
AlarmControlPanelEntityFeature, | ||
) | ||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.const import ( | ||
STATE_ALARM_ARMED_AWAY, | ||
STATE_ALARM_ARMED_NIGHT, | ||
STATE_ALARM_ARMING, | ||
STATE_ALARM_DISARMED, | ||
STATE_ALARM_TRIGGERED, | ||
) | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.entity_platform import AddEntitiesCallback | ||
|
||
from .const import DOMAIN, FreeboxHomeCategory | ||
from .home_base import FreeboxHomeEntity | ||
from .router import FreeboxRouter | ||
|
||
FREEBOX_TO_STATUS = { | ||
"alarm1_arming": STATE_ALARM_ARMING, | ||
"alarm2_arming": STATE_ALARM_ARMING, | ||
"alarm1_armed": STATE_ALARM_ARMED_AWAY, | ||
"alarm2_armed": STATE_ALARM_ARMED_NIGHT, | ||
"alarm1_alert_timer": STATE_ALARM_TRIGGERED, | ||
"alarm2_alert_timer": STATE_ALARM_TRIGGERED, | ||
"alert": STATE_ALARM_TRIGGERED, | ||
} | ||
|
||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
async def async_setup_entry( | ||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback | ||
) -> None: | ||
"""Set up alarm panel.""" | ||
router: FreeboxRouter = hass.data[DOMAIN][entry.unique_id] | ||
|
||
alarm_entities: list[AlarmControlPanelEntity] = [] | ||
|
||
for node in router.home_devices.values(): | ||
if node["category"] == FreeboxHomeCategory.ALARM: | ||
alarm_entities.append(FreeboxAlarm(hass, router, node)) | ||
|
||
if alarm_entities: | ||
async_add_entities(alarm_entities, True) | ||
|
||
|
||
class FreeboxAlarm(FreeboxHomeEntity, AlarmControlPanelEntity): | ||
"""Representation of a Freebox alarm.""" | ||
|
||
def __init__( | ||
self, hass: HomeAssistant, router: FreeboxRouter, node: dict[str, Any] | ||
) -> None: | ||
"""Initialize an alarm.""" | ||
super().__init__(hass, router, node) | ||
|
||
# Commands | ||
self._command_trigger = self.get_command_id( | ||
node["type"]["endpoints"], "slot", "trigger" | ||
) | ||
self._command_arm_away = self.get_command_id( | ||
node["type"]["endpoints"], "slot", "alarm1" | ||
) | ||
self._command_arm_home = self.get_command_id( | ||
node["type"]["endpoints"], "slot", "alarm2" | ||
) | ||
self._command_disarm = self.get_command_id( | ||
node["type"]["endpoints"], "slot", "off" | ||
) | ||
self._command_state = self.get_command_id( | ||
node["type"]["endpoints"], "signal", "state" | ||
) | ||
self._set_features(self._router.home_devices[self._id]) | ||
|
||
async def async_alarm_disarm(self, code: str | None = None) -> None: | ||
"""Send disarm command.""" | ||
if await self.set_home_endpoint_value(self._command_disarm): | ||
self._set_state(STATE_ALARM_DISARMED) | ||
|
||
async def async_alarm_arm_away(self, code: str | None = None) -> None: | ||
"""Send arm away command.""" | ||
if await self.set_home_endpoint_value(self._command_arm_away): | ||
self._set_state(STATE_ALARM_ARMING) | ||
|
||
async def async_alarm_arm_home(self, code: str | None = None) -> None: | ||
"""Send arm home command.""" | ||
if await self.set_home_endpoint_value(self._command_arm_home): | ||
self._set_state(STATE_ALARM_ARMING) | ||
|
||
async def async_alarm_trigger(self, code: str | None = None) -> None: | ||
"""Send alarm trigger command.""" | ||
if await self.set_home_endpoint_value(self._command_trigger): | ||
self._set_state(STATE_ALARM_TRIGGERED) | ||
|
||
async def async_update_signal(self): | ||
"""Update signal.""" | ||
state = await self.get_home_endpoint_value(self._command_state) | ||
if state: | ||
self._set_state(state) | ||
|
||
def _set_features(self, node: dict[str, Any]) -> None: | ||
"""Add alarm features.""" | ||
# Search if the arm home feature is present => has an "alarm2" endpoint | ||
can_arm_home = False | ||
for nodeid, local_node in self._router.home_devices.items(): | ||
if nodeid == local_node["id"]: | ||
alarm2 = next( | ||
filter( | ||
lambda x: (x["name"] == "alarm2" and x["ep_type"] == "signal"), | ||
local_node["show_endpoints"], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use a generator expression instead of filter + lambda. |
||
), | ||
None, | ||
) | ||
if alarm2: | ||
can_arm_home = alarm2["value"] | ||
break | ||
|
||
if can_arm_home: | ||
self._attr_supported_features = ( | ||
AlarmControlPanelEntityFeature.ARM_AWAY | ||
| AlarmControlPanelEntityFeature.ARM_HOME | ||
) | ||
|
||
else: | ||
self._attr_supported_features = AlarmControlPanelEntityFeature.ARM_AWAY | ||
|
||
def _set_state(self, state: str) -> None: | ||
"""Update state.""" | ||
self._attr_state = FREEBOX_TO_STATUS.get(state) | ||
if not self._attr_state: | ||
self._attr_state = STATE_ALARM_DISARMED | ||
self.async_write_ha_state() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_set_state
doesn't accept the Home Assistant entity state, it accepts the device state.