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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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"""
Expand Down Expand Up @@ -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
Expand All @@ -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):
"""
Expand All @@ -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):
"""
Expand All @@ -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)

15 changes: 15 additions & 0 deletions db/management/commands/cleanup.py
Original file line number Diff line number Diff line change
@@ -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")
Loading

0 comments on commit 89cbae5

Please sign in to comment.