Skip to content

Commit

Permalink
simple threshold based logic and tests
Browse files Browse the repository at this point in the history
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 89cbae5
Show file tree
Hide file tree
Showing 8 changed files with 608 additions and 38 deletions.
85 changes: 85 additions & 0 deletions .pida-metadata/python/config.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!
94 changes: 87 additions & 7 deletions db/alarm.py
Expand Up @@ -2,6 +2,14 @@
Alarm clock logic Alarm clock logic
""" """


from uberclock.tools import Enumeration
from django.conf import settings

import datetime


ACTIONS = Enumeration("ACTIONS",
(("LIGHTS",1), "WAKEUP"))


class Manager(object): class Manager(object):
"""Manages Alarm Programs""" """Manages Alarm Programs"""
Expand Down Expand Up @@ -69,6 +77,7 @@ class BaseAction(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
self.background = kwargs.get("background", False)


def execute(self): def execute(self):
raise NotImplemented raise NotImplemented
Expand All @@ -80,8 +89,11 @@ class ExecuteAction(BaseAction):
""" """
def execute(self): def execute(self):
import subprocess import subprocess
self.popen = subprocess.Popen(self.args) if self.background:
self.popen.communicate() 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): class BaseAlarm(object):
""" """
Expand All @@ -92,22 +104,30 @@ class BaseAlarm(object):
name = None name = None
short_name = None short_name = None


def __init__(self, manager, session): def __init__(self, manager, session, **kwargs):
self.manager = manager self.manager = manager
self.session = session self.session = session
self.next_alarm = None self.next_alarm = None
self.snooze_time = kwargs.get('snooze_time', settings.DEFAULT_SNOOZE_TIME)


def check(self): def check(self):
""" """
Returns a alarm action to execute Returns a alarm action to execute
""" """
return None return False


def snooze(self): def snooze(self, snooze_time=None):
""" """
User pressed snooze 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): def feed(self, entry):
""" """
Expand All @@ -120,4 +140,64 @@ class BasicAlarm(BaseAlarm):
name = "Basic Alarm" name = "Basic Alarm"
short_name = "basic" 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)

15 changes: 15 additions & 0 deletions db/management/commands/cleanup.py
@@ -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")

0 comments on commit 89cbae5

Please sign in to comment.