Der Kurznachrichtendienst Twitter erlaubt mithilfe einer API das automatische Erstellen von Nachrichten.(Seit dem 20.09.2016 sind mehr als 140 Zeichen erlaubt)
In diesem Tutorial möchte ich erläutern, wie ein NodeMCU Arduino Clone mit einem Twitteraccount verbunden wird und automatisch Sensorwerte pusht. Dazu werde ich die Sensordaten per WLAN an einen Server im Internet mit HTTP GET senden und diese mithilfe von PHP als Twitternachricht über den Account DraegerITSensor erstellen.
Ziel
Das Ziel dieses Projektes soll es sein, dass Sensordaten (Temperatur, Lichtstärke, Luftfeuchtigkeit usw.) als Twitternachricht bereitgestellt werden.
Vorbedingungen
Als Vorbedingung wird gegeben, dass ein Twitteraccount und ein Server mit PHP (min. Version 5.4) existiert und der Zugriff eingerichtet ist.
Des Weiteren wird ein NodeMCU Arduino Clone und Sensoren benötigt.
Den Mikrocontroller NodeMCU habe ich im Tutorial NodeMCU – “Einer für (fast) Alles!” ausgiebig erklärt.
UserStories
Das Projekt wird in 5 Meilensteine untergliedert, wobei jeder Meilenstein aus einer oder mehreren UserStories besteht. Beim Erreichen eines Meilensteins ist jeweils ein lauffähiges Produktincrement vorhanden, welches einen Mehrwert zum vorherigen bietet.
Meilenstein 1 – Sensordaten auf einer Webseite darstellen (intern)
US 1.1 – Sensordaten aufnehmen und ablegen
Aufgabe: Es sollen Sensordaten aufgenommen und intern abgespeichert werden.
Als Ausgangsbasis nutze ich das Sketch aus dem Tutorial Arduino Lektion 29: DHT22 Sensor jedoch wird nur der Teil mit dem DHT11 Sensor benötigt.
Speichern der Daten in einer Struktur
Folgende Lösung habe ich vom Arbeitskollegen Udo K. erhalten und finde diese deutlich besser als mit einem mehrdimensionalen Array.
Es gibt nun eine Struktur / Objekt welches folgende Eigenschaften hat:
- id,
- temperatur,
- luftfeuchtigkeit,
- timestamp
Als Datentyp habe ich hier “unsigned” gewählt da der DHT11 Sensor nur positive Werte ausgibt und die Zeit auch nicht negativ sein kann. Dieses hat den positiven Nebeneffekt, dass Speicher auf dem Gerät gespart wird.
struct Entry { unsigned int id; unsigned int temperatur; unsigned int luftfeuchtigkeit; unsigned long timestamp; }; const int MAX_ENTRIES = 200; Entry entries[MAX_ENTRIES]; int counter = 0;
US 1.2 – Interne Webseite erstellen
Aufgabe: Es soll eine Webseite erzeugt werden, welche von jedem beliebigen Computer im selben Netzwerk aufgerufen werden kann.
Dazu verwende ich als Grundlage das Beispiel welches zur ESP8266 Bibliothek mitgeliefert wird.
US 1.3 – Daten auf der Internen Webseite anzeigen
Aufgabe: Es sollen die aus der UserStorie 1.1 gespeicherten Daten in der Webseite tabellarisch angezeigt werden.
#include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #include "DHT.h" #define DHT11PIN 0 #define DHT11TYPE DHT11 DHT dht11(DHT11PIN, DHT11TYPE); const char* ssid = "xyz"; const char* password = "xyz"; struct Entry { unsigned int id; unsigned int temperatur; unsigned int luftfeuchtigkeit; unsigned long timestamp; }; const int MAX_ENTRIES = 200; const int PAUSE = 5000; unsigned long lastAction = -1L; Entry entries[MAX_ENTRIES]; int counter = -1; ESP8266WebServer server(80); const int led = 13; void handleRoot() { digitalWrite(led, 1); server.send(200, "text/html", getStoredData()); digitalWrite(led, 0); } Entry getCurrentDht11EntryData(){ unsigned int humidy = dht11.readHumidity(); //relative Luftfeuchtigkeit vom Sensor DHT11 lesen unsigned int temp = dht11.readTemperature(); //Temperatur vom Sensor DHT11 lesen unsigned long currentTime = millis(); return {counter, temp, humidy, currentTime}; } String getStoredData(){ String result = "<html><body><table border='1'>"; result += "<thead>"; result += "<tr>"; result += "<th>ID</th>"; result += "<th>Luftfeuchtigkeit</th>"; result += "<th>Temperatur</th>"; result += "<th>Zeit</th>"; result += "</tr>"; result += "</thead>"; result += "<tbody>"; for(int i=0;i<counter;i++){ Entry e = entries[i]; result += "<tr>"; result += "<td>"; result += String(e.id,DEC); result += "</td>"; result += "<td>"; result += String(e.temperatur,DEC); result += "°C"; result += "</td>"; result += "<td>"; result += String(e.luftfeuchtigkeit,DEC); result += "%"; result += "</td>"; result += "<td>"; result += String(e.timestamp,DEC); result += "</td>"; result += "</tr>"; } result += "</tbody>"; result += "</table></body></html>"; return result; } void handleNotFound(){ digitalWrite(led, 1); String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET)?"GET":"POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i=0; i<server.args(); i++){ message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); digitalWrite(led, 0); } void setup(){ Serial.begin(115200); delay(25); dht11.begin(); pinMode(led, OUTPUT); digitalWrite(led, 0); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.println(""); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); } server.on("/", handleRoot); server.on("/inline", [](){ server.send(200, "text/plain", "this works as well"); }); server.onNotFound(handleNotFound); server.begin(); Serial.println("HTTP server started"); } void loop(void){ server.handleClient(); unsigned long currentTimeMillis = millis(); if((lastAction+PAUSE)<currentTimeMillis){ lastAction = currentTimeMillis; if((counter+1) >MAX_ENTRIES){ counter = -1; } entries[++counter] = getCurrentDht11EntryData(); } }