126 files
This commit is contained in:
@@ -430,6 +430,11 @@ class AlarmoCoordinator(DataUpdateCoordinator):
|
||||
)
|
||||
return
|
||||
|
||||
if action == const.EVENT_ACTION_DISARM:
|
||||
_LOGGER.info("Received request for disarming")
|
||||
await alarm_entity.async_alarm_disarm(None, skip_code=True)
|
||||
return
|
||||
|
||||
arm_mode = (
|
||||
alarm_entity._revert_state
|
||||
if alarm_entity._revert_state in const.ARM_MODES
|
||||
@@ -452,9 +457,6 @@ class AlarmoCoordinator(DataUpdateCoordinator):
|
||||
elif action == const.EVENT_ACTION_RETRY_ARM:
|
||||
_LOGGER.info("Received request for retry arming")
|
||||
await alarm_entity.async_handle_arm_request(arm_mode, skip_code=True)
|
||||
elif action == const.EVENT_ACTION_DISARM:
|
||||
_LOGGER.info("Received request for disarming")
|
||||
await alarm_entity.async_alarm_disarm(None, skip_code=True)
|
||||
else:
|
||||
_LOGGER.info(
|
||||
"Received request for arming with mode %s",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -323,8 +323,11 @@ class AlarmoBaseEntity(AlarmControlPanelEntity, RestoreEntity):
|
||||
async def _validate_code(self, code, to_state): # noqa PLR0911
|
||||
"""Validate code and user permissions for a requested state change.
|
||||
|
||||
Returns a (success, error_event) tuple. When success is True,
|
||||
error_event is None.
|
||||
Returns a (success, info) tuple.
|
||||
When validation is successful, success is True, otherwise False.
|
||||
When success is True, info is the user data
|
||||
(or None if no user/code was needed).
|
||||
When success is False, info is the error event.
|
||||
"""
|
||||
# check bypass rules
|
||||
if (
|
||||
@@ -404,7 +407,7 @@ class AlarmoBaseEntity(AlarmControlPanelEntity, RestoreEntity):
|
||||
|
||||
# success
|
||||
self._changed_by = user[ATTR_NAME]
|
||||
return True, None
|
||||
return True, user
|
||||
|
||||
async def async_service_disarm_handler(self, code, context_id=None):
|
||||
"""Handle external disarm request from alarmo.disarm service."""
|
||||
|
||||
@@ -44,6 +44,8 @@ def validate_area(trigger, area_id, hass):
|
||||
return False
|
||||
elif trigger[const.ATTR_AREA]:
|
||||
return trigger[const.ATTR_AREA] == area_id
|
||||
elif area_id and hass.data[const.DOMAIN].get("master"):
|
||||
return False
|
||||
elif len(hass.data[const.DOMAIN]["areas"]) == 1:
|
||||
return True
|
||||
else:
|
||||
|
||||
@@ -15,7 +15,7 @@ from homeassistant.components.alarm_control_panel import (
|
||||
AlarmControlPanelEntityFeature,
|
||||
)
|
||||
|
||||
VERSION = "1.10.18"
|
||||
VERSION = "1.10.19"
|
||||
NAME = "Alarmo"
|
||||
MANUFACTURER = "@nielsfaber"
|
||||
|
||||
|
||||
+448
-448
File diff suppressed because one or more lines are too long
@@ -17,5 +17,5 @@
|
||||
"iot_class": "local_push",
|
||||
"issue_tracker": "https://github.com/nielsfaber/alarmo/issues",
|
||||
"requirements": [],
|
||||
"version": "1.10.18"
|
||||
"version": "1.10.19"
|
||||
}
|
||||
@@ -130,7 +130,11 @@ class SensorHandler:
|
||||
|
||||
def __init__(self, hass: HomeAssistant):
|
||||
"""Initialize the sensor handler."""
|
||||
self._config = None
|
||||
# The sensor config is only loaded once HA has finished starting (see
|
||||
# _setup_sensor_listeners below). Until then this must be an empty dict
|
||||
# rather than None: restoring a persisted alarm state can call into
|
||||
# active_sensors_for_alarm_state() before that point.
|
||||
self._config = {}
|
||||
self.hass = hass
|
||||
self._state_listener = None
|
||||
self._subscriptions = []
|
||||
@@ -144,9 +148,10 @@ class SensorHandler:
|
||||
@callback
|
||||
def async_update_sensor_config():
|
||||
"""Sensor config updated, reload the configuration."""
|
||||
self._config = self.hass.data[const.DOMAIN][
|
||||
"coordinator"
|
||||
].store.async_get_sensors()
|
||||
self._config = (
|
||||
self.hass.data[const.DOMAIN]["coordinator"].store.async_get_sensors()
|
||||
or {}
|
||||
)
|
||||
self._groups = self.hass.data[const.DOMAIN][
|
||||
"coordinator"
|
||||
].store.async_get_sensor_groups()
|
||||
@@ -377,15 +382,28 @@ class SensorHandler:
|
||||
new_state = parse_sensor_state(event.data["new_state"])
|
||||
sensor_config = self._config[entity]
|
||||
if old_state == STATE_UNKNOWN:
|
||||
# sensor is unknown at startup,
|
||||
# state which comes after is considered as initial state
|
||||
_LOGGER.debug(
|
||||
"Initial state for %s is %s",
|
||||
entity,
|
||||
new_state,
|
||||
)
|
||||
self.update_ready_to_arm_status(sensor_config["area"])
|
||||
return
|
||||
if new_state not in (STATE_OPEN, STATE_UNAVAILABLE) or (
|
||||
sensor_config[ATTR_ALLOW_OPEN] and new_state == STATE_OPEN
|
||||
):
|
||||
# transition to a safe state, or to open while the sensor is
|
||||
# allowed to be open — treat as initial state
|
||||
_LOGGER.debug(
|
||||
"Initial state for %s is %s",
|
||||
entity,
|
||||
new_state,
|
||||
)
|
||||
self.update_ready_to_arm_status(sensor_config["area"])
|
||||
return
|
||||
else:
|
||||
# transition to a violation state — do not treat as initial,
|
||||
# proceed through normal trigger evaluation
|
||||
_LOGGER.debug(
|
||||
"Sensor %s recovered from unknown to %s while alarm is %s, "
|
||||
"evaluating as live state change",
|
||||
entity,
|
||||
new_state,
|
||||
self.hass.data[const.DOMAIN]["areas"][sensor_config["area"]].state,
|
||||
)
|
||||
if old_state == new_state:
|
||||
# not a state change - ignore
|
||||
return
|
||||
@@ -740,6 +758,13 @@ class SensorHandler:
|
||||
# Skip unknown sensors - they'll be handled when they become known
|
||||
continue
|
||||
|
||||
if sensor_config[ATTR_ALLOW_OPEN] and sensor_state == STATE_OPEN:
|
||||
_LOGGER.debug(
|
||||
"Sensor %s is open with allow_open, skipping startup eval",
|
||||
entity_id,
|
||||
)
|
||||
continue
|
||||
|
||||
# Check if sensor state is allowed in current alarm state
|
||||
res = sensor_state_allowed(sensor_state, sensor_config, alarm_entity.state)
|
||||
|
||||
|
||||
@@ -381,10 +381,10 @@ class AlarmoStorage:
|
||||
for area in data["areas"]:
|
||||
modes = {
|
||||
mode: ModeEntry(
|
||||
enabled=config["enabled"],
|
||||
exit_time=config["exit_time"],
|
||||
entry_time=config["entry_time"],
|
||||
trigger_time=config["trigger_time"],
|
||||
enabled=config.get("enabled", False),
|
||||
exit_time=config.get("exit_time", None),
|
||||
entry_time=config.get("entry_time", None),
|
||||
trigger_time=config.get("trigger_time", None),
|
||||
)
|
||||
for (mode, config) in area["modes"].items()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user