Das Ende. Der vorherige Teil .
Inhaltsverzeichnis:
Außenborder Sensor. Software
Sprechen Sie über die Software für den Übersee-Sensor. Danach erhalten Sie ein komplettes System, mit dem Sie bereits experimentieren können.
Ich möchte Sie daran erinnern, dass der Server eine zentrale Heimeinheit ist, die über WLAN mit dem Internet kommunizieren kann, und der Client ein sofort einsatzbereiter Remote-Sensor ist, der Daten drahtlos an den Server überträgt.
Der Quellcode für den Server und den Client ist hier .
Die Ausgangstexte werden mit detaillierten Kommentaren versehen.
Auf dem Client muss fast nichts konfiguriert werden.
Für den Funksender nRF24L01 +, genauer gesagt für die RadioHead-Bibliothek, müssen die Server- und Client-Adressen angegeben werden. Adressen werden angegeben, wenn Sie mehr als einen Server und einen Client haben. Eine Adresse ist nur eine beliebige Ganzzahl. Wenn ein Client ein Datenpaket an einen Server sendet, gibt er an, für welchen Server dieses Paket bestimmt ist. Der Server, der seine eigene Adresse kennt, bestimmt wiederum, ob dieses Paket für ihn bestimmt ist.
Daher sollte SERVER_ADDRESS
auf dem Server und auf dem Client identisch sein, CLIENT_ADDRESS
für verschiedene Clients sollte jedoch unterschiedlich sein. Mit anderen Worten, wenn Sie in Zukunft einen weiteren neuen Sensor an unser System anschließen, muss CLIENT_ADDRESS
dafür geändert werden.
// #define SERVER_ADDRESS 10 #define CLIENT_ADDRESS 20 // !!!
Die RF_CHANNEL
-Funkkanalnummer muss für alle gleich sein. Standardmäßig ist es 2. Ich habe die Standardnummer geändert, Sie können jede andere auswählen.
Die Voltmetereinstellungen zur Messung der Batterieversorgungsspannung müssen geändert werden:
// , const float r1 = 100400; // 100K const float r2 = 9960; // 10K // // http://localhost/arduino-secret-true-voltmeter/ const float typVbg = 1.082; // 1.0 -- 1.2
Um Energie zu sparen, wird die Lightweight Low Power Library für Arduino verwendet .
Hier sind meine tatsächlichen Verbrauchsmessungen für den Arduino Pro Mini mit dieser Bibliothek:
- normalerweise 25mA
- bei der Arbeit mit DHT das gleiche
- mit Funkübertragung 38 mA
- bei LowPower.idle 15 mA
- bei LowPower.powerdown 7,5 mA
Der Client misst Temperatur, Luftfeuchtigkeit und Versorgungsspannung, packt dies alles in eine Datenstruktur, sendet die Daten an den Server und „schläft ein“. Wenn während der Übertragung Fehler aufgetreten sind, wird die Übertragung sofort wiederholt.
Der Server (Zentraleinheit, Heimeinheit) empfängt wiederum Daten, bestätigt den Empfang und verarbeitet sie.
Datenbank, MySQL, PHP, WWW-Server
Nach der Arbeit haben wir ein voll funktionsfähiges Design der Wetterstation. Aber jetzt gibt es ein Dutzend solcher Wetterstationen, lokales Handwerk ist nicht mehr in Mode. Immerhin haben wir ein Internet der Dinge.
Daher werden wir darüber sprechen, wie der Zugriff auf diese Ihr Internet erfolgt, wir werden eine Datenbank und ein Webface an unsere Wetterstation anhängen.
Die Problemstellung für die "Webcam":
- Empfangen und Speichern von Wetterstationsdaten: Temperatur, Luftfeuchtigkeit, Luftdruck, Versorgungsspannung
- Zeigen Sie diese Daten an
- Diagramme erstellen.
In diesem Fall benötigen wir Hosting mit Unterstützung für Apache, PHP und MySQL mit dem mysqli-Modul. Und diese Bedingungen werden von fast jedem Hosting auf dem Planeten Erde erfüllt. Anstatt zu hosten, spielt Ihr Computer die Rolle eines Servers, der mit einem Heimnetzwerk-Router verbunden ist und über einen Internetzugang verfügt.
Datenbankerstellung
Beginnen wir von vorne, nämlich mit dem Entwurf und der Erstellung der Datenbank.
Datenbanken sind Ihre Welt, und Sie können sie lange studieren. Wir werden daher nur kurz auf die Dinge eingehen, die wir direkt benötigen.
Alle SQL-Skripte befinden sich im Verzeichnis weather-station/server/php-sql/
Wo beginnt das Datenbankdesign? Mit einer logischen und physischen Darstellung.
Logische Ansicht oder Datenbankschema:
- DHT-Temperatur- und Luftfeuchtigkeitstabelle
- BMP-Datentabelle des Druck- und Temperatursensors
- Die angegebenen Tabellen haben keine Beziehung zueinander, genauer gesagt, die Links werden nicht benötigt.
Das physische Schema basiert auf einem bestimmten DBMS und Datentypen. Es ist einfacher, mit einem bestimmten Beispiel zu zerlegen. Das SQL-Skript make_tables.sql
die logischen und physischen Schemas.
Jede Tabelle sollte ein Typfeld haben
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT
Der Feldname kann in verschiedenen Datenbanken unterschiedlich sein, aber es gibt nur einen Sinn - dies ist eine eindeutige Kennung, ein Datensatzschlüssel. Wenn Sie für die Zukunft eine Datenbank in Tabellen sehen, die keinen solchen Zähler haben, sollten Sie wissen, dass diese Datenbank von einer Person entworfen wurde, die weit von der Programmierung entfernt ist, höchstwahrscheinlich von den Geisteswissenschaften.
Wir speichern die Daten von Sensoren desselben Typs in einer Tabelle, für Sensoren eines anderen Typs erstellen wir eine andere Tabelle. Dies verkompliziert die Datenbank- und PHP-Bindung geringfügig, vereinfacht jedoch in Zukunft die Erweiterung oder Änderung des gesamten Systems.
In unserem Projekt gibt es zwei Tabellen. Die Tabelle arduino_dht
speichert Daten von den Sensoren des Typs DHT (Temperatur, Luftfeuchtigkeit), die Tabelle arduino_bmp
speichert Daten von den Sensoren des Typs BMP (Temperatur, Druck). Wenn Sie in Zukunft beispielsweise einen Gassensor oder einen Bewegungsmelder haben möchten, erstellen Sie zusätzliche Tabellen. Seien Sie nicht faul. Wenn Sie einen anderen Sensor vom Typ DHT11 oder DHT22 anschließen, müssen Sie keine zusätzliche Tabelle erstellen. Verwenden Sie die Tabelle arduino_dht
. Ich hoffe, das Prinzip ist klar: Eine separate physische Einheit ist eine separate Tabelle.
Wenn Daten von mehreren Sensoren desselben Typs in einer Tabelle gespeichert werden, wie können sie dann unterschieden werden? Geben Sie dazu in jede Tabelle ein Feld ein
idSensor INTEGER
Tatsächlich ist es CLIENT_ADDRESS
das wir in der client/client.ino
für jede Instanz des Remote-Client-Clients und in server/server.ino
für den Sensor server/server.ino
der direkt mit dem Server verbunden ist - der Zentraleinheit.
In industriellen Systemen sollte es eine andere Tabelle geben - die Entsprechung von idSensor
und seine verbale, für Menschen lesbare Beschreibung. Ein Sensor mit idSensor
= 2 lautet beispielsweise "Temperatur, Luftfeuchtigkeit in der Wohnung" usw. Aber in unserem Projekt werden wir nicht komplizieren, denken Sie daran:
- ein Sensor mit
idSensor
, es ist CLIENT_ADDRESS
, gleich 11 - dies ist der CLIENT_ADDRESS
auf dem Server - die Zentraleinheit, - Als Sensor mit
idSensor
ist es auch CLIENT_ADDRESS
, gleich 20 - dies ist der erste (in unserem Projekt und der einzige) fensterbasierte Sensor-Client.
Weiter. In den Tabellen werden folgende Daten gespeichert:
- ipRemote - IP-Adresse der Wetterstation (Server), von der die Daten stammen, nützlich zum Debuggen und Überwachen,
- dateCreate - Datum, an dem der Datensatz erstellt wurde.
- Millis - nützlich für das Debuggen. Dies ist die Zeit in Millisekunden seit dem Beginn der Skizze auf dem Arduino.
- Temperatur - Temperatur
- Luftfeuchtigkeit - Luftfeuchtigkeit
- Spannung - Versorgungsspannung,
- Druck - Druck
- Fehler - die Anzahl der Fehler (nicht verwendet). Es war beabsichtigt, die Anzahl der Übertragungsfehler usw. zu speichern, damit Sie den Status des gesamten Systems aus der Ferne bewerten können.
Wie Sie sehen können, sind die arduino_bmp
arduino_dht
und arduino_bmp
sehr ähnlich, der Unterschied besteht nur in den Feldern Druck und Luftfeuchtigkeit, und es besteht der Wunsch, alles in einem Heap (Tabelle) arduino_bmp
. Aber die erste normale Form befiehlt dies nicht, viele anfängliche Programmierer haben versucht, es zu umgehen, aber keiner von ihnen hat es geschafft, und wir werden es nicht tun. Auf diese Weise kann man das Gesetz der universellen Gravitation nicht beachten, da es sich vorerst durchaus herausstellen kann.
Die Tabelle arduino_error_log
nützlich zum Debuggen - sie ist ein Protokoll von Fehlern und anderen Systemmeldungen.
Das Erstellen einer Datenbank und ihres Benutzers mit Rechten wird in make_db.sql
Dies geschieht einmal, der Datenbankname und der Benutzername können sich einen eigenen einfallen lassen. Und was genau getan werden muss, ist Ihr Passwort festzulegen.
PHP und Webserver
Alle Webinterface-Einstellungen werden in config.php
gespeichert. Ändern Sie es entsprechend Ihren Datenbankeinstellungen.
Stellen Sie Ihre Zeitzone im PHP-Format ein
date_default_timezone_set('Europe/Prague')
Alle verfügbaren Zeitzonen werden hier beschrieben .
Legen Sie Ihren geheimen Schlüssel für den Zugriff (als Nummer) fest, der mit der Konstante SOURCE_KEY
aus der Skizze server.ino
$access_key = '***KEY***';
In unserem Webserver gibt es keine Autorisierung, Passworteingabe, dies würde das gesamte Design komplizieren. Für einen Prototyp ist dies nicht erforderlich. Daher basiert der gesamte Schutz auf der Datei robots.txt
, dem Fehlen von index.php
und diesem geheimen Schlüssel für den Zugriff.
Das PHP-Hauptskript weather.php
akzeptiert eine einfache HTTP-GET-Anforderung mit Daten und speichert sie in den entsprechenden Datenbanktabellen. Wenn der Schlüssel $access_key
nicht übereinstimmt, wird die Anforderung abgelehnt.
Das weather-view.php
zum Anzeigen von Datentabellen verwendet und enthält Hyperlinks zu anderen Skripten der Weboberfläche. Nenn ihn so
http:
Zum Beispiel
http:
weather-view.php
zeigt einfache Beschriftungen an, an die Sie sich erinnern müssen:
- Der Sensor mit der ID 11 ist der Heimsensor auf dem Server.
- Der Sensor mit der ID 20 ist ein Fenstersensor.
Das Skript function.php
enthält Funktionen, die allen PHP-Skripten gemeinsam sind.
Das chart-dht.php
ist für das Charting mit Google Charts verantwortlich . Hier ist zum Beispiel ein Diagramm der Versorgungsspannung des Überseesensors. Die Spannung steigt an einem sonnigen Tag aufgrund der Solarbatterie an, und dann entlädt sich die Stromversorgung der Batterien allmählich.

export-dht.php
exportiert Daten aus MySQL-Datenbanktabellen in eine CSV-Datei. Zum weiteren Importieren und Analysieren in Tabellenkalkulationen.
export-voltage.php
exportiert Daten zur Versorgungsspannung vom Fenstersensor aus der MySQL-Datenbank in eine CSV-Datei. Nützlich zum Debuggen.
truncate.php
löscht alle Tabellen, d.h. löscht alle unsere Daten. Nützlich zum Debuggen. Es gibt keine Links zu diesem Skript von weather-view.php
, daher müssen Sie es über einen direkten Link in der Adressleiste Ihres Browsers mit $access_key
.
Beim Empfang von Daten wird häufig die Funktion mysqli_real_escape_string()
verwendet, um zu verhindern, dass falsche Werte in die Datenbank gelangen.
Vergessen Sie nicht, robots.txt
im Stammverzeichnis Ihrer Website zu platzieren, um zu verhindern, dass es in Suchmaschinen gelangt.
ESP8266, WiFi und Datenübertragung
Und jetzt zurück zur server.ino
Skizze, zu dem Teil davon, der eine Verbindung zum WiFi-Zugangspunkt herstellt und Daten an den Webserver sendet.
Wie ich bereits schrieb, konnte ich keine normale Bibliothek für Arduino finden, um das ESP8266-Modul mit AT-Befehlen zu steuern. Ich musste mich selbst "kollektiv bewirtschaften". Ich möchte Sie auch daran erinnern, dass Sie eine bestimmte Firmware-Version in ESP8266-01 flashen müssen. Und jetzt, wenn alles fertig ist, wollen wir sehen, wie es funktioniert.
Um auf den Webserver in der server.ino
Skizze server.ino
, müssen server.ino
diese Konstanten ändern
const String DEST_HOST = " "; // habr.com const String DEST_PORT = " "; // 80 const String DEST_URL = "/ /weather.php"; const String SOURCE_KEY= " "; // $access_key config.php
In server.ino
in der Funktion void setup()
der ESP8266 zuerst in den Stationsmodus geschaltet, d. H. Es beginnt als WiFi-Client zu arbeiten
espSendCmd(«AT+CWMODE_CUR=1», «OK», 3000)
und folgt dann der Verbindung zum Zugangspunkt
espState = espConnectToWiFi()
Wenn die Verbindung nicht hergestellt wird, wird der Versuch (einmal) wiederholt.
if ( espState != ESP_SUCCESS ) { delay(5000); Serial.println("WiFi not connected! Try again ..."); espConnectToWiFi(); }
Wählen Sie dann den TCP / IP-Einzelverbindungsmodus
espSendCmd("AT+CIPMUX=0", "OK", 2000)
Beim Senden von Daten von Sensoren vom Typ DHT an den Webserver wird eine Funktion verwendet, die den Datentyp als type=dht
espSendData( "type=dht&t=" + String(dhtData.temperature) + "&h=" + String(dhtData.humidity) + "&v=" + String(dhtData.voltage) + "&s=" + String(CLIENT_ADDRESS) )
Beim Senden von Daten von BMP-Sensoren an einen Webserver wird dieselbe Funktion mit dem als type=bmp
angegebenen Datentyp verwendet
espSendData( "type=bmp&t=" + String(temperature_bmp) + "&p=" + String(pressure_bmp) + "&s=" + String(CLIENT_ADDRESS) )
Die Funktion espSendData()
akzeptiert eine HTTP-GET-Anforderungszeichenfolge und sendet sie wie beabsichtigt an den Webserver.
In sich selbst überprüft espSendData()
die Verfügbarkeit des ESP-Moduls, indem es den Befehl „AT“ sendet. Anschließend überprüft es die WiFi-Verbindung und stellt bei Bedarf erneut eine Verbindung her. Dann werden die Daten gesendet und die TCP-Verbindung geschlossen.
Android App
Wenn heutzutage jeder eine LED blinken kann, werden Sie niemanden mit einer Wetterstation überraschen. Aber wenn das Handwerk weiß, wie man über WLAN mit dem Server kommuniziert, ein Webface und eine mobile Anwendung hat, dann ist dies etwas! Mit Server meinen wir hier natürlich den Anwendungsserver, d.h. In unserem Fall ist dies eine PHP-Bindung und ein MySQL-DBMS. Es gibt nicht genug Kirschen auf dem Kuchen, nämlich die Android-Anwendung, die wir jetzt schreiben werden.
Architektur
Die Architektur der gesamten Wetterstationssoftwareplattform ist einfach:
- Der Serverteil (Zentraleinheit) der Wetterstation sammelt Daten von Remote-Sensor-Clients
- Anschließend werden Daten an den Webserver von Anwendungen übertragen, der diese Daten in der Datenbank speichert
- Die Android-Anwendung (oder eine andere Remote-Anwendung: iOS, Browser) fordert Daten von einem Webserver an und zeigt sie auf dem Bildschirm an.
Auf dem Bildschirm des Android-Geräts werden die aktuellen und neuesten Sensorwerte angezeigt.
HTTP GET und JSON
Die Frage, die zuerst gelöst werden muss, ist, wie Daten vom Webserver zur Android-Anwendung übertragen werden.
Hier muss nichts erfunden werden, alles wurde bereits für uns erfunden - das sind HTTP GET und JSON.
In unserem Fall kann eine einfache GET-Anforderung an den Webserver manuell kompiliert und debuggt werden, während die Android-Anwendung noch nicht bereit ist.
In Java und Android gibt es vorgefertigte Bibliotheken für die Verarbeitung von Daten im JSON-Format. JSON ist ein für Menschen lesbares Textformat, das zum Debuggen nützlich ist.
Erstellen Sie ein neues PHP-Skript last-data-to-json.php auf dem Webserver, um aktuelle Daten von Wetterstationssensoren zu generieren.
Skriptaufruf:
http://<>/last-data-to-json.php?k=<access_key>
Dabei ist <access_key>
, wie wir uns erinnern, der geheime Datenbankzugriffsschlüssel.
Beispielantwort im JSON-Format:
{ "DHT 11":{ "idSensor":"11", "dateCreate":"2016-04-20 18:06:03", "temperature":"19", "humidity":"26", "voltage":"5.01" }, "DHT 20":{ "idSensor":"20", "dateCreate":"2016-04-18 07:36:26", "temperature":"10", "humidity":"26", "voltage":"3.7" }, "BMP 11":{ "idSensor":"11", "dateCreate":"2016-04-20 18:06:22", "temperature":"19", "pressure":"987.97" } }
Es muss daran erinnert werden, dass wir 3 Sensoren haben. Ihre ID und ihr Typ (DHT oder BMP) sind im gesamten Wetterstationscode fest codiert. Diese Methode der Hardcore-Codierung ist ideologisch falsch, aber für einen kniegezeichneten Prototyp (bei dem eine schnelle und einfache Lösung erforderlich ist) ist dies ein vernünftiger Kompromiss.
$idSensor = 11; // DHT $idSensor = 11; // BMP $idSensor = 20; // DHT
Das last-data-to-json.php
entnimmt die neuesten Daten dieser heterogenen Sensoren aus der Datenbank und packt sie in das JSON-Format. Die Auswahl der Daten aus der Datenbank „vom Ende“ erfolgt folgendermaßen:
SELECT <> FROM <> ORDER BY id DESC LIMIT 1;
Android
Jetzt schreiben wir eine einfache Android-Anwendung, die JSON-Daten anfordert, empfängt, decodiert und Informationen auf dem Bildschirm anzeigt.
Unsere Android-Anwendung wird so einfach wie möglich sein, nur das Wesentliche der Technologie. Weiter um dieses "Skelett" wird es bereits möglich sein, verschiedene "Schönheiten" aufzuziehen.
Hier ist ein Screenshot dessen, was dazu führen sollte

Wie Sie sehen können, ist die Benutzeroberfläche nur spartanisch, basierend auf LinearLayout, nichts weiter.
Oben in der Textansicht werden die ID der Sensoren und ihre meteorologischen Daten angezeigt. Die Schaltfläche Aktualisieren initiiert eine zweite Anforderung an den Webserver. Weiter in EditText ist die einzige Programmeinstellung - dies ist die Anforderungs-URL im Formular
http://< >/last-data-to-json.php?k=<access_key>
Was ist zu beachten?
Fügen Sie im Manifest Leitungen hinzu, die das Internet ermöglichen und den Status der Netzwerkverbindung überprüfen:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
Die Arbeit mit dem Netzwerk und das Empfangen von Daten von der Website ist wie folgt.
Wir verwenden AsyncTask, um eine Hintergrundaufgabe zu erstellen, die vom Haupt-UI-Thread getrennt ist. Diese Hintergrundaufgabe verwendet die Anforderungs-URL und verwendet sie zum Erstellen der HttpURLConnection
.
Nachdem die Verbindung hergestellt wurde, lädt AsyncTask den Inhalt der Webseite (JSON) als InputStream. Als nächstes wird der InputStream in eine Zeichenfolge konvertiert, die mit JSONObject dekodiert und mit der Methode onPostExecute()
in der Benutzeroberfläche angezeigt wird.
Ändern Sie in MainActivity.java die URL in:
private static final String defUrl = "http://host/dir/last-data-to-json.php?k=< >";
Es wird standardmäßig verwendet, wenn Sie zum ersten Mal eine Android-Anwendung ausführen.
Nachwort
Nun, etwas hat schon funktioniert. Dann können Sie etwas optimieren, etwas ersetzen, alles wegwerfen, aber auch etwas ausleihen.
Ein separater großer Wundpunkt ist der Energieverbrauch . Ich empfehle, Kommentare zu Beiträgen zu lesen, in denen es viele praktische Tipps gibt.
Bis ins Unendliche ... und darüber hinaus.