Der elektronische Armreif Up misst die Armbewegungen seines Trägers und schließt daraus auf tags zurückgelegte Wege und nächtliche Schlafrhythmen. Wen die offizielle Smartphone-App langweilt, der lässt eigene Perl-Skripte auf das inoffizielle Web-API zugreifen.
Um der verbreiteten Tendenz zu übermäßigem Körperfett entgegenzuwirken, tragen viele Smartphonebesitzer heutzutage kleine Gadgets mit sich herum, die sie an ihre Trägheit erinnern. Wer stundenlang regungslos vor dem Bildschirm sitzt, soll so motiviert werden, öfter ums Karree zu gehen oder die Toilette im falschen Stockwerk aufzusuchen. Der Trend zur Selbstvermessung kommt aus den USA und rangiert unter dem Namen “Quantify Yourself”.
Ein elektronischer Armreif wie das Up-Band ([2], Abbildung 1) von der Firma Jawbone misst die gegangenen Schritte und zeigt später über die zugehörige App fürs Smartphone die zurückgelegte Wegstrecke und die verbrauchten Kalorien an. Das Accessoire gibt es in drei Größen, mehreren Farben und ist auch in Europa für rund 130 Euro leicht erhältlich. Das Gerät scheint funktional nur momentane Beschleunigungswerte zu erfassen und sie zeitlich zu kumulieren. Die geografische Position des Trägers ließe sich mit einem GPS-Chip ermitteln, aber ein solcher würde die kleine Batterie des Geräts wohl in kürzester Zeit leersaugen.
Online PLUS
In einem Screencast demonstriert Michael Schilli das Beispiel: https://www.linux-magazin.de/plus/2013/10
Entblößtes Innenleben
Da die auf Lifestyle-Gadgtes spezialisierte Firma Jawbone in Sachen Open Hardware unverdächtig ist, schlitzt in einem Video ([3], Abbildung 3) ein neugieriger Elektronik-Freak kurzerhand die äußere Gummihülle des Armbands auf und zeigt die wasserdicht eingeschweißten Komponenten. Er findet bei seiner Operation ein halbes Dutzend kleinerer Platinchen mit SMD-Komponenten, aber außer einem Beschleunigungsmesser, der Lithium-Ionen-Batterie inklusive Ladechips, einem Vibrator und Komponenten zum Andocken an den Audioport des Smartphones kommt nichts zutage.
Der Armreif schickt also lediglich die zeitlich aufbereiten Beschleunigungsdaten an ein Machine-Learning-System, das aus dem Bewegungsmuster errät, welche Art von Bewegung die Person ausführt (Gehen, Laufen, Fitnesstrainer), wie viele Schritte der Träger geschafft und welche Wegstrecke er dabei zurückgelegt hat.
Schlaf der Gerechten
Wer den Reif auch nachts trägt, kann am Morgen über seine Schlafmuster staunen. Die App zeigt grafisch an, wann der Träger zu Bett ging, wann er eingeschlafen ist, wie oft er aufgewacht oder aufgestanden ist. Auf Wunsch weckt die App den Schläfer mit sanftem Vibrieren innerhalb eines 20 Minuten langen Intervalls zu einem Zeitpunkt, an dem das Aufwachen am wenigsten nervig ist.
Zum Erfassen der Schlafrhythmen muss der User das Gerät allerdings vor dem Einschlafen manuell per Knopfdruck in den Schlafmodus versetzen. Bewegt sich der Träger dann lange Zeit nicht, ist er wohl tief eingeschlafen, liegen kleinere Bewegungen vor, gleitet er in eine leichtere Schlafphase hinüber.
Der im Band verbaute Akku hält ungefähr eine Woche ohne Nachladen durch. Um die Daten auszulesen, zieht der User ein Stöpselchen an einem Ende des Bandes ab und legt dabei einen Audiostecker frei. Den führt er in den Audioport seines Smartphones ein (Abbildung 5) und startet die Up-App. Das Band morst die Bewegungsdaten an die App und damit an den Server in der Jawbone-Cloud. Von dort erhält die App die aufbereiteten Daten zurück und zeigt sie grafisch ansprechend an (Abbildungen 2 und 4).
Läufer können Freunde in ihr “Team” einladen und einen Fitnesswettbewerb organisieren. Wer den eigenen Arbeitskollegen nicht auf die Nase binden möchte, dass er sich nächtelang schlaflos im Bett hin und her gewälzt hat, spart diese heiklen Informationsbissen im Bereich »Sharing« von der Publikation aus.
Offene Daten
Nun liegen die Schritt- und Schlafdaten nicht nur über die App, sondern auch in etwas roherer Form vor. Dazu nutzt das Skript in Listing 1 das CPAN-Modul WWW::Jawbone::Up und damit indirekt ein inoffizielles Web-API, das Bewegungsdaten in Perl-Skripte importiert. Mit »./uptest« auf der Linux-Kommandozeile fragt der experimentierfreudige Fitness-Enthusiast schnell mal seine bisher hochgeladenen Daten ab:
Mike Schilli walked 8.597km today Mike Schilli slept for 6h19m last night
Listing 1 zieht zu Anfang das CPAN-Modul herein und loggt sich dann mit der »connect()« -Methode in der Up-Cloud ein. Die E-Mail-Adresse und das Passwort in den Zeilen 6 und 7 ersetzt der User durch den Up-Account, den er bei dem Aktivieren seines Bandes angelegt hat. Die Methode »user()« holt die persönlichen Daten des Eingeloggten ein. Aus diesen extrahiert »name()« den registrierten Vor- und Nachnamen.
Die Methode »score()« erhält die aufbereiteten Bewegungsdaten vom Up-Server. Die in den letzten 24 Stunden vom Träger zurückgelegte Wegstrecke in Kilometern kommt mit »move()->distance()« zutage. Die Schlafdauer liefert »sleep()->asleep()« in Sekunden. Die nachfolgende Zeile teilt den Wert durch 60, erhält so die Minuten, und das CPAN-Modul DateTime::Duration errechnet daraus die vollen Stunden und überbleibenden Minuten. Bei Sekunden stellt es sich stur, da dies wegen Schaltsekunden in Sonderfällen fehlerhaft wäre.
Listing 1
uptest
01 #!/usr/local/bin/perl -w 02 use strict; 03 use WWW::Jawbone::Up; 04 use DateTime::Duration; 05 06 my $email = 'user@isp.com'; 07 my $pass = 'changeme'; 08 09 my $up = WWW::Jawbone::Up->connect( 10 $email, $pass ); 11 12 my $user = $up->user(); 13 my $score = $up->score(); 14 15 print $user->name . ' walked ' . 16 $score->move->distance . 'km today', "\n"; 17 18 my $dtd = DateTime::Duration->new( 19 minutes => $score->sleep->asleep()/60 ); 20 21 print $user->name . " slept for ", 22 $dtd->hours(), "h", int( $dtd->minutes() ), 23 "m", " last night\n";
Schön bunt
Mit der Fülle der verfügbaren Daten lassen sich nun allerhand Experimente anstellen. Ansprechende Diagramme erfordern lediglich ein Grafikpaket wie Chart::Clicker (erhältlich auf dem CPAN, Dokumentation auf [4]), das sie ohne viel Handarbeit, aber trotzdem ästethisch vollwertig generiert. Abbildung 6 zeigt zwei Graphen in einem Schaubild, lila die während der letzten 24 Stunden kumulierte Wegstrecke und gelb die in dynamisch festgelegten Intervallen gemessenen Schritte.
Um Speicherplatz im Gerät zu sparen, legt das Band Daten nämlich in unterschiedlich langen Messintervallen ab: Rührt sich lange nichts, wenn der Träger schläft oder zum Beispiel vor dem Fernseher verharrt, beträgt das Zeitfenster mit dem Zählwert für die registrierten Bewegungen schon mal eine Stunde oder mehr. In vollem Lauf hingegen schreibt der Armreif jede Minute einen Eintrag in den Speicher, der die Anzahl der Schritte festlegt. Der Up-Server schätzt daraus die zurückgelegte Strecke des Bandbesitzers, seine durchschnittliche Geschwindigkeit, die bei der Aktivität verbrannten Kalorien und die Anzahl der Sekunden, in denen der User im Zeitintervall aktiv war.
Alle Informationen greift das Skript aus Listing 2 über Methoden ab und stellt sie mit Hilfe des Chart-Pakets grafisch dar. Das Paket Chart::Clicker [4] vom CPAN malt formschöne Kurven und ist so flexibel, dass es sogar – wie Abbildung 6 zeigt – zwei Arten von Graphen in ein Schaubild packt: Die über die Zeitachse bislang zurückgelegten Meter platziert eine Render-Engine namens Chart::Clicker::Renderer::Area in eine ausgemalte Fläche (lila in Abbildung 6), die Schübe mit Step-Zählwerten zeigt die Grafik mit dünnen Bars in Gelb, ebenfalls über die Zeitachse.
Listing 2
bandchart
01 #!/usr/local/bin/perl -w
02 use strict;
03 use Chart::Clicker;
04 use Chart::Clicker::Renderer::Area;
05 use Chart::Clicker::Renderer::Bar;
06 use Chart::Clicker::Axis::DateTime;
07 use Chart::Clicker::Data::DataSet;
08 use Chart::Clicker::Data::Series;
09
10 use WWW::Jawbone::Up;
11 use DateTime::Duration;
12
13 my $email = 'user@isp.com';
14 my $pass = 'changeme';
15
16 my $up = WWW::Jawbone::Up->connect(
17 $email, $pass );
18
19 my @band = $up->band( );
20
21 my @time = ();
22 my @steps = ();
23 my @distance = ();
24 my $total = 0;
25
26 for my $band ( @band ) {
27 push @time, $band->time();
28 push @steps, $band->steps();
29
30 $total += $band->distance();
31 push @distance, $total;
32 }
33
34 my $cc = Chart::Clicker->new(
35 width => 1000, height => 800 );
36
37 my $def_ctx = $cc->get_context('default');
38
39 my $steps =
40 Chart::Clicker::Data::Series->new(
41 values => \@steps,
42 keys => \@time,
43 name => "Steps",
44 );
45
46 my $distance =
47 Chart::Clicker::Data::Series->new(
48 values => \@distance,
49 keys => \@time,
50 name => "Distance",
51 );
52
53 my $ds =
54 Chart::Clicker::Data::DataSet->new(
55 series => [ $distance ] );
56 my $ds_steps =
57 Chart::Clicker::Data::DataSet->new(
58 series => [ $steps ] );
59
60 my $steps_ctx =
61 Chart::Clicker::Context->new(
62 name => 'steps'
63 );
64 $cc->add_to_contexts( $steps_ctx );
65
66 $ds_steps->context( "steps" );
67
68 $cc->add_to_datasets( $ds );
69 $cc->add_to_datasets( $ds_steps );
70
71 my $dtaxis =
72 Chart::Clicker::Axis::DateTime->new(
73 format => "%H:%M",
74 time_zone => "America/Los_Angeles",
75 position => "bottom",
76 orientation => "horizontal"
77 );
78
79 $def_ctx->domain_axis( $dtaxis );
80 $steps_ctx->domain_axis( $dtaxis );
81
82 my $ren =
83 Chart::Clicker::Renderer::Area->new(
84 opacity => .7,
85 );
86 $ren->brush->width( 5 ) ;
87 $def_ctx->renderer( $ren );
88 $steps_ctx->renderer(
89 Chart::Clicker::Renderer::Bar->new(
90 opacity => .6, bar_width => 1 )
91 );
92
93 $cc->write_output( "chart.png" );
Alle Tage 24 Stunden auf Achse
Von Haus aus stellt Chart::Clicker Daten in Form von x-y-Koordinaten dar. Bestehen die x-Werte aus Datumsangaben in Unix-Sekunden, sorgt das Modul Chart::Clicker::Axis::DateTime dafür, dass sie als schöne Tagesdaten oder Uhrzeiten auf der x-Achse erscheinen.
Das Skript holt sich in Zeile 19 die Rohdaten des Bandes während der letzten 24 Stunden mit der Methode »band()« ab. Wahlweise ließe sich ein beliebiger Zeitraum festlegen. Zurück kommt ein Array von Einträgen, von denen jeder eine Referenz auf einen Hash enthält – unter »steps« die Anzahl der pro Zeitperiode abgespulten Schritte, unter »distance« die zurückgelegte Distanz, unter »speed« die Durchschnittsgeschwindigkeit während der Messperiode. In »time« steht der Zeitstempel, in »active_time« der Teil des Zeitfensters, in dem der User sich bewegt hat, und in »calories« die Anzahl der verbrannten Kalorien.
Mit den abgeholten Werten füllt das Skript dann drei Arrays: »@time« mit den Zeitstempeln im Unix-Format, »@steps« mit der Schrittzahl zu diesen Zeitpunkten und »@distance« mit der bis zur jeweiligen Zeit zurückgelegten Gesamtstrecke. Die Zeilen 40 und 47 erzeugen aus den Zeit-Step- beziehungsweise Zeit-Distanz-Kombinationen je eine Datenserie vom Typ Data::Series.
Ein Datensatz vom Typ Data::DataSet für einen Graphen darf in Chart::Clicker mehrere Datenserien speichern, aber die Zeilen 54 und 57 erzeugen jeweils einen Datensatz mit nur einer Serie für die zwei Graphen. Das Skript will beide verschieden darstellen, einen als Area-Graphen und den anderen als Balkengrafik, wenngleich im selben Diagramm.
Rendern im Kontext
Chart::Clicker arbeitet zum Rendern der Graphen in so genannten Kontexten, von Haus aus ist »default« eingestellt, und Zeile 37 holt das gleichnamige Objekt. Zum Darstellen des zweiten Datensatzes definiert Zeile 61 einen weiteren Kontext namens »steps« , Zeile 64 nimmt ihn ins System auf. Mit »add_to_datasets()« fügen dann die Zeilen 68 und 69 beide Datensätze zum Clicker-Objekt hinzu, und die Methode »domain_axis()« weist beiden über den Kontext die Zeitachse Axis::DateTime zu, die die x-Werte von Datenreihen als Datumsangaben interpretiert und ebenso darstellt.
Die Angabe »%H:%M« weist den Formatierer an, vom Unix-Datum jeweils nur die Stunde und die Minute in die Achse einzuzeichnen. Die Zeitzone »America/Los_Angeles« gilt beispielsweise für San Francisco und Umgebung und ist entsprechend auf die lokalen Gegebenheiten anzupassen. Der Name der Zeitzone entspricht der dem Datumsmodul zugrunde liegenden Olson-Datenbank; die Wikipedia-Seite [5] listet die Werte für Europa und den Rest der Welt auf.
Auf Abwegen
Der Zaubertrick mit den zwei Graph-Typen gelingt über den Kontext – Zeile 87 weist dem Default-Kontext den Area-Renderer zu, während der Steps-Kontext in Zeile 88 den Bar-Renderer bekommt. Der Parameter »opacity« bestimmt in beiden Fällen die Durchsichtigkeit des Graphen: Bei Werten um 0 sind die gemalten Linien und Flächen praktisch blickdicht, um 1 herum vollkommen durchsichtig.
Die grafisch aufpolierten Bewegungsdaten in Abbildung 6 enthüllen, dass ich nach der Arbeit zum nahe gelegenen Dolores-Park hinuntergelaufen bin, um einige Kilometer auf den Armreif zu spulen. Denn mit einem normalen Bürotag schafft kaum jemand die empfohlenen 10 000 Schritte. Mein abendliches Lungern vor der Glotze würdigte das Armband dagegen nicht.
Nach einer ausgiebigen Bettruhe bis 8 Uhr morgens ging ich die 500 Meter bis zur privaten Bushaltestelle des Yahoo-Shuttles in San Francisco. Untertags erhöhte sich die gemessene Laufstrecke gemächlich, während ich zwischen Meetings in unterschiedlichen Räumen oder gar Gebäuden mäanderte. Auf dem Weg von der Bushaltestelle zurück zur Wohnung ging’s den Berg rauf, und die Anzahl der zurückgelegten Schritte wuchs weiter, um am Ende des Tages etwa 10 000 zu erreichen.
Kein Band der Sympathie
Wer das Up-Band von Jawbone erwirbt, bekommt kein 100-prozentig ausgereiftes Produkt. In Diskussionsforen berichten nicht wenige Besitzer, dass ihr schlanker Armreif den Geist aufgegeben habe. Insbesondere die ersten Versionen wiesen offenbar katastrophale Fehlerraten auf, neuere arbeiten zuverlässiger, einzelne Exemplare laden gleichwohl ihre Batterie nicht richtig oder hängen sich oft auf. Dass dann der Kundenservice der Firma Jawbone nicht immer wie erhofft reagiert, flößt kein Vertrauen ein.
Eine Konkurrenz zum Up-Band bietet das schon länger auf dem Markt erhältliche Fitbit “The One” [6]. Das kleine Teil im Format eines USB-Sticks stecken Bewegte tagsüber in die Hosentasche, nachts binden sie das Gadget in einem relativ breiten Stoffband am Arm fest. (jk)
Infos
- Listings zu diesem Artikel: ftp://www.linux-magazin.de/pub/listings/magazin/2013/10/Perl
- Jawbone Up: https://jawbone.com/up
- “Jawbone UP Pedometer Teardown”, EEV Blog #412: http://www.youtube.com/watch?v=sRjHAGsl6ws
- Chart Clicker: http://gphat.github.io/chart-clicker/
- Zeitzonen in der Olson-Datenbank: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
- Fitbit: http://www.fitbit.com/de












