Wir Software Entwickler haben in der Regel viele positive Eigenschaften. Wir sind neugierig, aufgeschlossen gegenüber den modernsten Technologien, probieren gerne mal was Neues aus und haben den entsprechenden Weitblick.
Aber wir haben auch so unsere kleinen Schwächen. Vertieft im Programmieren vergessen wir oft die Welt um uns herum. Aufräumen gehört dann auch nicht unbedingt zu unseren Stärken. Dann liegt nach einer durchgearbeiteten Nacht so manches herum. Meistens in der Küche, am Kaffeeautomaten. Da verirren sich Dokumente, Bücher, Kabel und sogar Embedded Systeme zwischen mancher Kaffeebohne auf dem Küchenboden.
Ist nicht so schlimm. Wir haben ja einen Saugroboter, der regelmäßig in unseren Büros und in der Küche seine Runden dreht und alles aufsagt, was ihm vor die Bürste kommt. So eine automatische Büro-Haushaltshilfe ist doch was Tolles!
Allerdings taucht jetzt eine kleine Herausforderung auf - nicht alles was auf dem Boden liegt, soll er aufsaugen. Man stelle sich vor, unser Embedded System wird in Mitleidenschaft gezogen. Da müssen wir doch eingreifen können, notfalls auch wenn wir nicht im Büro sind!

Na klar - ein intelligenter Lichtwall, der Remote gesteuert werden kann, das ist die Lösung! Dann können wir die Küche einfach für den Roboter "absperren".
Gesagt, getan - so funktioniert das Ganze:
1. Das Signal wird auf der 38KHz Frequenz ausgestrahlt. Mithilfe der "lirc" Bibliothek können somit infrarote Signale aus dem statischen Lichtwall ausgelesen werden. Ein Raspberry Pi und zugehöriger Infrarot Empfänger helfen uns dabei, die Wellen zu lesen.
Lichtwall:

Raspberry:

2. Zufolge ist es offensichtlich, dass sich hinter den "pulse" & "space" Werten ein Muster versteckt.
Beispielcode:
space 2987 pulse 2913 space 1036 pulse 915 space 2986 pulse 918 space 2983 pulse 943 space 8805 pulse 2995 space 930 pulse 1021 ...
3. Nachdem genug Daten vorhanden sind, werden sie auf unserem Hadoop Cluster mithilfe von Spark analysiert:
Spark Code:
val rawData = ... //data case class Event(art:String, value:Integer) val cleanData: RDD[Event] = rawData.map { e => try { val tokens = e.split(" ") val event = Event(tokens(0),java.lang.Integer.valueOf(tokens(1))) event; } catch { case e: Exception => Event("",0) // ignore } } val indexedData = ... // index // get Bit Sequences for Pulses val sequences8Bits = indexedData.groupBy(_._2).map(g=> (g._1,g._2, g._2.size)).filter(t=>(t._3 == 16)).flatMap(_._2).filter(t=> t._1.art == "pulse") // org.apache.spark.rdd.RDD[(Event, Long)], Long unique ID of a bit //group bytes sequences8Bits.map(t=> { var res = if (t._1.value >1500) 1 else 0; (t._2,res) }).groupBy(_._1).map(t=> { val it = t._2.iterator; val sb = new StringBuilder(); while(it.hasNext) { sb.append(it.next._2); } (t._1, sb.toString); }).collect.foreach(println)
4. Nach genug Gruppieren, Transformieren und Mappen und Reducen bekommt man anschließend die Pattern sichtbar:
Code mit Binärsequenz:
(75988,10100010) (48388,10100010) (22948,10100010)
5. Mitunter wird für die Steuerung eine Infrarot LED Lampe und ein Arduino Board benötigt, um die "IRemote" Bibliothek erweitert.
Arduino code:
#include <IRremote.h> IRsend irsend; int khz = 38; //WALL 0xA2 -> 10100010 unsigned int irSignal[] = {3000, 1000, 1000, 3000, 3000, 1000, 1000, 3000, 1000, 3000, 1000, 3000, 3000, 1000, 1000, 3000}; irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz);
Beispiel Arduino:

6. Um die Küche kurz gesagt "on demand" zu sperren, verfügt unser Arduino über einen HTTP Server. Dazu genügt ein Sprachbefehl Shortcut über Siri, mit dem der Link für "ON" getriggert wird.
Sprachbefehl:

7. Voila! Wie der Prozess schließlich ausgeführt funktioniert, seht ihr in folgendem Video. Hinter der Küchentür steht Arduino, der Computer, der den Roboter stoppen kann.
ERGEBNIS
Das war´s! Problem gelöst - oder auch nicht, denn jetzt müssen wir allerdings die Küche wieder selbst aufräumen 🙂