]> git.neil.brown.name Git - plato.git/commitdiff
Initial support for profiles and rules.
authorNeilBrown <neilb@suse.de>
Thu, 19 Dec 2013 04:18:23 +0000 (15:18 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 19 Dec 2013 04:18:23 +0000 (15:18 +1100)
Alert can be controlled by rules which can be
affected by time of day and number calling.

alarm/alarm.c
gsm/gsmd2.py
lib/profile.py [new file with mode: 0644]
sms/storesms.py
utils/lock.py

index 50590c37d1fcec9a2c287b0941b6180152657419..ea90c0143592975f0a44531461297335104f0a1d 100644 (file)
@@ -221,7 +221,7 @@ void event_deliver(struct alarm_ev *ev)
                }
                f = open("/run/alert/alarm", O_WRONLY | O_CREAT, 0600);
                if (f) {
-                       write(f, "new\n", 4);
+                       write(f, "alarm\n", 4);
                        close(f);
                }
                /* Abort any current suspend cycle */
index a30156a2e78ee4f032dfd5f20454d65dccdcffea..ff749887e8571edb91811673f87df62397ebb373 100644 (file)
@@ -77,6 +77,7 @@ def call_log_end(key):
 
 def set_alert(key, value):
     path = '/run/alert/' + key
+    tpath = '/run/alert/.new.' + key
     if value == None:
         try:
             os.unlink(path)
@@ -84,9 +85,10 @@ def set_alert(key, value):
             pass
     else:
         try:
-            f = open(path, 'w')
+            f = open(tpath, 'w')
             f.write(value)
             f.close()
+            os.rename(tpath, path)
         except IOError:
             pass
         suspend.abort_cycle()
@@ -1289,7 +1291,7 @@ class voice(Engine):
             self.number = number
         record('incoming', n)
         record('status', 'INCOMING')
-        set_alert('ring','new')
+        set_alert('ring',n)
         self.delay = 500
         self.state = 'incoming'
         self.retry()
@@ -1390,7 +1392,7 @@ class sms_recv(Engine):
                 self.to_delete = res[:-10]
                 self.retry(1)
             if found:
-                set_alert('sms','new')
+                set_alert('sms',reduce(lambda x,y: x+','+y, found))
             self.unblock()
             return False
         if not line or line[:5] == 'ERROR' or line[:10] == '+CMS ERROR':
diff --git a/lib/profile.py b/lib/profile.py
new file mode 100644 (file)
index 0000000..bb396b6
--- /dev/null
@@ -0,0 +1,124 @@
+#
+# Load a list of profiles.  Later ones over-ride
+# earlier.
+# These are just variable assignments stored in a map.
+
+import time
+
+expect = [
+    'tone',
+    'volume',
+    'vibrate',
+    'LED',
+]
+
+def read_profile(p, file):
+    global expect
+    try:
+        f = open(file)
+        l = f.readlines()
+    except IOError:
+        l = []
+    for ln in l:
+        ln = ln.strip()
+        w = ln.split(':', 1)
+        if len(w) == 2:
+            k = w[0].strip()
+            if k in expect:
+                p[k] = w[1].strip()
+            else:
+                raise ValueError
+
+def load_profile(p, t):
+    if '=' in t:
+        pr = t.split('=', 1)
+        p[pr[0].strip()] = pr[1].strip()
+    else:
+        read_profile(p, "/data/profiles/"+t)
+
+def get_profile(event, who):
+    try:
+        f = open("/data/rules")
+        l = f.readlines()
+    except IOError:
+        l = []
+    p = {}
+    for ln in l:
+        ln = ln.strip()
+        w = ln.split(':', 1)
+        if len(w) == 2 and rule_matches(w[0].strip(), event, who):
+            load_profile(p, w[1].strip())
+    return p
+
+def rule_matches(rule, event, who):
+    if rule == '':
+        return True
+    if rule == event:
+        return True
+    for w in who.split(' '):
+        if w[-8:] == rule[-8:]:
+            return True
+    dt = rule.split(' ')
+    tm = time.localtime()
+    for d in dt:
+        a = day_match(d, tm)
+        if a == None:
+            a = time_match(d, tm)
+        if a == True:
+            return True
+        #if a == None:
+        #    raise ValueError
+    return False
+
+
+# python is broken: tm_wday==0 means monday!!!
+days = ['mo','tu','we','th','fr','sa','su']
+def day_match(d, tm):
+    global days
+    dl = d.split(',')
+    for d1 in dl:
+        if d1 in days:
+            if days.index(d1) == tm.tm_wday:
+                return True
+        elif len(d1)==5 and d1[2] == '-':
+            da = d1[0:2]
+            db = d1[3:5]
+            if da not in days or db not in days:
+                return None
+            dan = days.index(da)
+            dbn = days.index(db)
+            if dan <= dbn and dan <= tm.tm_wday and tm.tm_wday <= dbn:
+                return True
+            if dan > dbn and (dan <= tm.tm_wday or dbn >= tm.tm_wday):
+                return True
+        else:
+            return None
+    return False
+
+
+def time_match(t, tm):
+    tl = t.split(',')
+    for t1 in tl:
+        if len(t1) != 11 or t1[5] != '-':
+            return None
+        m1 = to_min(t1[0:5])
+        m2 = to_min(t1[6:11])
+        if m1 < 0 or m2 < 0:
+            return None
+        mn = tm.tm_hour*60 + tm.tm_min
+        if m1 <= m2 and m1 <= mn and mn <= m2:
+            return True
+        if m1 > m2 and (mn >= m1 or mn <= m2):
+            return True
+    return False
+
+def to_min(t):
+    h=t[0:2]
+    m=t[3:5]
+    if not h.isdigit() or not m.isdigit():
+        return -1
+    h=int(h)
+    m=int(m)
+    if h >= 24 or m >= 60:
+        return -1;
+    return h*60 + m
index 477786423e17747c8a8fdc211db896b5da5378ea..2b8d411a66657c106d46f741e71f4e5940cdf2db 100644 (file)
@@ -540,7 +540,7 @@ def sms_update(messages, sim):
     mfile = os.path.join(dir, '.sim-mirror-'+sim)
     mirror = load_mirror(mfile)
     mirror_seen = {}
-    found_one = False
+    found_one = []
     for index in messages:
         sender, date, txt, ref, part = messages[index]
         k = date[2:] + ' ' + sender
@@ -549,7 +549,7 @@ def sms_update(messages, sim):
                           sender=sender, text=txt.encode('utf-8'),
                           state='NEW', ref=ref, part=part)
             store.store(sms)
-            found_one = True
+            found_one.append(sender)
             mirror[index] = k
         mirror_seen[index] = k
 
index f33d037c455df223b5d2c40c3863ed77700007a8..f627608184aa562108070306cbfd7684d835c309 100755 (executable)
@@ -97,6 +97,29 @@ def clear_vibe():
         vib_han.close()
         vib_han = None
 
+
+from profile import *
+
+def do_alert(event, who):
+    p = get_profile(event, who)
+
+    n = '/run/sound/10-alert'
+    if 'tone' in p and p['tone']:
+        path = p['tone']
+        if 'volume' in p:
+            v = int(p['volume'])
+            if v < 10:
+                n = n + ('%d' % v)
+        if path[0] != '/':
+            path = os.path.join("/usr/share/openmoko/sounds",path)
+        try:
+            os.symlink(path, n)
+        except:
+            pass
+    if 'vib' in p and p['vib']:
+        set_vibrate(200,400,1800)
+    return n
+
 class SetAlerts:
     def __init__(self, alertdir, actiondir):
         # arrange to respond to alerts.
@@ -168,12 +191,13 @@ class SetAlerts:
         return False
 
     def action(self, name):
-        n = '/run/sound/10-alert'
         try:
-            os.symlink(os.path.join(self.actiondir, self.pref, name), n)
-        except:
-            pass
-        set_vibrate(200,400,1800)
+            f = open(os.path.join(self.alertdir, name))
+            l = f.readline()
+            f.close()
+        except IOError:
+            l = "new"
+        n = do_alert(name, l)
 
         if display.state != 'on':
             set_dim()