Dies ist der Bericht über ein privates Projekt von Jo. Das Ergebnis schaltet eine Glühbirne/Lampe in unserem Büro an sobald jemand unsere Webseite aufruft. Dadurch erhalten wir einen physischen Besuch, visualisiert durch ein warmes Licht.
Die Idee
Die Idee war simpel: welche Möglichkeiten haben wir, dass uns ein Besucher unserer Webseite im Büro angezeigt wird. Neben Business-Dashboards die uns sogar die gesamte Webstatistik auf dem Monitor zeigen würden, müsste es doch eine charmantere Idee geben. Vielleicht wichtig: ich bin kein gelernter Programmierer, ich bin Gestalter und gestalte Dinge – aber technische Spielereien haben für mich einen unwahrscheinlichen Reiz. 🙂 Zudem bin ich der festen Überzeugung, dass die Arbeit als Gestalter nicht auf das grafische Gestalten begrenzt sein darf. Es ist toll Dinge zu erstellen, die in der Welt um uns herum gesehen werden und Reaktionen erzeugen. So gesehen ist das Projekt für mich ein Gestaltungsprojekt.
Und tatsächlich wurde ich schnell fündig und habe mir unter anderem dieses Projekt genauer angeschaut:
Dabei war das eigentlich genau die Art der Umsetzung die mir vorschwebte. Jedesmal wenn ein Besucher auf den Blog kam wurde (passend zur Weihnachtszeit) die Glocke geläutet. Das kann zugegebenermaßen irgendwann sehr auf die Nerven gehen – vor allem im Büroalltag. Mein Wunsch, eine Glühbirne zum Leuchten zu bringen, kam mir aber mit diesen Tutorial umsetzbar vor.
Ausgangslage / Adaption
Der Unterschied meiner Ausgangsposition zum XMAS hintcounter kam mir kleiner vor als ich dachte. Es wird über ein simples PHP-Script eine Text-Datei erstellt bzw. in ihr wird ein numerischer Wert bei jedem Aufruf des Scripts, um die Zahl 1 erhöht. Irgendwo auf dem Webserver liegt also eine Textdatei, welche lediglich eine Zahl enthält. Das war mit der Anleitung schnell umgesetzt und funktionierte prächtig. Nur was mache ich jetzt mit dieser Zahl?
Alex von tinkerlog geht nun den Weg über ein Python-Script das auf seinem Rechner läuft und die Berechnung der tatsächlichen Website-Hits per Serial-Port an das Arduino-Board weiter gibt.
Neues Spielzeug! #arduinouno #ethernet #schaumama
Ein von Jo (@_der_jo) gepostetes Foto am
Ich wollte aber eine Stand-Alone-Lösung bauen, also eine Art Ding, das an das Stromnetz und Netzwerk angeschlossen wird und das keinen weiteren Host benötigt. Nach einiger Recherche habe ich mich auf folgende Bauteile festgelegt: ich nutze das Arduni Uno, ein Ethernetshield und ein 230V-Relais zum späteren Schalten der Lampe. Das bedeutete ich musste mir darüber Gedanken machen wie ich den Umweg über das Python-Script sparen kann, also eine direkte Abfrage der Zahl über das Ethernetshield auf dem Arduino hinbekomme. Dazu habe ich eine Menge Beispiele gefunden, hier ein paar Recherche-Links welche mich dem Ergebnis näher brachten:
Reading Text Files with Processing
Der erste Erfolg
Nach einigem Probieren und Verwerfen gelang es mir eine Ausgabe der Textdatei im SerialMonitor zu erhalten. Diese war allerdings sehr kryptisch und enthielt den gesamten Header der Textdatei und die Verbindungsdaten. Nach erneuter Recherche lernte ich, dass ich diesen sekündlichen Informationsschwall „parsen“ musste, um daraus die einzig wichtige Information zu filtern: die aktuelle Hitcounter-Zahl. Ich habe dazu ein Beispiel gefunden, welches es mir ermöglicht einfach nur eine bestimmte Zeile aus dem SerialOutput zu erfassen (also nur die Zeile in der die Zahl steht) und den Rest zu ignorieren. Sicherlich nicht die sauberste Lösung aber ich wollte schnell einen working prototype erstellen.
Nachdem mir das gelungen war saß ich um ehrlich zu sein mindestens 15 Minuten stolz vor dem SerialMonitor und beobachtete das Ankommen einer Zahl, welche ich durch den Aufruf der Webseite erhöhen konnte: 132…133…134…135… cool! 🙂
Im nächsten Schritt soll es also gelingen diese Zahl in eine Variable zu übergeben und dann sekündlich die neue Zahl abzufragen. Damit dann eine einfache Rechnung „neue Zahl minus alte Zahl = Delta“ und „ist Delta ≥ 1 dann tu was“.
finally! i get a #led light when you visit my website #justintime 🙂 #arduino #ethernet
Ein von Jo (@_der_jo) gepostetes Video am
Finalisierung
Nachdem diese Schritte geschafft waren leuchtete schon einmal eine LED am Arduino. Diese sollte nun ersetzt werden durch ein 230V Relais. Auch dafür habe ich ein Tutorial gefunden und ich weise ausdrücklich darauf hin, dass die Bastelei mit 230V-Spannung sicherlich kein argloses Unterfangen ist und ich mir der möglichen Gefahr durchaus bewusst war. Bitte nicht nachmachen und so!
Beispiel zur Schaltung Arduino und 230V Relais
Das Ergebnis
Für mich war es ein spannendes Experiment und es hat neben dem befriedigenden Gefühl es geschafft zu haben auch einen nachhaltigen Effekt: Besucher im Büro wundern sich nun über diese Ecklampe die immer nur kurz an und direkt wieder aus geht. Die Erklärung überrascht die meisten dann doch etwas. Wir haben uns schon daran gewöhnt und es ist wirklich interessant auf diese Art die Peak-Zeiten unseres Webtraffics angezeigt zu bekommen. Es ist wesentlich spannender als abends mal auf Googles Analytics-Seite vorbeizuschauen!
Alice, unsere Praktikantin, am Tag des ersten Testlaufs:
„Geht die jetzt den ganzen Tag an und wieder aus?“
Jo: „Ja! Geil oder?“
Hier nun der finale Code. Sicherlich geht das besser, schlanker, sinnvoller – wie ganz oben schon beschrieben befasse ich mich maximal mit HTML und CSS. Das alles war also komplettes Neuland für mich. Ich hoffe dem ein oder anderen ist es eine Inspiration oder sogar Hilfestellung.
Ich übernehme keine Haftung oder Verantwortung für Fehler, falsche Auslegung oder falsches Kommentieren 🙂
/* Date: 11.03.2016 author: @_der_jo based on different tutorials and examples:Arduino XMAS hitcounterHow to Download and Use Online Data with Arduinohttps://bildr.org/2011/06/arduino-ethernet-client/ https://playground.arduino.cc/Code/WebClient230V Relais schalten mit Arduino und Apple RemoteDescription: Sketch to read txt file from webserver which contains counted hits (hits counted by php file to text file) and calculate delta to old count. Light LEDif delta is > 0 Basis: zoomkat 12-22-10 and Webclient Sketch Posted November 2012 by SurferTim */ #include <SPI.h> #include <Ethernet.h> String readString, readString1; int x=0; int i = 0; //newhits int d = 0; //delta int o = 0; //oldhits char lf=10; char hits[10]; char newhits[10]; //LED einrichten const int relayPin = 5; int relayState = LOW; //const int ledPin = 8; // Nummer LED-Pin- 10-13 belegt //int ledState = LOW; // LED auf AUS schalten byte mac[] = { 0xB0, 0xC0, 0xDE, 0xEF, 0xFE, 0xC7 }; //Mac-Adresse des Ehternet shields char serverName[] = "www.jos-buero.de/jos2016"; //Server URL int serverPort = 80; // Server Port char pageName[] = "/counterlog.txt"; // Pfad zur Datei EthernetClient client; int totalCount = 0; // insure params is big enough to hold your variables char params[32]; // set this to the number of milliseconds delay // this is 30 seconds #define delayMillis 5000UL unsigned long thisMillis = 0; unsigned long lastMillis = 0; void setup() { // pinMode(ledPin, OUTPUT); pinMode(relayPin, OUTPUT); Serial.begin(9600); // disable SD SPI pinMode(4,OUTPUT); digitalWrite(4,HIGH); //Serial.print(F("Starting ethernet...")); if(!Ethernet.begin(mac)) Serial.println(F("failed")); //else Serial.println(Ethernet.localIP()); delay(2000); //Serial.println(F("Ready")); } void loop() { // If using a static IP, comment out the next line Ethernet.maintain(); thisMillis = millis(); if(thisMillis - lastMillis > delayMillis) { lastMillis = thisMillis; // params must be url encoded. sprintf(params,"temp1=%i",totalCount); if(!postPage(serverName,serverPort,pageName,params)) Serial.print(F("Fail ")); //else Serial.print(F("Pass ")); // versuch der rechnung von unten kommen die newhits totalCount++; //Serial.println(totalCount,DEC); } } byte postPage(char* domainBuffer,int thisPort,char* page,char* thisData) { int inChar; char outBuf[64]; //Serial.print(F("connecting...")); if(client.connect(domainBuffer,thisPort) == 1) { //Serial.println(F("connected")); // send the header sprintf(outBuf,"POST %s HTTP/1.1",page); client.println(outBuf); sprintf(outBuf,"Host: %s",domainBuffer); client.println(outBuf); client.println(F("Connection: closernContent-Type: application/x-www-form-urlencoded")); sprintf(outBuf,"Content-Length: %urn",strlen(thisData)); client.println(outBuf); // send the body (variables) client.print(thisData); } else { Serial.println(F("failed")); return 0; } while(client.connected()) { while(client.available()) { char c = client.read(); //Serial.print(c); // auskommentieren um gesamten Stream der gelesenen Datei zu sehen if (c==lf) x=(x+1); if (x==10) readString += c; // Zeile des Streams auswählen die in string gelesen werden soll } if (!client.connected()) { client.stop(); //Serial.print(readString); Serial.print("oldhits:"); Serial.print(o); readString.toCharArray(newhits, 10); //string zu charArray hinzufügen int i = atoi(newhits); // carhArray zu variable Serial.print("newhits:"); Serial.print(i); int d = i-o; // delta aus old und newhits berechnen Serial.print("delta:"); Serial.print(d); // LED variable auf AN setzen wenn delta vorhanden if (d > 0) { relayState = LOW; // ledState = HIGH; // sonst LED variable ausschalten } else { relayState = HIGH; // ledState = LOW; } // zuvor gesetzter State in definierten LED-Pin schreiben digitalWrite(relayPin, relayState); // digitalWrite(ledPin, ledState); // variable oldhits mit newhits füllen o=i; } // delta wieder auf null setzen d=0; } // zeilen der gelesenen Datei zurücksetzen(?) x=0; // string leeren readString = ""; relayState = LOW; client.stop(); return 1; }