Permalink
Browse files

simple threshold based logic and tests

started writing unittests.
implemented cleanup command that removes empty sessions
added a simple threshold based alarm logic
  • Loading branch information...
poelzi committed Jul 28, 2010
1 parent c14d2f1 commit 89cbae5389aa531e24f5436a43b0b9e69a5d3c75
Showing with 608 additions and 38 deletions.
  1. +85 −0 .pida-metadata/python/config.py
  2. +87 −7 db/alarm.py
  3. +15 −0 db/management/commands/cleanup.py
  4. +159 −16 db/models.py
  5. +202 −13 db/tests.py
  6. +5 −2 settings.py
  7. +40 −0 tools/__init__.py
  8. +15 −0 tools/date.py
@@ -0,0 +1,85 @@
+# The default ``config.py``
+
+
+def set_prefs(prefs):
+ """This function is called before opening the project"""
+
+ # Specify which files and folders to ignore in the project.
+ # Changes to ignored resources are not added to the history and
+ # VCSs. Also they are not returned in `Project.get_files()`.
+ # Note that ``?`` and ``*`` match all characters but slashes.
+ # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
+ # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
+ # '.svn': matches 'pkg/.svn' and all of its children
+ # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
+ # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
+ prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
+ '.hg', '.svn', '_svn', '.git']
+
+ # Specifies which files should be considered python files. It is
+ # useful when you have scripts inside your project. Only files
+ # ending with ``.py`` are considered to be python files by
+ # default.
+ #prefs['python_files'] = ['*.py']
+
+ # Custom source folders: By default rope searches the project
+ # for finding source folders (folders that should be searched
+ # for finding modules). You can add paths to that list. Note
+ # that rope guesses project source folders correctly most of the
+ # time; use this if you have any problems.
+ # The folders should be relative to project root and use '/' for
+ # separating folders regardless of the platform rope is running on.
+ # 'src/my_source_folder' for instance.
+ #prefs.add('source_folders', 'src')
+
+ # You can extend python path for looking up modules
+ #prefs.add('python_path', '~/python/')
+
+ # Should rope save object information or not.
+ prefs['save_objectdb'] = True
+ prefs['compress_objectdb'] = False
+
+ # If `True`, rope analyzes each module when it is being saved.
+ prefs['automatic_soa'] = True
+ # The depth of calls to follow in static object analysis
+ prefs['soa_followed_calls'] = 0
+
+ # If `False` when running modules or unit tests "dynamic object
+ # analysis" is turned off. This makes them much faster.
+ prefs['perform_doa'] = True
+
+ # Rope can check the validity of its object DB when running.
+ prefs['validate_objectdb'] = True
+
+ # How many undos to hold?
+ prefs['max_history_items'] = 32
+
+ # Shows whether to save history across sessions.
+ prefs['save_history'] = True
+ prefs['compress_history'] = False
+
+ # Set the number spaces used for indenting. According to
+ # :PEP:`8`, it is best to use 4 spaces. Since most of rope's
+ # unit-tests use 4 spaces it is more reliable, too.
+ prefs['indent_size'] = 4
+
+ # Builtin and c-extension modules that are allowed to be imported
+ # and inspected by rope.
+ prefs['extension_modules'] = []
+
+ # Add all standard c-extensions to extension_modules list.
+ prefs['import_dynload_stdmods'] = True
+
+ # If `True` modules with syntax errors are considered to be empty.
+ # The default value is `False`; When `False` syntax errors raise
+ # `rope.base.exceptions.ModuleSyntaxError` exception.
+ prefs['ignore_syntax_errors'] = False
+
+ # If `True`, rope ignores unresolvable imports. Otherwise, they
+ # appear in the importing namespace.
+ prefs['ignore_bad_imports'] = False
+
+
+def project_opened(project):
+ """This function is called after opening the project"""
+ # Do whatever you like here!
View
@@ -2,6 +2,14 @@
Alarm clock logic
"""
+from uberclock.tools import Enumeration
+from django.conf import settings
+
+import datetime
+
+
+ACTIONS = Enumeration("ACTIONS",
+ (("LIGHTS",1), "WAKEUP"))
class Manager(object):
"""Manages Alarm Programs"""
@@ -69,6 +77,7 @@ class BaseAction(object):
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
+ self.background = kwargs.get("background", False)
def execute(self):
raise NotImplemented
@@ -80,8 +89,11 @@ class ExecuteAction(BaseAction):
"""
def execute(self):
import subprocess
- self.popen = subprocess.Popen(self.args)
- self.popen.communicate()
+ if self.background:
+ self.popen = subprocess.Popen(self.args)
+ else:
+ self.popen = subprocess.Popen(self.args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ return self.popen.communicate()
class BaseAlarm(object):
"""
@@ -92,22 +104,30 @@ class BaseAlarm(object):
name = None
short_name = None
- def __init__(self, manager, session):
+ def __init__(self, manager, session, **kwargs):
self.manager = manager
self.session = session
self.next_alarm = None
+ self.snooze_time = kwargs.get('snooze_time', settings.DEFAULT_SNOOZE_TIME)
def check(self):
"""
Returns a alarm action to execute
"""
- return None
+ return False
- def snooze(self):
+ def snooze(self, snooze_time=None):
"""
User pressed snooze
"""
- pass
+ if snooze_time is None:
+ snooze_time = self.snooze_time
+
+ self.next_alarm = datetime.datetime.now() + \
+ datetime.timedelta(seconds=snooze_time)
+
+ def stop(self):
+ self.next_alarm = None
def feed(self, entry):
"""
@@ -120,4 +140,64 @@ class BasicAlarm(BaseAlarm):
name = "Basic Alarm"
short_name = "basic"
-manager.register(BasicAlarm)
+ def check(self, dt=None):
+ """
+ Returns a alarm action to execute
+ """
+ if not dt:
+ dt = datetime.datetime.now()
+ if not self.next_alarm:
+ return False
+ if self.next_alarm < dt:
+ return ACTIONS.WAKEUP
+ return False
+
+manager.register(BasicAlarm)
+
+class MovementAlarm(BasicAlarm):
+ key = "simple_movement"
+ name = "Simple Movement"
+ short_name = "smplmv"
+
+ DEFAULT_THRESHHOLDS = {
+ 0: 20000, # OpenChronos
+ None: 1000, # Unknown, default
+ }
+
+ def __init__(self, *args, **kwargs):
+ super(MovementAlarm, self).__init__(*args, **kwargs)
+
+ th = self.DEFAULT_THRESHHOLDS[None]
+ if self.session:
+ if self.session.detector:
+ th = self.DEFAULT_THRESHHOLDS.get(session.detector.typ, None)
+ if self.session.program:
+ th = self.session.program.get_var("movement_threshhold", th)
+ if "threshhold" in kwargs:
+ th = kwargs["threshhold"]
+ self.threshold = th
+
+ def check(self, dt=None):
+ """
+ Returns a alarm action to execute
+ """
+ if not dt:
+ dt = datetime.datetime.now()
+ # if the default action is already fireing
+ rv = super(MovementAlarm, self).check(dt)
+ if rv:
+ return rv
+ if not self.session.window:
+ return
+ fwin = dt - datetime.timedelta(minutes=self.session.window)
+ for entry in self.session.entry_set.order_by('-date')[:3]:
+ # stop when the entry is befor the considered window
+ if entry.date < fwin:
+ break
+ if entry.value > self.threshold:
+ if self.session.action_in_window(ACTIONS.WAKEUP, dt):
+ return ACTIONS.WAKEUP
+
+
+manager.register(MovementAlarm)
+
@@ -0,0 +1,15 @@
+from django.core.management.base import BaseCommand, CommandError
+from uberclock.db.models import cleanup_db
+from django.conf import settings
+from optparse import make_option
+import logging
+
+class Command(BaseCommand):
+ args = ''
+ help = 'Cleanup the database'
+
+ def handle(self, *args, **options):
+ logging.basicConfig(level=logging.DEBUG)
+ logging.info("cleanup database")
+ cleanup_db()
+ logging.info("done")
Oops, something went wrong.

0 comments on commit 89cbae5

Please sign in to comment.