7 import gnome.gconf as gconf
10 #gobject.threads_init()
12 PATH="/apps/pedometerhomewidget"
13 COUNTER=PATH+"/counter"
17 class PedometerHomePlugin(hildondesktop.HomePluginItem):
22 labelTotalCount = None
24 labelAvgDistance = None
32 gtk.gdk.threads_init()
33 hildondesktop.HomePluginItem.__init__(self)
35 self.client = gconf.client_get_default()
37 self.totalCounter = self.client.get_int(COUNTER)
38 self.mode = self.client.get_int(MODE)
39 self.height = self.client.get_int(HEIGHT)
41 self.client.set_int(COUNTER, 0)
42 self.client.set_int(MODE, 0)
43 self.client.set_int(HEIGHT, 0)
48 self.button = gtk.Button("Start")
49 self.button.connect("clicked", self.button_clicked)
51 self.labelTimer = gtk.Label("00:00:00")
52 self.labelLastCount = gtk.Label("--")
53 self.labelTotalCount = gtk.Label("%d steps" % self.totalCounter)
54 self.labelDistance = gtk.Label("--")
56 mainVBox = gtk.VBox(spacing=1)
57 mainVBox.add(self.button)
58 mainVBox.add(self.labelTimer)
59 mainVBox.add(self.labelLastCount)
60 mainVBox.add(self.labelTotalCount)
61 mainVBox.add(self.labelDistance)
66 self.connect("unrealize", self.close_requested)
67 self.set_settings(True)
68 self.connect("show-settings", self.show_settings)
71 def show_settings(self, widget):
72 def reset_total_counter(arg):
73 widget.totalCounter = 0
74 widget.labelTotalCount.set_label("%d steps" % widget.totalCounter)
75 hildon.hildon_banner_show_information(self,"None", "Total counter was resetted")
77 def selector_changed(selector, data):
78 widget.mode = selector.get_active(0)
79 widget.client.set_int(MODE, widget.mode)
81 def selectorH_changed(selector, data):
82 widget.height = selectorH.get_active(0)
83 widget.client.set_int(HEIGHT, widget.height)
86 dialog.set_transient_for(self)
87 dialog.set_title("Settings")
89 dialog.add_button("OK", gtk.RESPONSE_OK)
90 button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
91 button.set_title("Reset total counter")
92 button.set_alignment(0, 0.8, 1, 1)
93 button.connect("clicked", reset_total_counter)
95 selector = hildon.TouchSelector(text=True)
96 selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
97 selector.append_text("Walk")
98 selector.append_text("Run")
99 selector.connect("changed", selector_changed)
101 modePicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
102 modePicker.set_alignment(0.0, 0.5, 1.0, 1.0)
103 modePicker.set_title("Select mode")
104 modePicker.set_selector(selector)
105 modePicker.set_active(widget.mode)
107 selectorH = hildon.TouchSelector(text=True)
108 selectorH.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
109 selectorH.append_text("< 1.50 m")
110 selectorH.append_text("1.50 - 1.65 m")
111 selectorH.append_text("1.66 - 1.80 m")
112 selectorH.append_text("1.81 - 1.95 m")
113 selectorH.append_text(" > 1.95 m")
114 selectorH.connect("changed", selectorH_changed)
116 heightPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
117 heightPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
118 heightPicker.set_title("Select height")
119 heightPicker.set_selector(selectorH)
120 heightPicker.set_active(widget.height)
122 dialog.vbox.add(button)
123 dialog.vbox.add(modePicker)
124 dialog.vbox.add(heightPicker)
126 response = dialog.run()
127 hildon.hildon_banner_show_information(self, "None", "You have to Stop/Start the counter to apply the new settings")
130 def close_requested(self, widget):
131 if self.pedometer is None:
134 self.pedometer.request_stop()
135 if self.pedometer.isAlive():
136 self.pedometer.join()
138 def update_values(self, totalCurent, lastInterval):
141 self.totalCounter += lastInterval
142 dist = self.pedometer.get_distance(self.totalCounter)
144 tdelta = time.time() - self.startTime
145 hours = int(tdelta / 3600)
146 tdelta -= 3600 * hours
147 mins = int(tdelta / 60)
151 strtime = "%.2d:%.2d:%.2d" % ( hours, mins, secs)
153 self.labelTimer.set_label(strtime)
154 self.labelLastCount.set_label(str(totalCurent) + " steps")
155 self.labelTotalCount.set_label(str(self.totalCounter) + " steps")
157 self.labelDistance.set_label(str(dist/1000) + " km")
159 self.labelDistance.set_label(str(dist) + " m")
161 def button_clicked(self, button):
162 print "button clicked"
164 if self.pedometer is not None and self.pedometer.isAlive():
166 self.pedometer.request_stop()
167 self.pedometer.join()
168 self.client.set_int(COUNTER, self.totalCounter)
169 self.button.set_label("Start")
171 self.pedometer = PedoCounter(self.update_values)
172 self.pedometer.set_mode(self.mode)
173 self.pedometer.set_height(self.height)
175 self.labelTimer.set_label("00:00:00")
176 self.labelLastCount.set_label("0 steps")
177 self.labelTotalCount.set_label("%d steps" % self.totalCounter)
178 self.labelDistance.set_label("0 m")
180 self.pedometer.start()
181 self.startTime = time.time()
182 self.button.set_label("Stop")
184 print "button clicked finished"
186 hd_plugin_type = PedometerHomePlugin
188 # The code below is just for testing purposes.
189 # It allows to run the widget as a standalone process.
190 if __name__ == "__main__":
192 gobject.type_register(hd_plugin_type)
193 obj = gobject.new(hd_plugin_type, plugin_id="plugin_id")
199 ############### old pedometer.py ###
203 from threading import Thread
205 logger = logging.getLogger("pedometer")
206 logger.setLevel(logging.INFO)
208 ch = logging.StreamHandler()
209 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
210 ch.setFormatter(formatter)
211 logger.addHandler(ch)
213 class PedoIntervalCounter:
221 #TODO: check if last detected step is at the end of the interval
223 def __init__(self, coords, tval):
229 def setThreshold(self, value):
230 self.MIN_THRESHOLD = value
232 def setTimeSteps(self, value):
233 self.MIN_TIME_STEPS = value
235 def calc_mean(self, vals):
240 return sum / len(vals)
243 def calc_stdev(self, vals):
245 mean = self.calc_mean(vals)
247 rez+=pow(abs(mean-i),2)
248 return math.sqrt(rez/len(vals))
250 def calc_threshold(self, vals):
253 mean = self.calc_mean(vals)
254 threshold = max (abs(mean-vmax), abs(mean-vmin))
257 def count_steps(self, vals, t):
258 threshold = self.MIN_THRESHOLD
259 mean = self.calc_mean(vals)
264 if abs(vals[i] - mean) > threshold:
267 while i < len(vals) and t[i] < ntime:
272 def get_best_values(self, x, y, z):
273 dev1 = self.calc_stdev(x)
274 dev2 = self.calc_stdev(y)
275 dev3 = self.calc_stdev(z)
276 dev_max = max(dev1, dev2, dev3)
278 if ( abs(dev1 - dev_max ) < 0.001):
279 logger.info("X chosen as best axis, stdev %f" % dev1)
281 elif (abs(dev2 - dev_max) < 0.001):
282 logger.info("Y chosen as best axis, stdev %f" % dev2)
285 logger.info("Z chosen as best axis, stdev %f" % dev3)
288 def number_steps(self):
289 vals = self.get_best_values(self.x, self.y, self.z)
290 return self.count_steps(vals, self.t)
292 class PedoCounter(Thread):
293 COORD_FNAME = "/sys/class/i2c-adapter/i2c-3/3-001d/coord"
294 COORD_FNAME_SDK = "/home/andrei/pedometer-widget-0.1/date.txt"
295 COORD_GET_INTERVAL = 0.01
304 stop_requested = False
305 update_function = None
307 def __init__(self, update_function = None):
308 Thread.__init__(self)
309 if not os.path.exists(self.COORD_FNAME):
310 self.COORD_FNAME = self.COORD_FNAME_SDK
312 self.update_function = update_function
314 def set_mode(self, mode):
315 #runnig, higher threshold to prevent fake steps
317 self.MIN_THRESHOLD = 600
318 self.MIN_TIME_STEPS = 0.35
321 self.MIN_THRESHOLD = 500
322 self.MIN_TIME_STEPS = 0.5
324 #set height, will affect the distance
325 def set_height(self, height_interval):
326 if height_interval == 0:
328 elif height_interval == 1:
330 elif height_interval == 2:
332 elif height_interval == 3:
334 elif height_interval == 4:
337 def get_rotation(self):
338 f = open(self.COORD_FNAME, 'r')
339 coords = [int(w) for w in f.readline().split()]
343 def reset_counter(self):
346 def get_counter(self):
349 def start_interval(self):
350 logger.info("New interval started")
353 coords = [[], [], []]
354 while not self.stop_requested and (len(t) == 0 or t[-1] < 5):
355 x,y,z = self.get_rotation()
356 coords[0].append(int(x))
357 coords[1].append(int(y))
358 coords[2].append(int(z))
359 now = time.time()-stime
361 time.sleep(self.COORD_GET_INTERVAL)
362 pic = PedoIntervalCounter(coords, t)
363 cnt = pic.number_steps()
365 logger.info("Number of steps detected for last interval %d, number of coords: %d" % (cnt, len(t)))
368 logger.info("Total number of steps : %d" % self.counter)
371 def request_stop(self):
372 self.stop_requested = True
375 logger.info("Thread started")
376 while 1 and not self.stop_requested:
377 last_cnt = self.start_interval()
378 if self.update_function is not None:
379 gobject.idle_add(self.update_function, self.counter, last_cnt)
381 logger.info("Thread has finished")
383 def get_distance(self, steps=None):
386 return self.STEP_LENGTH * steps;