7 import gnome.gconf as gconf
10 #gobject.threads_init()
12 PATH="/apps/pedometerhomewidget"
13 COUNTER=PATH+"/counter"
18 class PedometerHomePlugin(hildondesktop.HomePluginItem):
21 #labels for current steps
22 labelsC = { "timer" : None, "count" : None, "dist" : None, "avgSpeed" : None }
24 #labels for all time steps
25 labelsT = { "timer" : None, "count" : None, "dist" : None, "avgSpeed" : None }
40 gtk.gdk.threads_init()
41 hildondesktop.HomePluginItem.__init__(self)
43 self.client = gconf.client_get_default()
45 self.totalCounter = self.client.get_int(COUNTER)
46 self.totalTime = self.client.get_int(TIMER)
47 self.mode = self.client.get_int(MODE)
48 self.height = self.client.get_int(HEIGHT)
50 self.client.set_int(COUNTER, 0)
51 self.client.set_int(TIMER, 0)
52 self.client.set_int(MODE, 0)
53 self.client.set_int(HEIGHT, 0)
55 self.pedometer = PedoCounter(self.update_values)
56 self.pedometer.set_mode(self.mode)
57 self.pedometer.set_height(self.height)
59 self.button = gtk.Button("Start")
60 self.button.connect("clicked", self.button_clicked)
62 self.create_labels(self.labelsC)
63 self.create_labels(self.labelsT)
65 self.update_ui_values(self.labelsC, 0, 0)
66 self.update_ui_values(self.labelsT, self.totalTime, self.totalCounter)
68 mainHBox = gtk.HBox(spacing=1)
70 descVBox = gtk.VBox(spacing=1)
71 descVBox.add(gtk.Label())
72 descVBox.add(gtk.Label("Time:"))
73 descVBox.add(gtk.Label("Steps:"))
74 descVBox.add(gtk.Label("Distance:"))
75 descVBox.add(gtk.Label("Avg Speed:"))
77 currentVBox = gtk.VBox(spacing=1)
78 currentVBox.add(gtk.Label("Current"))
79 currentVBox.add(self.labelsC["timer"])
80 currentVBox.add(self.labelsC["count"])
81 currentVBox.add(self.labelsC["dist"])
82 currentVBox.add(self.labelsC["avgSpeed"])
84 totalVBox = gtk.VBox(spacing=1)
85 totalVBox.add(gtk.Label("Total"))
86 totalVBox.add(self.labelsT["timer"])
87 totalVBox.add(self.labelsT["count"])
88 totalVBox.add(self.labelsT["dist"])
89 totalVBox.add(self.labelsT["avgSpeed"])
91 mainHBox.add(self.button)
92 mainHBox.add(descVBox)
93 mainHBox.add(currentVBox)
94 mainHBox.add(totalVBox)
99 self.connect("unrealize", self.close_requested)
100 self.set_settings(True)
101 self.connect("show-settings", self.show_settings)
103 def create_labels(self, labels):
104 labels["timer"] = gtk.Label()
105 labels["count"] = gtk.Label()
106 labels["dist"] = gtk.Label()
107 labels["avgSpeed"] = gtk.Label()
109 def update_ui_values(self, labels, timer, steps):
110 def get_str_distance(meters):
112 return str(meters/1000) + " km"
114 return str(meters) + " m"
116 def get_avg_speed(timer, dist):
119 speed = 1.0 *dist / timer
120 #convert from meters per second to kilometers per hour
122 return "%.2f km/h" % speed
125 hours = int(tdelta / 3600)
126 tdelta -= 3600 * hours
127 mins = int(tdelta / 60)
131 strtime = "%.2d:%.2d:%.2d" % ( hours, mins, secs)
133 labels["timer"].set_label(strtime)
134 labels["count"].set_label(str(steps))
136 dist = self.pedometer.get_distance(steps)
138 labels["dist"].set_label(get_str_distance(dist))
139 labels["avgSpeed"].set_label(get_avg_speed(timer, dist))
141 def update_current(self):
142 self.update_ui_values(self.labelsC, self.time, self.counter)
144 def update_total(self):
145 self.update_ui_values(self.labelsT, self.totalTime, self.totalCounter)
147 def show_settings(self, widget):
148 def reset_total_counter(arg):
149 widget.totalCounter = 0
151 widget.update_total()
152 hildon.hildon_banner_show_information(self,"None", "Total counter was resetted")
154 def selector_changed(selector, data):
155 widget.mode = selector.get_active(0)
156 widget.client.set_int(MODE, widget.mode)
158 def selectorH_changed(selector, data):
159 widget.height = selectorH.get_active(0)
160 widget.client.set_int(HEIGHT, widget.height)
162 dialog = gtk.Dialog()
163 dialog.set_transient_for(self)
164 dialog.set_title("Settings")
166 dialog.add_button("OK", gtk.RESPONSE_OK)
167 button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
168 button.set_title("Reset total counter")
169 button.set_alignment(0, 0.8, 1, 1)
170 button.connect("clicked", reset_total_counter)
172 selector = hildon.TouchSelector(text=True)
173 selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
174 selector.append_text("Walk")
175 selector.append_text("Run")
176 selector.connect("changed", selector_changed)
178 modePicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
179 modePicker.set_alignment(0.0, 0.5, 1.0, 1.0)
180 modePicker.set_title("Select mode")
181 modePicker.set_selector(selector)
182 modePicker.set_active(widget.mode)
184 selectorH = hildon.TouchSelector(text=True)
185 selectorH.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
186 selectorH.append_text("< 1.50 m")
187 selectorH.append_text("1.50 - 1.65 m")
188 selectorH.append_text("1.66 - 1.80 m")
189 selectorH.append_text("1.81 - 1.95 m")
190 selectorH.append_text(" > 1.95 m")
191 selectorH.connect("changed", selectorH_changed)
193 heightPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
194 heightPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
195 heightPicker.set_title("Select height")
196 heightPicker.set_selector(selectorH)
197 heightPicker.set_active(widget.height)
199 dialog.vbox.add(button)
200 dialog.vbox.add(modePicker)
201 dialog.vbox.add(heightPicker)
203 response = dialog.run()
204 hildon.hildon_banner_show_information(self, "None", "You have to Stop/Start the counter to apply the new settings")
207 def close_requested(self, widget):
208 if self.pedometer is None:
211 self.pedometer.request_stop()
212 if self.pedometer.isAlive():
213 self.pedometer.join()
215 def update_values(self, totalCurent, lastInterval):
216 self.totalCounter += lastInterval
217 self.counter = totalCurent
219 tdelta = time.time() - self.time - self.startTime
221 self.totalTime += tdelta
223 self.update_current()
226 def button_clicked(self, button):
227 print "button clicked"
229 if self.pedometer is not None and self.pedometer.isAlive():
231 self.pedometer.request_stop()
232 self.pedometer.join()
233 self.client.set_int(COUNTER, self.totalCounter)
234 self.client.set_int(COUNTER, int(self.totalTime))
235 self.button.set_label("Start")
237 self.pedometer = PedoCounter(self.update_values)
238 self.pedometer.set_mode(self.mode)
239 self.pedometer.set_height(self.height)
244 self.update_current()
246 self.pedometer.start()
247 self.startTime = time.time()
248 self.button.set_label("Stop")
250 print "button clicked finished"
252 hd_plugin_type = PedometerHomePlugin
254 # The code below is just for testing purposes.
255 # It allows to run the widget as a standalone process.
256 if __name__ == "__main__":
258 gobject.type_register(hd_plugin_type)
259 obj = gobject.new(hd_plugin_type, plugin_id="plugin_id")
263 ############### old pedometer.py ###
267 from threading import Thread
269 logger = logging.getLogger("pedometer")
270 logger.setLevel(logging.INFO)
272 ch = logging.StreamHandler()
273 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
274 ch.setFormatter(formatter)
275 logger.addHandler(ch)
277 class PedoIntervalCounter:
285 #TODO: check if last detected step is at the end of the interval
287 def __init__(self, coords, tval):
293 def setThreshold(self, value):
294 self.MIN_THRESHOLD = value
296 def setTimeSteps(self, value):
297 self.MIN_TIME_STEPS = value
299 def calc_mean(self, vals):
304 return sum / len(vals)
307 def calc_stdev(self, vals):
309 mean = self.calc_mean(vals)
311 rez+=pow(abs(mean-i),2)
312 return math.sqrt(rez/len(vals))
314 def calc_threshold(self, vals):
317 mean = self.calc_mean(vals)
318 threshold = max (abs(mean-vmax), abs(mean-vmin))
321 def count_steps(self, vals, t):
322 threshold = self.MIN_THRESHOLD
323 mean = self.calc_mean(vals)
328 if abs(vals[i] - mean) > threshold:
331 while i < len(vals) and t[i] < ntime:
336 def get_best_values(self, x, y, z):
337 dev1 = self.calc_stdev(x)
338 dev2 = self.calc_stdev(y)
339 dev3 = self.calc_stdev(z)
340 dev_max = max(dev1, dev2, dev3)
342 if ( abs(dev1 - dev_max ) < 0.001):
343 logger.info("X chosen as best axis, stdev %f" % dev1)
345 elif (abs(dev2 - dev_max) < 0.001):
346 logger.info("Y chosen as best axis, stdev %f" % dev2)
349 logger.info("Z chosen as best axis, stdev %f" % dev3)
352 def number_steps(self):
353 vals = self.get_best_values(self.x, self.y, self.z)
354 return self.count_steps(vals, self.t)
356 class PedoCounter(Thread):
357 COORD_FNAME = "/sys/class/i2c-adapter/i2c-3/3-001d/coord"
358 COORD_FNAME_SDK = "/home/andrei/pedometer-widget-0.1/date.txt"
359 COORD_GET_INTERVAL = 0.01
368 stop_requested = False
369 update_function = None
371 def __init__(self, update_function = None):
372 Thread.__init__(self)
373 if not os.path.exists(self.COORD_FNAME):
374 self.COORD_FNAME = self.COORD_FNAME_SDK
376 self.update_function = update_function
378 def set_mode(self, mode):
379 #runnig, higher threshold to prevent fake steps
381 self.MIN_THRESHOLD = 600
382 self.MIN_TIME_STEPS = 0.35
385 self.MIN_THRESHOLD = 500
386 self.MIN_TIME_STEPS = 0.5
388 #set height, will affect the distance
389 def set_height(self, height_interval):
390 if height_interval == 0:
392 elif height_interval == 1:
394 elif height_interval == 2:
396 elif height_interval == 3:
398 elif height_interval == 4:
401 def get_rotation(self):
402 f = open(self.COORD_FNAME, 'r')
403 coords = [int(w) for w in f.readline().split()]
407 def reset_counter(self):
410 def get_counter(self):
413 def start_interval(self):
414 logger.info("New interval started")
417 coords = [[], [], []]
418 while not self.stop_requested and (len(t) == 0 or t[-1] < 5):
419 x,y,z = self.get_rotation()
420 coords[0].append(int(x))
421 coords[1].append(int(y))
422 coords[2].append(int(z))
423 now = time.time()-stime
425 time.sleep(self.COORD_GET_INTERVAL)
426 pic = PedoIntervalCounter(coords, t)
427 cnt = pic.number_steps()
429 logger.info("Number of steps detected for last interval %d, number of coords: %d" % (cnt, len(t)))
432 logger.info("Total number of steps : %d" % self.counter)
435 def request_stop(self):
436 self.stop_requested = True
439 logger.info("Thread started")
440 while 1 and not self.stop_requested:
441 last_cnt = self.start_interval()
442 if self.update_function is not None:
443 gobject.idle_add(self.update_function, self.counter, last_cnt)
445 logger.info("Thread has finished")
447 def get_distance(self, steps=None):
450 return self.STEP_LENGTH * steps;