Wetterstation

Jeder kennt diese Wetterstationen mit Anzeige fuer Innen- und Aussentemperatur, Uhrzeit, Luftdruck und was man sonst noch so messen kann. Sowas will ich auch haben – aber gefuettert mit den Daten aus openhab. Ebenso wie diese Wetterstationen soll das Ding moeglichst mit einer Batterie auskommen. Daher habe ich mir als Anzeige E-paper vorgestellt. So suche ich schon seit Monaten ein E-pager Display, welches sich per Wifi mit Daten fuettern laesst. leider waren die diversen Projekte, welche ich bisher gefunden habe, viel zu komplex fuer meine beschaenkten Faehigkeiten.

Da kam dann Anfang des Jahres der c’t Artikel zum digitalen Tuerschild genau richtig. Das Display kann man in Deutschland kaufen, den esp32 habe ich mir aus China besorgt (gleich in einer Variante mit Batteriefach). Als Rahmen habe ich erstmal eine “BÅS Vitrinekistj” genommen, da passt alles einfach rein, auch wenn es nicht besonders schoen aussieht. Das Ganze war schnell aufgebaut. Wieder Erwarten funktionierten alle Loetstellen auf Anhieb, dafuer von der Software fast gar nichts. Es hat eine Weile gedauert bis ich gemerkt habe, dass es im Source-Code diverse Stellen mit Kommentaren der Art “hier aendern je nach php-Version” oder “hier anpassen je nach Display-Groesse’ gibt. Irgendwann ging es dann. Auf dem esp32 laeuft ein Programm, welches sich einfach das rohe Bild (also 640*384 bits entsprechend 30720 bytes) per http und wifi vom Server holt.

Damit brauche ich nur noch auf dem Server ein Bild mit Daten aus dem openhab generieren, den Rest vom c’t-Projekt kann ich direkt nutzen.

Leider enthaelt das c’t Projekt keinen Code, um das rohe Bild zu testen. Das kann aber schnell selber gebaut werden: da der esp32 es per http abholt, kann man es sich quasi im Browser anschauen. Dafuer braucht es nur ein paar Zeilen Javascript, die die Rohdaten in ein html5 canvas malen. Das ist ganz praktisch, wenn man das Bild selber generiert:

<!DOCTYPE html >
<html>
        <head>
                <meta charset="UTF-8">
                <script>
function loadImage(tb) {
        console.log("loading image from "+tb.value);
        var xhr = new XMLHttpRequest();
        xhr.onload = function(e) {
                var buffer = xhr.response;
                if (buffer) {
                        var byteArray = new Uint8Array(buffer);
                        var c = document.getElementById("bild");
                        var ctx = c.getContext("2d");
                        ctx.moveTo(0,0);
                        ctx.clearRect(0,0,c.width,c.height);
                        var x = 0, y = 0;

                        for (var i=0; i<byteArray.byteLength;i++) { 
                                var v = byteArray[i];
                                for (var j = 0; j < 8; ++j ) {
                                        var bit = (v & (1 << (7-j)));
                                        if (bit) {
                                                ctx.fillRect(x,y,1,1);
                                        }
                                        x = x + 1;
                                        if (x >= 640) {
                                                x = 0;
                                                y = y + 1;
                                        }
                                }
                        }
                        tb.readOnly = false;
                }
        };
        xhr.open('GET', tb.value, 'true')
                xhr.responseType = 'arraybuffer'
                xhr.send(null);
}

function keyEvent(event) {
        var tb = document.getElementsByName("urlinput")[0]
                if (event.keyCode === 13) {
                        tb.readOnly = true;
                        loadImage(tb);
                }
}
                </script>
        </head>
        <body>
                URL: <input type="text" name="urlinput" size="100" value="/server/openhab.raw"
                                                     onkeyup="keyEvent(event)"><br>
                <canvas id="bild" width="640" height="384"></canvas>
        </body>
</html>

Laeuft bei mir in Chrome und Firefox.

Das sieht dann in etwas so aus:




Gewinnt sicher keinen Designpreis, funktioniert aber gut.

Um die Daten aus dem openhab zu generieren, gibt es fuer den Anfang einen recht einfachen Weg:

  1. bauen wir uns eine passende Sitemap, egal ob classic oder habpanel oder wie auch immer, Hauptsache wir haben eine Website mit allen Daten
  2. holen wir uns diese Seite als Bild: firefox -screenshot http://.../basicui/app -P screenshots (ein eigenes Profile fuer Batch ist immer gut, damit es keine Konflikte gibt mit laufenden Instanzen vom Firefox)
  3. passen wir das entsprechende Bild in der Groesse an: convert screenshot.png -resize 640x384\! small-screenshot.png
  4. konvertieren wir das Bild in pbm: convert small-screenshot.png small-screenshot.pbm (pbm gibt es als binary und als ascii, wir brauchen ersteres, das ist der default)
  5. schneiden wir den bpm-Header ab: tail -n +3 small-screenshot.pbm > small-screenshot.raw (bpm ist naemlich genau unser rohes Format, nur mit ein paar Zeilen Metadaten vorweg)

Das kann man einfach in ein cgi giessen und loslegen. Das Ergebnis sieht schon ganz gut aus:



Im naechsten Schritt muss ich jetzt die Anzeige etwas aufhuebschen. Das ist nicht so meine Staerke. Die Sitemap ist dafuer nicht so optimal geeignet. Im naechsten Schritt wird es also darum gehen, ein bisschen was zu programmieren, das sich Daten aus dem openhab holt (und vielleicht noch ein paar Wetternachrichten), das alles nett in ein Bild packt und zur Abholung bereitstellt.