forked from platypush/platypush
[#340] Better state management for alarms.
- Added `AlarmEnabledEvent` and `AlarmDisabledEvent`. - Added `snooze_interval` configurable both at plugin level and alarm level.
This commit is contained in:
parent
34e2a59285
commit
f27e7bb7e2
4 changed files with 54 additions and 9 deletions
|
@ -4,43 +4,54 @@ from platypush.message.event import Event
|
|||
|
||||
|
||||
class AlarmEvent(Event):
|
||||
def __init__(self, name: Optional[str] = None, *args, **kwargs):
|
||||
"""
|
||||
Base class for alarm events.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, name: Optional[str] = None, **kwargs):
|
||||
super().__init__(*args, name=name, **kwargs)
|
||||
|
||||
|
||||
class AlarmEnabledEvent(AlarmEvent):
|
||||
"""
|
||||
Triggered when an alarm is enabled.
|
||||
"""
|
||||
|
||||
|
||||
class AlarmDisabledEvent(AlarmEvent):
|
||||
"""
|
||||
Triggered when an alarm is disabled.
|
||||
"""
|
||||
|
||||
|
||||
class AlarmStartedEvent(AlarmEvent):
|
||||
"""
|
||||
Triggered when an alarm starts.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class AlarmEndedEvent(AlarmEvent):
|
||||
"""
|
||||
Triggered when an alarm stops.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class AlarmDismissedEvent(AlarmEndedEvent):
|
||||
"""
|
||||
Triggered when an alarm is dismissed.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class AlarmSnoozedEvent(AlarmEvent):
|
||||
"""
|
||||
Triggered when an alarm is snoozed.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class AlarmTimeoutEvent(AlarmEndedEvent):
|
||||
"""
|
||||
Triggered when an alarm times out.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# vim:sw=4:ts=4:et:
|
||||
|
|
|
@ -79,6 +79,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
alarms: Optional[Union[list, Dict[str, Any]]] = None,
|
||||
media_plugin: Optional[str] = None,
|
||||
poll_interval: Optional[float] = 5.0,
|
||||
snooze_interval: float = 300.0,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
|
@ -90,8 +91,11 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
``media.gstreamer`` etc. If not specified, the first available
|
||||
configured local media plugin will be used. This only applies to
|
||||
alarms that are configured to play an audio resource.
|
||||
:param poll_interval: Poll interval in seconds (default: 5).
|
||||
:param snooze_interval: Default snooze interval in seconds (default: 300).
|
||||
"""
|
||||
super().__init__(poll_interval=poll_interval, **kwargs)
|
||||
self.snooze_interval = snooze_interval
|
||||
self._db_lock = RLock()
|
||||
alarms = alarms or []
|
||||
if isinstance(alarms, dict):
|
||||
|
@ -160,7 +164,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
self.alarms[name] = Alarm.from_db(
|
||||
alarm,
|
||||
stop_event=self._should_stop,
|
||||
media_plugin=self.media_plugin,
|
||||
media_plugin=alarm.media_plugin or self.media_plugin,
|
||||
)
|
||||
|
||||
def _sync_alarms(self):
|
||||
|
@ -240,6 +244,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
audio_file: Optional[str] = None,
|
||||
audio_volume: Optional[Union[int, float]] = None,
|
||||
enabled: bool = True,
|
||||
snooze_interval: Optional[float] = None,
|
||||
) -> Alarm:
|
||||
alarm = Alarm(
|
||||
when=when,
|
||||
|
@ -249,6 +254,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
media=media or audio_file,
|
||||
media_plugin=self.media_plugin,
|
||||
audio_volume=audio_volume,
|
||||
snooze_interval=snooze_interval or self.snooze_interval,
|
||||
stop_event=self._should_stop,
|
||||
on_change=self._on_alarm_update,
|
||||
)
|
||||
|
@ -281,6 +287,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
self.logger.info('No alarm is running')
|
||||
return
|
||||
|
||||
interval = interval or alarm.snooze_interval or self.snooze_interval
|
||||
alarm.snooze(interval=interval)
|
||||
|
||||
@action
|
||||
|
@ -293,6 +300,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
audio_file: Optional[str] = None,
|
||||
audio_volume: Optional[Union[int, float]] = None,
|
||||
enabled: bool = True,
|
||||
snooze_interval: Optional[float] = None,
|
||||
) -> dict:
|
||||
"""
|
||||
Add a new alarm.
|
||||
|
@ -307,6 +315,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
:param media: Path of the audio file to be played.
|
||||
:param audio_volume: Volume of the audio.
|
||||
:param enabled: Whether the new alarm should be enabled (default: True).
|
||||
:param snooze_interval: Snooze seconds before playing the alarm again.
|
||||
:return: The newly created alarm.
|
||||
"""
|
||||
if audio_file:
|
||||
|
@ -322,6 +331,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
name=name,
|
||||
enabled=enabled,
|
||||
audio_volume=audio_volume,
|
||||
snooze_interval=snooze_interval,
|
||||
).to_dict()
|
||||
|
||||
@action
|
||||
|
@ -343,6 +353,19 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
"""
|
||||
self._disable(name)
|
||||
|
||||
@action
|
||||
def set_enabled(self, name: str, enabled: bool):
|
||||
"""
|
||||
Enable/disable an alarm.
|
||||
|
||||
:param name: Alarm name.
|
||||
:param enabled: Whether the alarm should be enabled.
|
||||
"""
|
||||
if enabled:
|
||||
self._enable(name)
|
||||
else:
|
||||
self._disable(name)
|
||||
|
||||
@action
|
||||
def dismiss(self):
|
||||
"""
|
||||
|
@ -351,7 +374,7 @@ class AlarmPlugin(RunnablePlugin, EntityManager):
|
|||
self._dismiss()
|
||||
|
||||
@action
|
||||
def snooze(self, interval: Optional[float] = 300.0):
|
||||
def snooze(self, interval: Optional[float] = None):
|
||||
"""
|
||||
Snooze the alarm that is currently running for the specified number of seconds.
|
||||
The alarm will stop and resume again later.
|
||||
|
|
|
@ -12,9 +12,11 @@ from platypush.context import get_bus, get_plugin
|
|||
from platypush.entities.alarm import Alarm as AlarmDb
|
||||
from platypush.message.request import Request
|
||||
from platypush.message.event.alarm import (
|
||||
AlarmStartedEvent,
|
||||
AlarmDisabledEvent,
|
||||
AlarmDismissedEvent,
|
||||
AlarmEnabledEvent,
|
||||
AlarmSnoozedEvent,
|
||||
AlarmStartedEvent,
|
||||
)
|
||||
from platypush.plugins.media import MediaPlugin, PlayerState
|
||||
from platypush.procedure import Procedure
|
||||
|
@ -145,7 +147,13 @@ class Alarm:
|
|||
self.set_enabled(True)
|
||||
|
||||
def set_enabled(self, enabled: bool):
|
||||
if enabled == self._enabled:
|
||||
return
|
||||
|
||||
self._enabled = enabled
|
||||
evt_type = AlarmEnabledEvent if enabled else AlarmDisabledEvent
|
||||
get_bus().post(evt_type(name=self.name))
|
||||
self._on_change()
|
||||
|
||||
def dismiss(self):
|
||||
self.state = AlarmState.DISMISSED
|
||||
|
@ -232,6 +240,7 @@ class Alarm:
|
|||
sleep_time = self._runtime_snooze_interval
|
||||
else:
|
||||
self.state = AlarmState.WAITING
|
||||
self._on_change()
|
||||
|
||||
break
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
manifest:
|
||||
events:
|
||||
- platypush.message.event.alarm.AlarmDisabledEvent
|
||||
- platypush.message.event.alarm.AlarmDismissedEvent
|
||||
- platypush.message.event.alarm.AlarmEnabledEvent
|
||||
- platypush.message.event.alarm.AlarmSnoozedEvent
|
||||
- platypush.message.event.alarm.AlarmStartedEvent
|
||||
- platypush.message.event.alarm.AlarmTimeoutEvent
|
||||
|
|
Loading…
Reference in a new issue