Added option to log accelerometer data to file
[pedometerwidget] / pedometer_widget_home.py~
index 19363fb..fca005a 100644 (file)
 import gtk
 import hildondesktop
+import gobject
+import os
+import time
+import hildon
+import gnome.gconf as gconf
 
-#from pedometer import *
+print "!!!!"
+#gobject.threads_init()
 
-class HelloWorldDialog(gtk.Dialog):
-    def __init__(self):
-        gtk.Dialog.__init__(self, "Hello World", None,
-                            gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR,
-                            ("Close", gtk.RESPONSE_OK))
-        self.vbox.add(gtk.Label("Hello World!"))
-        self.show_all()
-
-def hello_world_dialog_show(button):
-    dialog = HelloWorldDialog()
-    dialog.run()
-    dialog.destroy()
+PATH="/apps/pedometerhomewidget"
+COUNTER=PATH+"/counter"
+TIMER=PATH+"/timer"
+MODE=PATH+"/mode"
+HEIGHT=PATH+"/height"
+UNIT=PATH+"/unit"
+ASPECT=PATH+"/aspect"
 
 class PedometerHomePlugin(hildondesktop.HomePluginItem):
     button = None
-    loader = None
-    labelLastCount = None
-    labelTotalCount = None
-    labelDistance = None
+
+    #labels for current steps
+    labelsC = { "timer" : None, "count" : None, "dist" : None, "avgSpeed" : None }
+
+    #labels for all time steps
+    labelsT = { "timer" : None, "count" : None, "dist" : None, "avgSpeed" : None }
 
     pedometer = None
+    startTime = None
 
-    def __init__(self):
+    totalCounter = 0
+    totalTime = 0
+    mode = 0
+    height = 0
+    unit = 0
 
-        gtk.gdk.threads_init()
-        hildondesktop.HomePluginItem.__init__(self)
-        button = gtk.Button("Start")
-        button.connect("clicked", self.button_clicked)
+    counter = 0
+    time = 0
+    aspect = 0
 
-        self.labelLastCount = gtk.Label("--")
-        self.labelTotalCount = gtk.Label("--")
-        self.labelDistance = gtk.Label("--")
+    def __init__(self):
 
-        mainVBox = gtk.VBox(spacing=1)
-        mainVBox.add(button)
-        mainVBox.add(self.labelLastCount)
-        mainVBox.add(self.labelTotalCount)
-        mainVBox.add(self.labelDistance)
+        gtk.gdk.threads_init()
+        hildondesktop.HomePluginItem.__init__(self)
 
-        mainVBox.show_all()
-        self.add(mainVBox)
+        self.client = gconf.client_get_default()
+        try:
+            self.totalCounter = self.client.get_int(COUNTER)
+            self.totalTime = self.client.get_int(TIMER)
+            self.mode = self.client.get_int(MODE)
+            self.height = self.client.get_int(HEIGHT)
+            self.unit = self.client.get_int(UNIT)
+            self.aspect = self.client.get_int(ASPECT)
+        except:
+            self.client.set_int(COUNTER, 0)
+            self.client.set_int(TIMER, 0)
+            self.client.set_int(MODE, 0)
+            self.client.set_int(HEIGHT, 0)
+            self.client.set_int(UNIT, 0)
+            self.client.set_int(ASPECT, 0)
 
         self.pedometer = PedoCounter(self.update_values)
+        self.pedometer.set_mode(self.mode)
+        self.pedometer.set_height(self.height)
+
+        self.button = gtk.Button("Start")
+        self.button.connect("clicked", self.button_clicked)
+
+        self.create_labels(self.labelsC)
+        self.create_labels(self.labelsT)
+
+        self.update_ui_values(self.labelsC, 0, 0)
+        self.update_ui_values(self.labelsT, self.totalTime, self.totalCounter)
+
+        mainHBox = gtk.HBox(spacing=1)
+
+        descVBox = gtk.VBox(spacing=1)
+        descVBox.add(gtk.Label())
+        descVBox.add(gtk.Label("Time:"))
+        descVBox.add(gtk.Label("Steps:"))
+        descVBox.add(gtk.Label("Distance:"))
+        descVBox.add(gtk.Label("Avg Speed:"))
+
+        currentVBox = gtk.VBox(spacing=1)
+        currentVBox.add(gtk.Label("Current"))
+        currentVBox.add(self.labelsC["timer"])
+        currentVBox.add(self.labelsC["count"])
+        currentVBox.add(self.labelsC["dist"])
+        currentVBox.add(self.labelsC["avgSpeed"])
+        self.currentBox = currentVBox
+
+        totalVBox = gtk.VBox(spacing=1)
+        totalVBox.add(gtk.Label("Total"))
+        totalVBox.add(self.labelsT["timer"])
+        totalVBox.add(self.labelsT["count"])
+        totalVBox.add(self.labelsT["dist"])
+        totalVBox.add(self.labelsT["avgSpeed"])
+        self.totalBox = totalVBox
+
+        mainHBox.add(self.button)
+        mainHBox.add(descVBox)
+        mainHBox.add(currentVBox)
+        mainHBox.add(totalVBox)
+
+        mainHBox.show_all()
+        self.add(mainHBox)
+        self.update_aspect()
+
+        self.connect("unrealize", self.close_requested)
+        self.set_settings(True)
+        self.connect("show-settings", self.show_settings)
+
+    def create_labels(self, labels):
+        labels["timer"] = gtk.Label()
+        labels["count"] = gtk.Label()
+        labels["dist"] = gtk.Label()
+        labels["avgSpeed"] = gtk.Label()
+
+    def update_aspect(self):
+        if self.aspect == 0:
+            self.currentBox.show_all()
+            self.totalBox.show_all()
+        elif self.aspect == 1:
+            self.currentBox.show_all()
+            self.totalBox.hide_all()
+        else:
+            self.currentBox.hide_all()
+            self.totalBox.show_all()
+
+    def update_ui_values(self, labels, timer, steps):
+        def get_str_distance(meters):
+            if meters > 1000:
+                if self.unit == 0:
+                    return str(meters/1000) + " km"
+                else:
+                    return str(meters/1609.344) + " mi"
+            else:
+                if self.unit == 0:
+                    return str(meters) + " m"
+                else:
+                    return str(meters*3.2808) + " ft"
+
+        def get_avg_speed(timer, dist):
+            suffix = ""
+            conv = 0
+            if self.unit:
+                suffix = "mi/h"
+                conv = 2.23693629
+            else:
+                suffix = "km/h"
+                conv = 3.6
+
+            if timer == 0:
+                return "N/A " + suffix
+            speed = 1.0 *dist / timer
+            #convert from meters per second to km/h or mi/h
+            speed *= conv
+            return "%.2f %s" % (speed, suffix)
+
+        tdelta = timer
+        hours = int(tdelta / 3600)
+        tdelta -= 3600 * hours
+        mins = int(tdelta / 60)
+        tdelta -= 60 * mins
+        secs = int(tdelta)
+
+        strtime = "%.2d:%.2d:%.2d" % ( hours, mins, secs)
+
+        labels["timer"].set_label(strtime)
+        labels["count"].set_label(str(steps))
+
+        dist = self.pedometer.get_distance(steps)
+
+        labels["dist"].set_label(get_str_distance(dist))
+        labels["avgSpeed"].set_label(get_avg_speed(timer, dist))
+
+    def update_current(self):
+        self.update_ui_values(self.labelsC, self.time, self.counter)
+
+    def update_total(self):
+        self.update_ui_values(self.labelsT, self.totalTime, self.totalCounter)
+
+    def show_settings(self, widget):
+        def reset_total_counter(arg):
+            widget.totalCounter = 0
+            widget.totalTime = 0
+            widget.update_total()
+            hildon.hildon_banner_show_information(self,"None", "Total counter was resetted")
+
+        def selector_changed(selector, data):
+            widget.mode = selector.get_active(0)
+            widget.client.set_int(MODE, widget.mode)
+
+        def selectorH_changed(selector, data):
+            widget.height = selectorH.get_active(0)
+            widget.client.set_int(HEIGHT, widget.height)
+
+        def selectorUnit_changed(selector, data):
+            widget.unit = selectorUnit.get_active(0)
+            widget.client.set_int(UNIT, widget.unit)
+            widget.update_current()
+            widget.update_total()
+
+        def selectorUI_changed(selector, data):
+            widget.aspect = selectorUI.get_active(0)
+            widget.client.set_int(ASPECT, widget.aspect)
+            widget.update_aspect()
+
+        dialog = gtk.Dialog()
+        dialog.set_transient_for(self)
+        dialog.set_title("Settings")
+
+        dialog.add_button("OK", gtk.RESPONSE_OK)
+        button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        button.set_title("Reset total counter")
+        button.set_alignment(0, 0.8, 1, 1)
+        button.connect("clicked", reset_total_counter)
+
+        selector = hildon.TouchSelector(text=True)
+        selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
+        selector.append_text("Walk")
+        selector.append_text("Run")
+        selector.connect("changed", selector_changed)
+
+        modePicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        modePicker.set_alignment(0.0, 0.5, 1.0, 1.0)
+        modePicker.set_title("Select mode")
+        modePicker.set_selector(selector)
+        modePicker.set_active(widget.mode)
+
+        selectorH = hildon.TouchSelector(text=True)
+        selectorH.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
+        selectorH.append_text("< 1.50 m")
+        selectorH.append_text("1.50 - 1.65 m")
+        selectorH.append_text("1.66 - 1.80 m")
+        selectorH.append_text("1.81 - 1.95 m")
+        selectorH.append_text(" > 1.95 m")
+        selectorH.connect("changed", selectorH_changed)
+
+        heightPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        heightPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
+        heightPicker.set_title("Select height")
+        heightPicker.set_selector(selectorH)
+        heightPicker.set_active(widget.height)
+
+        selectorUnit = hildon.TouchSelector(text=True)
+        selectorUnit.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
+        selectorUnit.append_text("Metric (km)")
+        selectorUnit.append_text("English (mi)")
+        selectorUnit.connect("changed", selectorUnit_changed)
+
+        unitPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        unitPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
+        unitPicker.set_title("Units")
+        unitPicker.set_selector(selectorUnit)
+        unitPicker.set_active(widget.unit)
+
+        selectorUI = hildon.TouchSelector(text=True)
+        selectorUI = hildon.TouchSelector(text=True)
+        selectorUI.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
+        selectorUI.append_text("Show current + total")
+        selectorUI.append_text("Show only current")
+        selectorUI.append_text("Show only total")
+        selectorUI.connect("changed", selectorUI_changed)
+
+        UIPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
+        UIPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
+        UIPicker.set_title("Widget aspect")
+        UIPicker.set_selector(selectorUI)
+        UIPicker.set_active(widget.aspect)
+
+        dialog.vbox.add(button)
+        dialog.vbox.add(modePicker)
+        dialog.vbox.add(heightPicker)
+        dialog.vbox.add(unitPicker)
+        dialog.vbox.add(UIPicker)
+
+        dialog.show_all()
+        response = dialog.run()
+        hildon.hildon_banner_show_information(self, "None", "You have to Stop/Start the counter to apply the new settings")
+        dialog.destroy()
+
+    def close_requested(self, widget):
+        if self.pedometer is None:
+            return
+
+        self.pedometer.request_stop()
+        if self.pedometer.isAlive():
+            self.pedometer.join()
+
+    def update_values(self, totalCurent, lastInterval):
+        self.totalCounter += lastInterval
+        self.counter = totalCurent
+
+        tdelta = time.time() - self.time - self.startTime
+        self.time += tdelta
+        self.totalTime += tdelta
+
+        self.update_current()
+        self.update_total()
 
-    def update_values(self, total, lastInterval):
+    def button_clicked(self, button):
+        print "button clicked"
 
-        print "update"
+        if self.pedometer is not None and self.pedometer.isAlive():
+            #counter is running
+            self.pedometer.request_stop()
+            self.pedometer.join()
+            self.client.set_int(COUNTER, self.totalCounter)
+            self.client.set_int(TIMER, int(self.totalTime))
+            self.button.set_label("Start")
+            self.desc.hide_all()
+        else:
+            self.desc.show_all()
+            self.pedometer = PedoCounter(self.update_values)
+            self.pedometer.set_mode(self.mode)
+            self.pedometer.set_height(self.height)
 
-        dist = self.pedometer.get_distance()
+            self.time = 0
+            self.counter = 0
 
-        self.labelLastCount.set_label(str(lastInterval))
-        self.labelTotalCount.set_label(str(total))
-        self.labelDistance.set_label(str(dist))
+            self.update_current()
 
-    def button_clicked(self, button):
-        print "button clicked"
-        self.labelLastCount.set_label("updating")
-        self.labelTotalCount.set_label("updating")
-        self.labelDistance.set_label("updating")
+            self.pedometer.start()
+            self.startTime = time.time()
+            self.button.set_label("Stop")
 
-        self.pedometer.start()
         print "button clicked finished"
 
-
 hd_plugin_type = PedometerHomePlugin
 
-
 # The code below is just for testing purposes.
 # It allows to run the widget as a standalone process.
 if __name__ == "__main__":
@@ -79,13 +339,9 @@ if __name__ == "__main__":
     obj.show_all()
     gtk.main()
 
-
-
 ############### old pedometer.py ###
 import math
-import time
 import logging
-import gobject
 
 from threading import Thread
 
@@ -97,7 +353,6 @@ formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(messag
 ch.setFormatter(formatter)
 logger.addHandler(ch)
 
-
 class PedoIntervalCounter:
     MIN_THRESHOLD = 500
     MIN_TIME_STEPS = 0.5
@@ -114,6 +369,12 @@ class PedoIntervalCounter:
         self.z = coords[2]
         self.t = tval
 
+    def setThreshold(self, value):
+        self.MIN_THRESHOLD = value
+
+    def setTimeSteps(self, value):
+        self.MIN_TIME_STEPS = value
+
     def calc_mean(self, vals):
         sum = 0
         for i in vals:
@@ -173,17 +434,49 @@ class PedoIntervalCounter:
 
 class PedoCounter(Thread):
     COORD_FNAME = "/sys/class/i2c-adapter/i2c-3/3-001d/coord"
+    COORD_FNAME_SDK = "/home/andrei/pedometer-widget-0.1/date.txt"
     COORD_GET_INTERVAL = 0.01
     COUNT_INTERVAL = 5
-    STEP_LENGTH = 0.5
+
+    STEP_LENGTH = 0.7
+
+    MIN_THRESHOLD = 500
+    MIN_TIME_STEPS = 0.5
 
     counter = 0
+    stop_requested = False
     update_function = None
 
     def __init__(self, update_function = None):
         Thread.__init__(self)
+        if not os.path.exists(self.COORD_FNAME):
+            self.COORD_FNAME = self.COORD_FNAME_SDK
+
         self.update_function = update_function
 
+    def set_mode(self, mode):
+        #runnig, higher threshold to prevent fake steps
+        if mode == 1:
+            self.MIN_THRESHOLD = 600
+            self.MIN_TIME_STEPS = 0.35
+        #walking
+        else:
+            self.MIN_THRESHOLD = 500
+            self.MIN_TIME_STEPS = 0.5
+
+    #set height, will affect the distance
+    def set_height(self, height_interval):
+        if height_interval == 0:
+            STEP_LENGTH = 0.5
+        elif height_interval == 1:
+            STEP_LENGTH = 0.6
+        elif height_interval == 2:
+            STEP_LENGTH = 0.7
+        elif height_interval == 3:
+            STEP_LENGTH = 0.8
+        elif height_interval == 4:
+            STEP_LENGTH = 0.9
+
     def get_rotation(self):
         f = open(self.COORD_FNAME, 'r')
         coords = [int(w) for w in f.readline().split()]
@@ -201,7 +494,7 @@ class PedoCounter(Thread):
         stime = time.time()
         t=[]
         coords = [[], [], []]
-        while len(t) == 0 or t[-1] < 5:
+        while not self.stop_requested and (len(t) == 0 or t[-1] < 5):
             x,y,z = self.get_rotation()
             coords[0].append(int(x))
             coords[1].append(int(y))
@@ -218,15 +511,20 @@ class PedoCounter(Thread):
         logger.info("Total number of steps : %d" % self.counter)
         return cnt
 
+    def request_stop(self):
+        self.stop_requested = True
+
     def run(self):
-        while 1:
+        logger.info("Thread started")
+        while 1 and not self.stop_requested:
             last_cnt = self.start_interval()
             if self.update_function is not None:
                 gobject.idle_add(self.update_function, self.counter, last_cnt)
 
+        logger.info("Thread has finished")
+
     def get_distance(self, steps=None):
         if steps == None:
             steps = self.counter
         return self.STEP_LENGTH * steps;
 
-