Skip to content

Commit

Permalink
Fix initial state bug (take 2) (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
nickw444 committed Dec 31, 2018
1 parent 320af9e commit e8249cc
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 9 deletions.
28 changes: 22 additions & 6 deletions nessclient/alarm.py
Expand Up @@ -2,7 +2,7 @@
from enum import Enum
from typing import Optional, Callable, List

from .event import BaseEvent, ZoneUpdate, SystemStatusEvent
from .event import BaseEvent, ZoneUpdate, ArmingUpdate, SystemStatusEvent


class ArmingState(Enum):
Expand Down Expand Up @@ -35,21 +35,37 @@ class Zone:
triggered: Optional[bool]

def __init__(self) -> None:
# TODO: Determine the best way to query the alarm initial state. For
# now, we assume the alarm is initially disarmed on connection.
self.arming_state: ArmingState = ArmingState.DISARMED
self.arming_state: ArmingState = ArmingState.UNKNOWN
self.zones: List[Alarm.Zone] = [Alarm.Zone(triggered=None) for _ in range(16)]

self._on_state_change: Optional[Callable[['ArmingState'], None]] = None
self._on_zone_change: Optional[Callable[[int, bool], None]] = None

def handle_event(self, event: BaseEvent) -> None:
if (isinstance(event, ZoneUpdate)
and event.request_id == ZoneUpdate.RequestID.ZONE_INPUT_UNSEALED):
if isinstance(event, ArmingUpdate):
self._handle_arming_update(event)
elif (isinstance(event, ZoneUpdate)
and event.request_id == ZoneUpdate.RequestID.ZONE_INPUT_UNSEALED):
self._handle_zone_input_update(event)
elif isinstance(event, SystemStatusEvent):
self._handle_system_status_event(event)

def _handle_arming_update(self, update: ArmingUpdate) -> None:
if update.status == [ArmingUpdate.ArmingStatus.MANUAL_EXCLUDE_MODE]:
return self._update_arming_state(ArmingState.EXIT_DELAY)
if ArmingUpdate.ArmingStatus.MANUAL_EXCLUDE_MODE in update.status and \
ArmingUpdate.ArmingStatus.DAY_ZONE_SELECT:
# TODO(NW): This might not be the correct condition for an "armed"
# system, in fact, the same states are shown throughout armed, and
# entry delay. We should determine a better way to query the
# current alarm state.
return self._update_arming_state(ArmingState.ARMED)
elif self.arming_state == ArmingState.UNKNOWN:
# TODO(NW): Initially update to disarmed when the state is unknown.
# In the future, it would be ideal to infer other states by making
# calls to other status commands (i.e. zones in delay).
return self._update_arming_state(ArmingState.DISARMED)

def _handle_zone_input_update(self, update: ZoneUpdate) -> None:
for i, zone in enumerate(self.zones):
zone_id = i + 1
Expand Down
5 changes: 4 additions & 1 deletion nessclient/cli/server/alarm_server.py
Expand Up @@ -146,7 +146,10 @@ def get_arming_status(state: Alarm.ArmingState) -> List[ArmingUpdate.ArmingStatu
ArmingUpdate.ArmingStatus.MANUAL_EXCLUDE_MODE,
ArmingUpdate.ArmingStatus.DAY_ZONE_SELECT
]
return []
elif state == Alarm.ArmingState.EXIT_DELAY:
return [ArmingUpdate.ArmingStatus.MANUAL_EXCLUDE_MODE]
else:
return []


def toggled_state(state: Zone.State) -> Zone.State:
Expand Down
6 changes: 4 additions & 2 deletions nessclient/client.py
Expand Up @@ -59,10 +59,12 @@ async def aux(self, output_id: int, state: bool = True) -> None:
return await self.send_command(command)

async def update(self) -> None:
"""Force update of zones"""
"""Force update of alarm status and zones"""
await asyncio.gather(
# List unsealed Zones
self.send_command('S00'),
# Arming status update
self.send_command('S14'),
)

async def _connect(self) -> None:
Expand Down Expand Up @@ -130,7 +132,7 @@ async def _update_loop(self) -> None:
await asyncio.sleep(self._update_interval)
while not self._closed:
_LOGGER.debug("Forcing a keepalive state update")
await self.update()
await self.send_command('S00') # List unsealed Zones
await asyncio.sleep(self._update_interval)

async def keepalive(self) -> None:
Expand Down

0 comments on commit e8249cc

Please sign in to comment.