Skip to content

Commit

Permalink
Merge pull request #314 from ParadoxAlarmInterface/dev
Browse files Browse the repository at this point in the history
Timezone & trouble notification fixes
  • Loading branch information
yozik04 authored Sep 5, 2022
2 parents 033e751 + b22f4c4 commit bce50ae
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 33 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,6 @@ ENV/
/config/*.yaml
/eeprom.bin
/ram.bin

# OS X
.DS_Store
9 changes: 5 additions & 4 deletions config/pai.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import logging
# OUTPUT_PULSE_DURATION = 1 # Duration of a PGM pulse in seconds
# SYNC_TIME = False # Update panel time periodically when time drifts more than SYNC_TIME_MIN_DRIFT
# SYNC_TIME_MIN_DRIFT = 60 # Minimum time drift in seconds to initiate time sync
# SYNC_TIME_TIMEZONE='' # Timezone used for panel time synchronisation. PAI host timezone is used by default
# PASSWORD = '0000' # PC Password. Set to None if Panel has no Password.
# # In Babyware: Right click on your panel -> Properties -> PC Communication (Babyware) ->
# # PC Communication (Babyware) Tab.
Expand Down Expand Up @@ -149,7 +150,7 @@ import logging
## Event filtering by tags:
# HOMEASSISTANT_NOTIFICATIONS_EVENT_FILTERS = [ # list of tags to include or exclude see hardware event.py for tag list
# 'live,alarm,-restore', # or
# 'live,trouble,-clock', # or
# 'trouble,-clock', # or
# 'live,tamper'
# ]
## - OR - event filtering using regexp. Cannot be used together with _EVENT_FILTERS
Expand All @@ -167,7 +168,7 @@ import logging
## Event filtering by tags:
# PUSHBULLET_EVENT_FILTERS = [ # list of tags to include or exclude see hardware event.py for tag list
# 'live,alarm,-restore', # or
# 'live,trouble,-clock', # or
# 'trouble,-clock', # or
# 'live,tamper'
# ]
## - OR - event filtering using regexp. Cannot be used together with _EVENT_FILTERS
Expand All @@ -189,7 +190,7 @@ import logging
## Event filtering by tags:
# PUSHOVER_EVENT_FILTERS = [ # list of tags to include or exclude see hardware event.py for tag list
# 'live,alarm,-restore', # or
# 'live,trouble,-clock', # or
# 'trouble,-clock', # or
# 'live,tamper'
# ]
## - OR - event filtering using regexp. Cannot be used together with _EVENT_FILTERS
Expand All @@ -208,7 +209,7 @@ import logging
## Event filtering by tags:
# SIGNAL_EVENT_FILTERS = [ # list of tags to include or exclude see hardware event.py for tag list
# 'live,alarm,-restore', # or
# 'live,trouble,-clock', # or
# 'trouble,-clock', # or
# 'live,tamper'
# ]
## - OR - event filtering using regexp. Cannot be used together with _EVENT_FILTERS
Expand Down
2 changes: 1 addition & 1 deletion paradox/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = "3.0.1"
VERSION = "3.1.0"
13 changes: 7 additions & 6 deletions paradox/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ class Config(object):
"SYNC_TIME_MIN_DRIFT": (
120,
int,
(60, 0xFFFFFFFF)
(120, 0xFFFFFFFF)
), # Minimum time drift in seconds to initiate time sync
"SYNC_TIME_TIMEZONE": "", # By default pai uses the same timezone as pai host
"PASSWORD": (
None,
[int, str, bytes, type(None)],
Expand Down Expand Up @@ -182,7 +183,7 @@ class Config(object):
"HOMEASSISTANT_NOTIFICATIONS_ALLOW_EVENTS": [], # Same as before but as a white list. Default is use EVENT_FILTERS
"HOMEASSISTANT_NOTIFICATIONS_EVENT_FILTERS": [ # list of tags, property changes to include or exclude. See event.py for tag list
"live,alarm,-restore",
"live,trouble,-clock",
"trouble,-clock",
"live,tamper",
],
# Pushbullet
Expand All @@ -194,7 +195,7 @@ class Config(object):
"PUSHBULLET_ALLOW_EVENTS": [], # Same as before but as a white list. Default is use EVENT_FILTERS
"PUSHBULLET_EVENT_FILTERS": [ # list of tags, property changes to include or exclude. See event.py for tag list
"live,alarm,-restore",
"live,trouble,-clock",
"trouble,-clock",
"live,tamper",
],
"PUSHBULLET_MIN_EVENT_LEVEL": (
Expand All @@ -212,7 +213,7 @@ class Config(object):
"PUSHOVER_ALLOW_EVENTS": [], # Same as before but as a white list. Default is use EVENT_FILTERS
"PUSHOVER_EVENT_FILTERS": [ # list of tags, property changes to include or exclude. See event.py for tag list
"live,alarm,-restore",
"live,trouble,-clock",
"trouble,-clock",
"live,tamper",
],
"PUSHOVER_MIN_EVENT_LEVEL": (
Expand All @@ -227,7 +228,7 @@ class Config(object):
"SIGNAL_ALLOW_EVENTS": [], # Same as before but as a white list. Default is use EVENT_FILTERS
"SIGNAL_EVENT_FILTERS": [ # list of tags, property changes to include or exclude. See event.py for tag list
"live,alarm,-restore",
"live,trouble,-clock",
"trouble,-clock",
"live,tamper",
],
"SIGNAL_MIN_EVENT_LEVEL": (
Expand Down Expand Up @@ -456,4 +457,4 @@ def get_limits_for_type(elem_type: str, default: list = None):
if isinstance(limits, str):
if "auto" in limits:
return default
return string_to_id_list(limits)
return string_to_id_list(limits)
4 changes: 4 additions & 0 deletions paradox/console_scripts/pai_dump_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from paradox.config import config as cfg
from paradox.lib import help
from paradox.lib.encodings import register_encodings
from paradox.paradox import Paradox

if sys.version_info < (3, 6,):
Expand Down Expand Up @@ -74,6 +75,9 @@ def main():
else:
cfg.load()

# Registering additional encodings
register_encodings()

loop = asyncio.get_event_loop()
loop.run_until_complete(dump_memory(args.file, args.type))

Expand Down
4 changes: 2 additions & 2 deletions paradox/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def get_format(level):
return "%(asctime)s - %(levelname)-8s - %(name)s - %(message)s"


def config_logger(logger):
def configure_logger(logger):
logger_level = cfg.LOGGING_LEVEL_CONSOLE

if cfg.LOGGING_FILE:
Expand Down Expand Up @@ -119,7 +119,7 @@ def main(args):
else:
cfg.load()

config_logger(logger)
configure_logger(logger)

logger.info(f"Starting Paradox Alarm Interface {VERSION}")
logger.info(f"Config loaded from {cfg.CONFIG_FILE_LOCATION}")
Expand Down
51 changes: 31 additions & 20 deletions paradox/paradox.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import asyncio
import logging
import time
import pytz
from binascii import hexlify
from datetime import datetime
from typing import Callable, Iterable, Optional, Sequence
Expand Down Expand Up @@ -244,18 +245,28 @@ async def dump_memory(self, file, memory_type):
)

async def sync_time(self):
logger.debug("Synchronizing panel time")
now = datetime.now().astimezone()
if cfg.SYNC_TIME_TIMEZONE:
try:
tzinfo = pytz.timezone(cfg.SYNC_TIME_TIMEZONE)
now = now.astimezone(tzinfo)
except pytz.exceptions.UnknownTimeZoneError:
logger.debug(f"Panel Timezone Unknown ('{cfg.SYNC_TIME_TIMEZONE}'). Skipping sync")
return

if not self._is_time_sync_required(now.replace(tzinfo=None)):
return

now = time.localtime()
args = dict(
century=int(now.tm_year / 100),
year=int(now.tm_year % 100),
month=now.tm_mon,
day=now.tm_mday,
hour=now.tm_hour,
minute=now.tm_min,
century=int(now.year / 100),
year=int(now.year % 100),
month=now.month,
day=now.day,
hour=now.hour,
minute=now.minute,
)

logger.debug("Synchronizing panel time")
reply = await self.send_wait(
self.panel.get_message("SetTimeDate"), args, reply_expected=0x03, timeout=10
)
Expand Down Expand Up @@ -713,8 +724,7 @@ def _on_status_update(self, status):
self._update_partition_states()

if cfg.SYNC_TIME:
if self._check_if_time_sync_required():
self.work_loop.create_task(self.sync_time())
self.work_loop.create_task(self.sync_time())

def _process_trouble_statuses(self, trouble_statuses):
global_trouble = False
Expand All @@ -733,20 +743,21 @@ def _process_trouble_statuses(self, trouble_statuses):
"system", "troubles", {"trouble": global_trouble}
)

def _check_if_time_sync_required(self):
def _is_time_sync_required(self, now) -> bool:
assert now.tzinfo is None
try:
drift = (
datetime.now() - self.storage.get_container("system")["date"]["time"]
).total_seconds()
drift = (now - self.storage.get_container("system")["date"]["time"]).total_seconds()

if abs(drift) > cfg.SYNC_TIME_MIN_DRIFT:
logger.info(f"Time drifted more than allowed: {drift} seconds")
return True
else:
logger.debug(f"Time drifted within allowed range: {drift} seconds")
if abs(drift) > cfg.SYNC_TIME_MIN_DRIFT:
logger.info(f"Time drifted more than allowed: {drift} seconds")
return True
else:
logger.debug(f"Time drifted within allowed range: {drift} seconds")

except KeyError:
return False
pass

return False

def _update_partition_states(self):
"""
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ require-python-3
construct~=2.9.43
argparse>=1.4.0
python-slugify>=4.0.1
pytz>=2021.3
#
# Optional
#
Expand Down

0 comments on commit bce50ae

Please sign in to comment.