Skip to content

Commit

Permalink
started implementing alarm logics
Browse files Browse the repository at this point in the history
* small bugfixes
  • Loading branch information
poelzi committed Jul 24, 2010
1 parent b5fca41 commit c14d2f1
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 31 deletions.
4 changes: 3 additions & 1 deletion TODO
@@ -1,3 +1,5 @@
• fix hero weather proxy
• make it translatable
• unittests
• unittests
• allow the uberclockd to act as wireless update server
• add command line tool to control server via rpc
33 changes: 22 additions & 11 deletions db/alarm.py
Expand Up @@ -13,12 +13,12 @@ def register(self, program):
"""
Register a new alarm clock program
"""
if not program.nid:
raise ValueError, "program id (nid) is not set"
if program.nid in self.programs and self.programs[program.nid] != program:
raise ValueError, "program id (nid) already exists"
if not program.key:
raise ValueError, "program id (key) is not set"
if program.key in self.programs and self.programs[program.key] != program:
raise ValueError, "program id (key) already exists"

self.programs[program.nid] = program
self.programs[program.key] = program

def list_programs(self):
"""
Expand All @@ -32,15 +32,18 @@ def choices_programs(self):
Return a choices list used in django
"""
rv = []
for program in self.programs.iteritems():
rv.append((program.nid, program))
for key,program in self.programs.iteritems():
rv.append((key, program))
return rv

def is_valid_program_id(self, nid):
def is_valid_program(self, key):
for program in self.programs.iteritems():
if program.nid == nid:
if program.key == key:
return True

def get_program(self, key):
return self.programs.get(key, self.programs["basic"] )

def create_session(self, user_name, program):
pass

Expand Down Expand Up @@ -85,8 +88,9 @@ class BaseAlarm(object):
Base Class for all alarm logics
"""
# numeric id. must be unique and change never
nid = None
title = None
key = None
name = None
short_name = None

def __init__(self, manager, session):
self.manager = manager
Expand All @@ -110,3 +114,10 @@ def feed(self, entry):
Feed one new Entry into the Alarm program.
"""
pass

class BasicAlarm(BaseAlarm):
key = "basic"
name = "Basic Alarm"
short_name = "basic"

manager.register(BasicAlarm)
126 changes: 114 additions & 12 deletions db/models.py
Expand Up @@ -24,6 +24,17 @@

RF_ID_BIT_LENGHT = 3

def get_user_or_default(user=None):
if user and isinstance(user, User):
return user
try:
return User.objects.get(username=user)
except User.DoesNotExist:
try:
return User.objects.get(username=settings.DEFAULT_USER)
except User.DoesNotExist:
return None

class Detector(models.Model):
"""
Device which messures the sleep state
Expand All @@ -36,6 +47,58 @@ class Detector(models.Model):
def __repr__(self):
return '<Detector %s >' %self.ident

class UserProgramManager(models.Manager):
def get_program_for_user(self, user, id_):
obj, created = self.get_or_create(user = user, users_id = id_,
defaults = {
"user":user, "users_id":id_,
"alarm_key":settings.DEFAULT_ALARM
})
if created:
obj.save()
return obj

def get_users_default(self, user):
res = self.filter(user=user).order_by("-default", "users_id")
if not res:
return None
return res[0]

class UserProgram(models.Model):
"""
Maps a alarm program to user and his choosen id
"""
user = models.ForeignKey(User, null=True, db_index=True)
users_id = models.IntegerField(null=False, db_index=True)
default = models.BooleanField(default=False)
alarm_key = models.CharField(null=False, max_length=30, choices=alarm.manager.choices_programs)
rname = models.CharField(max_length=30, null=True, blank=True)
short_name = models.CharField(max_length=5, null=True, blank=True)

settings = models.TextField()

objects = UserProgramManager()

class Meta:
unique_together = (("user", "users_id"),)

def _get_name(self):
if self.rname:
return self.rname
return alarm.manager.get_program(self.alarm_key).name

def _set_name(self, val):
self.rname = val

name = property(_get_name, _set_name)

@property
def program_class(self):
return alarm.manager.get_program(self.alarm_key)

def __unicode__(self):
return u"%s of %s" %(self.name, self.user)

class WakeupTime(models.Model):
"""
User saved wakeup times for shortcuts
Expand Down Expand Up @@ -94,7 +157,7 @@ class Session(models.Model):
stop = models.DateTimeField("Stop", null=False, auto_now_add=True, editable=False)
user = models.ForeignKey(User, null=True)
detector = models.ForeignKey(Detector, null=True)
program = models.IntegerField("Program", default=0, choices=alarm.manager.choices_programs)
program = models.ForeignKey(UserProgram, null=True)
wakeup = models.DateTimeField("Wakeup", null=True)
rating = models.IntegerField("Rating", null=True)
deleted = models.BooleanField("Deleted", default=False)
Expand All @@ -103,13 +166,38 @@ class Session(models.Model):
new = models.BooleanField("Session has not yet run", default=False)

objects = SessionManager()

# Do we need this ?
#alone = models.BooleanField("Alone", null=True, default=True, help_text="Sleeping with someone else in the bed")

# def __init__(self, *args, **kwargs):
# if not "user" in kwargs:
# if "detector" in kwargs:
# kwargs["user"] = get_user_or_default(kwargs["device"].default_user)
# else:
# kwargs["user"] =
# if not "program" in kwargs:
# self.kwargs["program"] = UserProgram.objects.get_users_default(kwargs["user"])
#
# return super(Session, self).__init__(*args, **kwargs)

def save(self, *args, **kwargs):
super(Session, self).save(*args, **kwargs)
self.learndata

@property
def get_user(self):
if self.user:
return self.user
if self.detector and self.detector.default_user:
# we set self.user here, so changes to a detector will not change
# old sessions
self.user = self.detector.default_user
return self.user
# fallback to default user
self.user = get_user_or_default()
return self.user

@property
def learndata(self):
if not self.id:
Expand Down Expand Up @@ -246,8 +334,11 @@ def smpl_0x03(self, data):
try:
session = Session.objects.get_active_session(rf_id)
except Session.DoesNotExist:
logging.warning("Session id sent which is not active. Creating a new Session")
session = Session(start=now, stop=now, rf_id=rf_id)
logging.warning("Session id %s sent which is not active. Creating a new Session" %rf_id)
user=get_user_or_default(None)
program=UserProgram.objects.get_users_default(user)
session = Session(start=now, stop=now, rf_id=rf_id,
user=user, program=program)
session.save()

logging.debug("%s S:%2d C:%2d %6d %s" %(session.id, rf_id, counter, var, "#"*max(min((var/500), 80),1)))
Expand All @@ -264,9 +355,11 @@ def smpl_0x04(self, data):
print "04", repr(data)
mdata = self.get_smpl_data(data)
ident = "0x%02x%02x" %(ord(mdata[0]), ord(mdata[1]))
device, created = Detector.objects.get_or_create(ident=ident, defaults={"name": "eZ430 OpenChronos",
device, created = Detector.objects.get_or_create(ident=ident,
defaults={"name": "eZ430 OpenChronos",
"ident": ident,
"typ": DETECTOR_TYPES[0][0],
"user": get_user_or_default(None),
})
if created:
device.save()
Expand All @@ -283,22 +376,31 @@ def smpl_0x04(self, data):
# we have an active session running
active_session = session

# find program
program_id = ord(mdata[2])
user = get_user_or_default(device.default_user)
program = UserProgram.objects.get_program_for_user(user, program_id)


if not active_session:
rf_id = Session.objects.get_new_rf_id()
program = ord(mdata[2])
if not alarm.manager.is_valid_program_id(program):
program = 0
active_session = Session(start=now, stop=now, detector=device, user=device.default_user,
rf_id=rf_id, program=program)

active_session = Session(start=now, stop=now, detector=device,
rf_id=rf_id,
user=user,
program=program)
active_session.save()

logging.info("Send Session ID: %s" %(active_session.rf_id))

logging.info("Send Session ID: %s (user:%s program:%s)" %(active_session.rf_id, active_session.user, active_session.program))

data = [SIMPLICITI_PHASE_CLOCK_START_RESPONSE, active_session.rf_id]
self.send_smpl_data(data)
# we shall not do anything until the clock reads out the
# session data
time.sleep(0.030)
for x in xrange(10):
self.send_smpl_data(data, wait=False)
time.sleep(0.050)

def smpl_0x10(self, data):
"""
Expand All @@ -309,7 +411,7 @@ def smpl_0x10(self, data):
# empty buffer
self.read_sync_data()
# read old data
for x in xrange(1000):
for x in xrange(100):
self.send_smpl_data([ez_chronos.SYNC_AP_CMD_GET_STATUS], wait=False)
time.sleep(0.020)
if self.get_sync_buffer_status():
Expand Down
17 changes: 13 additions & 4 deletions settings.py
@@ -1,6 +1,11 @@
# Django settings for uberclock project.

import os.path
import os, os.path

CONFIG_PATH = os.path.expanduser("~/.uberclock")

if not os.path.exists(CONFIG_PATH):
os.mkdir(CONFIG_PATH)

DEVELOPMENT_MODE = False
DEBUG = True
Expand Down Expand Up @@ -122,6 +127,9 @@
SERVER_LISTEN = '0.0.0.0'
SERVER_PORT = 8000

DEFAULT_USER = 'user'
DEFAULT_ALARM = 'basic'

CLOCK_SESSION_TIMEOUT = 60*5

PISTON_STREAM_OUTPUT = True
Expand All @@ -133,11 +141,12 @@
'default' : '<embed width="800" height="480" quality="high" bgcolor="#FFFFFF" wmode="transparent" name="virtualchumby" type="application/x-shockwave-flash" src="http://www.chumby.com/virtualchumby_noskin.swf" FlashVars="_chumby_profile_url=http%3A%2F%2Fwww.chumby.com%2Fxml%2Fvirtualprofiles%2FE8E34C1E-726B-11DF-BA50-001B24F07EF4&amp;baseURL=http%3A%2F%2Fwww.chumby.com" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>'
}

import os

if not os.path.exists(os.path.expanduser("~/.uberclock")):
os.mkdir(os.path.expanduser("~/.uberclock"))
# load user config file
if os.path.exists(os.path.join(CONFIG_PATH, "settings.py")):
execfile(os.path.join(CONFIG_PATH, "settings.py"), globals())

# load current dir config file
try:
from settings_local import *
except ImportError:
Expand Down
11 changes: 8 additions & 3 deletions tools/ez_chronos.py
Expand Up @@ -107,7 +107,7 @@ def __init__(self, stream):
#self._nullread()
self.debug = False
self.sync()
print self.dstr(self.send_read(BM_GET_PRODUCT_ID, [0x00, 0x00, 0x00, 0x00]))
#self.send_smpl_data([], wait=False)
#def

#def _nullread(self):
Expand Down Expand Up @@ -158,7 +158,7 @@ def send(self, cmd_, data=None):
res = array.array('B', [0xFF, cmd_, ln])
self.last_cmd = (cmd_, ln)
if self.debug:
if self.debug >= 2:
if self.debug >= 3:
print "send:" + self.dstr(res.tostring())
else:
if res.tostring() not in ('\xff\x08\x07\x00\x00\x00\x00', '\xff\x32\x04\x00'):
Expand Down Expand Up @@ -217,6 +217,11 @@ def reset(self):

def start_ap(self):
self.send_read(BM_START_SIMPLICITI)
for i in xrange(10):
res = self.send_read(BM_GET_SIMPLICITIDATA, [0x00, 0x00, 0x00, 0x00])
print self.dstr(res)
res = self.send_read(BM_GET_STATUS, [0x00])
print self.dstr(res)

def stop_ap(self):
#The start access point command needs to come before the stop access point command
Expand Down Expand Up @@ -321,7 +326,7 @@ def handle_smpl_data(self, data):
if self.debug > 3:
print "got no data"
else:
if self.debug >= 2:
if self.debug >= 1:
print "handle", self.dstr(data)
if hasattr(self, "smpl_%s" %"0x%0.2X" %ord(data[3])):
getattr(self, "smpl_%s" %"0x%0.2X" %ord(data[3]))(data)
Expand Down

0 comments on commit c14d2f1

Please sign in to comment.