Lichtwecker (Aktuell: Smartphone Anbindung)

  • Moinsen..
    ich bin schon seit längerem interessiert an einem Lichtwecker, der durch den RPi realisiert wird.
    Für alle die noch nicht wissen, was ein Lichtwecker ist:
    Ein Licht, dass ca. 30 Minuten vor dem eigentlichen Zeitpunkt, zu dem man aufstehen will, einen Sonnenaufgang im Raum simuliert. Es ist mehrfach nachgewiesen, dass dies ein entspanteres aufwachen sehr begünstigt. Daher gibts dazu auch massig fertige Geräte zu kaufen. Teils ganz schön teuer. Der hohe Preis basiert häufig auf den vielen zusätzlichen Features, wie z.b. zusätzlich mp3 abspielen, Grafikdisplay etc.. etc.. Mit einem RPi wären hier kaum Grenzen für Features gesetzt.


    Interessant fand ich immer die Idee, an meinem jetzigen verhalten nichts zu verändern und sowas dennoch zu nutzen. Sprich:
    Ich möchte meinen jetzigen Wecker auf meinem Android Smartphone "anzapfen".


    Ich habe keinen Plan von Android App Coding. Meine Kenntnisse beschränken sich auf ein paar Shellscript-Schnippsel, etwas php und google
    Daher war die Idee:
    Automatisiert die Weckzeit auslesen, und auf dem RPi abspeichern.


    Seit kurzem bin ich damit einen Schritt weiter und kann die gesetzte Alarmzeit auswerten.


    Leider kann mein Android Device kein NFC womit man die Idee ansich einfacher / effektiver umsetzen könnte.


    In meinem Fall ist das WLAN am Android Device durchgehend aktiviert.. womit dies erst ermöglicht werden konnte.. Ebenso hängt mein RPi durchgehend im Heimischen Netz. Beides zusammen ergibt eine lückenlose Kommunikation, sobald ich zuhause bin.
    Ein Szenario mit einer Adhoc-Verbindung zwischen Android und dem RPi um unabhängig von anderen Netzen sein zu können, wird sicherlich technisch ohne weiteres Möglich sein, ist hier aber kein Thema.


    App Development erlernen ist mir für dieses Projekt eine Hausnummer zu viel.. das gibt meine Zeit einfach nicht her..


    ########
    # Android #
    ########


    Ziele:

    • Simple Lösung ohne großen Aufwand
    • Möglichst mit Boardmitteln arbeiten können damit Szenario von vielen nachspielbar ist


    Mit etwas google und etwas frickeln konnte ich das ganze für das Android-Device auf ein Minimum reduzieren:
    Es wird auf einem gerooteten Android die APP cron4phone und eine einzige Codezeile benötigt. Die App führt die Codezeile im eingestellten Intervall aus. Das war alles, was man auf dem Android Device erledigen muss.


    Hier die Codezeile:

    Code
    r=$(eval sqlite3 -column /data/data/com.android.providers.settings/databases/settings.db \'select value from system where name = \"next_alarm_formatted\"\') ; wget "0.0.0.0/test.php?p=passwqrd&t=$r"


    zur Erklärung:
    Das Programm "sqlite3" liest eine bestimmte Datenbank aus, in der der gesuchte Wert (die nächste Alarmzeit) steht. Anschließend wird dieser Wert in eine Variable "r" gepackt. Danach wird das Programm "wget" genutzt um einen Link zu einer Website zu öffnen und hier gleich ein paar Parameter mitzugeben.
    0.0.0.0 ist hierbei der Webserver (musst du anpassen auf die IP deines Webservers/RPi)
    test.php die passende php Datei an die die Parameter übergeben werden sollen
    Parameter p = ein selbst gewähltes passwort
    Parameter t = wird mit der Variable "r" verknüpft. Das heißt, der Inhalt der Variable (und damit die nächste Alarmzeit) wird hier eingesetzt.


    Damit ist die Arbeit auf dem Android-Device komplett erledigt.
    gehen wir also nun zum RPi um die Daten dort entgegen zu nehmen.. auszuwerten.. und dann entsprechend zu handeln.


    #####
    # RPi #
    #####


    Auf dem RPi rennt ein Webserver (ich nutze z.B. nginx), der die oben erwähnte Datei test.php bereitstellt. Dieses PHP-Script nimmt diese Werte (passwort und Alarmzeit) entgegen und wandelt die Alarmzeit in Unixzeit um.
    Ich habe mich für die Unixzeit entschieden, weil man mit ihr als einfache Zahl viel einfacher weiterarbeiten kann. Danach schreibt das PHP-Script jeweils in eine neue Zeile für die weitere Verarbeitung in eine Text-Datei namens test.txt folgendes:

    • die Weckzeit als Unixzeit
    • dass Passwort
    • die akutelle Zeit (ebenfalls als Unixzeit)


    Sollte keine Alarmzeit am Android Device existieren konnte auch keine Alarmzeit an das PHP-Script weitergegeben werden. Das PHP-Script stellt dies fest und schreibt stattdessen eine definierte "Fake-Zeit" (z.B. 999999999 was für 09.09.2001 - 03:46:39 steht) in die test.txt und macht dennoch ein Update in Zeile drei.


    damit wäre die test.php komplett fertig mit ihren Aufgaben.


    Info zu den Werten die in die test.txt geschrieben werden:
    Diese "Fake-Zeit" dient dazu einen klaren definierten Zustand zu haben, den wir entsprechend auswerten können. Denn ein einfaches "keine Zeit angekommen" könnte auch bedeuten, dass das Handy garnicht im WLAN ist, weil ich z.B. gerade woanders übernachte.
    Und genau aus diesem Grund schreiben wir auch in die letzte Zeile die aktuelle Uhrzeit für den Zeitpunkt als das Android Device diese Daten übermittelt hat.
    Wenn wir beim Auslesen diese Zeit mit dem Zeitpunkt vergleichen, wärend wir auslesen, können wir so genau feststellen, wie lange es her ist, als das Android Device das letzte mal ein Update geschickt hat. Da das Android Device dies alle 5 Minuten tun soll, würden wir hiermit einen klar definierten Wert erhalten, ob das Android Device aus/defekt/nicht anwesend ist. wir gehen einfach mal davon aus, dass das Android Device / und oder das Netzwerk nicht über Nacht kaputt gehen =)
    Für den Fall, dass das Android Device runtergefahren wurde, können wir mit der oben genannten APP und einer weiteren Codezeile dies dem RPi mitteilen (to be done!)
    Bleibt also bei dem Zustand, dass das letzte Update länger als 5 Minuten her ist, nur die Möglichkeit übrig, dass das Android-Device nichtmehr anwesend ist.. und kein Alarm mehr benötigt wird.


    Somit können wir unterscheiden zwischen:

    • Alarm ist gesetzt
    • Kein Alarm ist gesetzt
    • Android Device ist runtergefahren (to be done!)
    • Android Device ist nicht in der nähe


    ####


    nun haben wir die Werte die wir benötigen in einer dreizeiligen Textdatei gespeichert und diese wollen ausgewertet werden.
    Sinnvoll ist es, dies automatisch geschehen zu lassen. Und zwar in einem Intervall, welches größer ist, als das vorherige. Wenn wir 15 oder 20 Minuten nehmen, haben wir garantiert, dass mehrere durchgänge zum abspeichern der Werte in die test.txt schon geschehen sind.
    Als erstes prüfen wir, ob unsere Fakezeit gesetzt ist. Wenn ja, wird kein Alarm gesetzt und wir sind fertig bis zum nächsten Durchgang.
    Wenn nicht die Fakezeit gesetzt wurde, muss dort eine reale Alarmzeit stehen.
    Als nächstes prüfen wir, ob die Zeit in Zeile drei länger als z.B. 15 Minuten zurückliegt. Damit stellen wir fest, ob schon mehrere Intervalle kein Update vom Android-Device angekommen ist und können auch hier an dieser Stelle aussteigen und einen eventuellen Alarm deaktivieren, denn dies bedeutet ja, wir sind nicht im Heimnetz und damit nicht anwesend.
    Gab es doch Intervalle, wird die Zeit aus Zeile 1 genommen und von ihr z.B. 30 Minuten (der Zeitraum wie lange der Lichtwecker den Sonnenaufgang vorher starten soll) abgezogen. Damit haben wir die Startzeit für unseren Lichtwecker ermittelt.


    Da wir diese Startzeit nicht irgendwo abspeichern und ihrem Schicksal überlassen können, müssen wir bei jedem Aufruf dieses PHP-Scriptes eine erneute Prüfung auf alle Begebenheiten starten. Denn ansonsten geht uns vieleicht die Information verloren, dass der Alarm nachträglich deaktiviert oder die Alarmzeit verändert wurde.


    Meine Lösung dafür geht von hinten durchs Auge. Anstatt die genaue Startzeit auch zum starten zu nutzen, wird überprüft ob die Zeit zwischen der Startzeit und der aktuellen Zeit kleiner oder größer ist, als das Intervall der Überprüfung selbst. Wenn nicht, passiert nichts weiter. Sollte die Zahl kleiner sein, stehen wir im letzten Intervall vor der eigentlichen Startzeit und können den Licktwecker starten.
    Ich würde behaupten, bei einem Lichtwecker kommt es nicht auf wenige Minuten an. Und wir können so Extra-Code um z.B. einen Cronjob zu schreiben und diesen gegebenfalls wieder zu löschen, etc.. vermeiden.


    Durch weitere simple Mathematik ist es auch möglich, den Lichtwecker nach einer selbst festgelegten Zeit automatisch zu deaktivieren (z.b. 20 minuten nach der eigentlichen Weckzeit (also in dem Rechenbeispiel 50 Minuten nach der Startzeit)).


    Den entsprechenden Code habe ich unten unter "test2.php" stehen.. er ist nicht ausgereift.. und sicherlich zu verbessern.. es ist nur eine Momentaufnahme.. ich Bastel da noch weiter..


    Jetzt bleibt nur die Frage, ob mein Ansatz/meine Idee am Ende überhaupt praktikabel ist.
    Das ganze habe ich bisher nur auf meinem Motorola Moto G mit Cyanogenmod testen können.
    Vieleicht hat ja wer Zeit und Lust das ganze mit seinem gerooteten Android Device zu verifizieren?


    todo:
    (Stand 2014.11.15_01:40)

    • Abfrage Passwort
    • Codezeile bei Ausschalten des Android Device (+ Verarbeitung nach Auswertung)
    • Schaltung für Sonnenaufgang (z.B. RGB-LED Strip oder TIP142 + 12V halogen)
    • LED zu Anzeige ob "scharf geschaltet" und/oder Taster zur Aktivierung eines Displays
    • mp3 Ausgabe wärend Sonnenaufgang (z.B. leichtes Meeresrauschen oder entferntes Vogelgezwitscher, etc..)
    • Eventuell Display zur Anzeige von Daten wie z.B. Wetterprognose, Uhrzeit, whatever (dafü liegt hier noch ein Pearl DPF)
    • Lösung finden was passieren soll bei snooze (wie erkennen, dass snooze?)


    #### Update: 2014_11_12 23:20 Uhr


    test.php


    test2.php

    Edited once, last by demlak ().

  • Hab den Text oben komplett überarbeitet. ich habe eine Lösung fertig, die ich erstmal als nahezu vollständig und lückenlos betrachte. Das ganze habe ich nun ausführlich/detailiert Beschrieben.
    Ich hab bestimmt irgendeinen Gedankengang nicht gut "zu Papier gebracht".. daher bitte Kritik an mich, wenn irgendwas nicht verständlich geschrieben wurde oder sogar in der erklärung ausgelassen wurde.. und wie gesagt, ich würd mich über ein wenig Brainstorming freuen.

  • Sorry, totaler Noob, aber trotzdem mal eine vermutlich dumme Frage...


    Wie rufst du denn deine test2.php auf?
    Durch ein Script das die Datei alle paar Sekunden aufruft? Falls ja, dann führt es ja wohl auch deine Befehle jedes mal beim Call der PHP Datei aus, was in deinem Fall aber nicht weiter schlimm sein sollte...


    Ansonsten hab ich mir mal ein paar Zeilen von deinem Code "geklaut" und ein bisschen abgewandelt.
    Habe mir die Android Wecker Funktion mal durch eine Website mit Date/Timepicker ersetzt.


    Aber vielen Dank auf jeden Fall für deine Mühe, sieht sehr durchdacht und sauber aus.
    Ich hoffe du bleibst dran an der Sache!


  • Wie rufst du denn deine test2.php auf?
    Durch ein Script das die Datei alle paar Sekunden aufruft? Falls ja, dann führt es ja wohl auch deine Befehle jedes mal beim Call der PHP Datei aus, was in deinem Fall aber nicht weiter schlimm sein sollte...


    die datei wird dann per cronjob auf dem RPi aufgerufen.. in einem zu bestimmenden intervall.. ich denke einmal pro minute ist vollkommen ausreichend.. da bei einem lichtwecker kein sekundengenauer start notwendig ist.



    Ansonsten hab ich mir mal ein paar Zeilen von deinem Code "geklaut" und ein bisschen abgewandelt.


    macht überhauptnix, wenn du mich dafür im quellcode erwähnst =)


    Habe mir die Android Wecker Funktion mal durch eine Website mit Date/Timepicker ersetzt.


    was genau meinst du mit date/timepicker?


    Aber vielen Dank auf jeden Fall für deine Mühe, sieht sehr durchdacht und sauber aus.
    Ich hoffe du bleibst dran an der Sache!


    sauber ist sicherlich was anderes.. aber ich bleib dran =)

  • OK, du rufst die 2.php also per cronjob auf. Das heißt, falls ich damit jetzt zum Beispiel eine für einen Weckton eine MP3 aufrufen will, wird diese auch jede Minute aufgerufen. OK, dass müsste man evtl. noch abfangen, durch voriges checken ob der Prozess bereits läuft...
    _____________________


    Den Quellcode bekommt außer mir niemand zu Gesicht, also kein Problem ;)


    _____________________


    Ich habe mir nur eine kleine Seite gebastelt, in der ich quasi den Wecker setze (als Ersatz für deine Android Lösung).


    Datepickers
    _____________________


    Ansonsten werde ich wohl noch eine Webseite erstellen, die die aktuelle Uhrzeit, das Datum, die Alarmzeit, und noch ein Icon, das signalisiert ob der Wecker an oder aus ist anzeigt.


    Zusätzlich werde ich wohl noch sowas in der Art auf meiner Weckzeit-Einstellungs-Seite hinzufügen, damit ich mir den Weckton auswählen kann.

  • dafür ist eigentlich der check ganz unten.. es wird gecheckt ob die 30 minuten vor der weckzeit schon angefangen haben oder nicht.. etc..


    aber ich hab mir da auch nochmal gedanken zur logik gemacht.. der code da oben ist erstmal nur spielerei..


    folgendes ist gerade in den letzten bereichen ganz unten noch noch fertig ausgereift.. irgendwie fehlt da noch was..


  • Ich hab mich mal drangesetzt, wie ich am besten das Licht des RGB Streifens fade.. die kennlinie des menschlichen auges ist ja nicht linear.. und ich denke, ich werde aber linear faden.. daher hab ich mir die Berechnungsformel aus diesem Demoprogramm geschnapt und in php umgesetzt.. hinzugefügt hab ich noch, dass man jeden Farbkanal einzeln berechnen kann.. so dass am Ende eine php-Funktion dabei rauskam, mit der eine RGB Zahlenreihe generiert werden kann, durch die durchgefaded wird.. und das nicht nur von schwarz zu weiß.. sondern schwarz zu jeder x-beliebigen Farbe.. in meinem Fall scheint es so, als wenn ich bis hin zu RGB 255,122,0 faden lassen werde..



    die funktionsweise ist recht simpel..
    z.b. pwm von 0 bis 255 in z.b. 900 schritten für schwarz bis 255,122,0...
    Aufruf im browser mit:

    Code
    calc.php?M=255&S=900&F=1.1&R=255&G=122&B=65


    hier das php script:


    UPDATE 2014_12_03 : 17:07
    habs jetzt so gebastelt, dass es auch gleich den fade ausführt.. und es klappt sowohl von der commandozeile.. als auch aus dem browser heraus..
    UPDATE 2014_12_04: 03:24
    Jetzt ist auch ein check drin, ob bereits ein fade im gange ist, oder nicht
    Und egal was berechnet wird, pausen zwischen den einzelnen steps gibts erst, wenn mindestens ein Kanel mehr als den Wert 0 zugewiesen bekommt

    Edited once, last by demlak ().