Unser Eigenbau-Feinstaubsensor ist fertig und liefert deine Daten an die Feinstaubkarte und vielleicht einige andere Umweltdatenbanken. Von dort können wir uns die Daten auch zurückholen – die eigenen und auch die von fremden Sensoren. Aber es gibt auch die Möglichkeit, einen eigenen Server zu betreiben, an den der Feinstaubsensor seine Daten zusätzlich abliefert. Die kann man dann nach Belieben in einer eigenen Datenbank speichern, auswerten, grafisch aufbereiten und als Webseite anzeigen. In diesem Artikel zeige ich, wie die Sensordaten vom Feinstaubsensor auf einen eigenen Server kommen.
Zuerst verweise ich wieder auf die originale Anleitung des Stuttgarter Feinstaub Projekts, die man in jedem Fall gelesen haben sollte, wenn man sich an den Eigenbau eines Feinstaubsensors machen will.
Was wird benötigt?
Ein eigener Feinstaubsensor natürlich, so wie in dieser Artikelserie beschrieben. Und ein Server. Der kann sich im eigenen Heimnetz befinden, aber auch im Internet. Was die Server-Software angeht, so gibt es da mehrere Möglichkeiten. Man könnte zum Beispiel einen REST-API-Server aufsetzen. REST steht für Representational State Transfer und meint Maschine-zu-Maschine-Kommunikation über das HTTP-Protokoll. Es geht aber auch mit vertrauteren Mitteln, nämlich mit einem LAMP-Server, was nichts anderes ist, als ein Web-Server auf Linuxbasis mit PHP und MySQL. Den könnte man auf einem Raspberry Pi für das eigene Heimnetz installieren ober man verwendet einen Webspace bei einem Provider im Internet. Lediglich PHP als serverseitige Programmiersprache muss verfügbar sein und falls die Daten in einer Datenbank gespeichert werden sollen, dann eben MySQL oder etwas ähnliches.
Steht ein Web-Server mit PHP zur Verfügung, dann sind grob nur zwei Dinge zu tun, die ich nachfolgend beschreiben werde:
- Erstellen eines PHP-Programms, das die Sensordaten entgegen nimmt und
- Konfigurieren des Feinstaubsensors, damit dieser das PHP-Programm anspricht.
PHP-Programm, zum Empfang von Feinstaubdaten
Wir beginnen mit einem Zweizeiler um zu sehen, was der Feinstaubsensor überhaupt an Daten sendet:
<?php
$json = file_get_contents("php://input");
file_put_contents("feinstaub.log", $json);
?>
Alten PHP-Web-Programmier-Hasen wird hier komisch vorkommen, wie die Daten übernommen werden. Das passiert nicht, wie bei der Entgegennahme eines Web-Formulars mit $_GET[’name‘] oder $_POST[’name‘]. Das hat den einfachen Grund, dass der Feinstaubsensor kein Web-Formular emuliert und es den Feldnamen ’name‘ in diesem Fall gar nicht gibt. Der CONTENT_TYPE ist nicht multipart/form-data, wie bei Web-Formularen, sondern application\/json, es wird also reines JSON ohne irgendwelche zusätzliche Verpackung versendet.
Und was ist JSON? Ausgeschrieben JavaScript Object Notation, hat JSON mit JavaScript eigentlich gar nichts zu tun, sondern ist ein beliebtes Datenaustauschformat. Beliebt deshalb, weil man in beliebigen Programmiersprachen sehr einfach Objekte oder beliebige Datenstrukturen in JSON wandeln und dann als Textstring verschicken kann. So kann zum Beispiel JavaScript in einem Web-Browser Daten mit einem PHP-Programm auf einem Web-Server im Hintergrund austauschen, ohne dass der Anwender die WebSeite neu laden muss. Das heißt dann AJAX (Asynchronous JavaScript and XML), auch wenn statt XML JSON verwendet wird. So weit nur ein kleiner begrifflicher Einstieg, für diejenigen, denen diese Begriffe fremd sind.
Was macht das Programm? In der ersten Zeile (also eigentlich in der zweiten, wenn wir das einleitende <?php
mit zählen) werden die vom Feinstaubsensor gelieferten Daten in die Variable $json
gepackt. Und in der folgenden Zeile wird der Inhalt mit file_put_contents
in eine Datei namens feinstaub.log
geschrieben. Eigentlich ganz einfach. Dem PHP Programm geben wir einen Namen (ich nenne es sensor.php
) und legen es in ein Unterverzeichnis /feinstaub
auf den Webserver.
Je nach dem, wie die Rechtestruktur am Webserver angelegt ist, müssen wir ggf dafür sorgen, dass das PHP-Programm Schreibrechte auf die Datei feinstaub.log
hat. Dazu legen wir eine leere feinstaub.log
im Verzeichnis /feinstaub
an und geben ihr mit chmod
den Wert 666, also Schreib/Lese-Rechte für Eigentümer, Gruppe und Andere. Das kann bei einem fremden oder entfernten Server mit dem FTP-Client erfolgen.
Damit ist der Webserver empfangsbereit.
Feinstaubsensor konfigurieren
Jetzt brauchen wir Zugriff auf die Konfigurations-Webseite unseres Feinstaubsensors. Zur Erinnerung, dazu geben wir folgendes im Webbrowser ein:
http://feinstaubsensor-ID.local/
wobei ID durch die jeweilige Chip-ID zu ersetzen ist. Im Falle meines Sensors also:
http://feinstaubsensor-534958.local/
Alternativ dazu, oder wenn es mit diesem Namen nicht funktioniert, kann man natürlich auch direkt die IP-Adresse des Sensors verwenden, wie im Beispiel rechts. Vom Hauptmenü klicken wir uns auf die Konfigurationsseite und blättern nach unten bis An eigene API senden. Den Punkt markieren wir mit einem Häkchen und füllen dann die nächsten drei Zeilen aus. Bei Server muss natürlich der eigene Servername oder dessen IP-Adresse eingetragen werden und nicht meiner. Der Pfad hängt davon ab, wo die PHP-Datei am Server liegt und wie sie heißt und der Port ist üblicherweise 80 für Http. Danach das Speichern nicht vergessen.
Nun wird bei jedem Datenversand, der alle 145 Sekunden erfolgt, auch der eigene Server mit beliefert. Die Datei feinstaub.log
sollte also innerhalb der nächsten 2½ Minuten einen Inhalt bekommen. Den können wir mit einem Texteditor anschauen. Es wird eine einzige ziemlich lange Zeile sein mit vielen geschweiften und eckigen Klammern. Das ist JSON und etwas in Form gebracht sieht der Inhalt dann folgendermaßen aus:
{
"esp8266id": "534958",
"software_version": "NRZ-2017-099",
"sensordatavalues":[
{"value_type":"SDS_P1","value":"4.47"},
{"value_type":"SDS_P2","value":"4.03"},
{"value_type":"temperature","value":"15.60"},
{"value_type":"humidity","value":"75.20"},
{"value_type":"samples","value":"635908"},
{"value_type":"min_micro","value":"226"},
{"value_type":"max_micro","value":"27791"},
{"value_type":"signal","value":"-90"}
]
}
Bei anderen oder zusätzlichen Sensoren wird der Inhalt natürlich etwas anders sein, aber die Struktur wird hier schon klar. Unter den sensordatavalues
kommen im Beispiel zuerst die beiden Feinstaubwerte, dann Temperatur und Luftfeuchtigkeit. Zu den drei folgenden habe ich keine Erklärung und der letzte Wert bei signal
ist die WLAN-Signalstärke in dBm.
PHP-Programm zur Verarbeitung der Sensordaten
Das zweizeilige PHP-Programm oben ist gut geeignet um einen Einblick in die Datenstruktur zu bekommen. Diese ist allerdings etwas kryptisch und der Dateiinhalt wird bei jeder neuen Datenlieferung überschrieben. Aber nachdem wir nun die Struktur der JSON-Daten kennen, können wir uns die interessanten Werte extrahieren und dann weiter verarbeiten. Diese Weiterverarbeitung kann die Ablage in einer SQL-Datenbank sein, oder wie im folgenden Beispiel die Generierung einer CSV-Datei (für Excel zum Beispiel).
<?php
$log = "feinstaub.log";
$schluessel = array("SDS_P1", "SDS_P2", "temperature", "humidity", "signal");
$json = file_get_contents("php://input");
$daten = json_decode($json, true);
$sensoren = $daten["sensordatavalues"];
$zeit = date("Y-m-d H:i:s");
$zeile = $zeit.",";
foreach ($schluessel as $key) {
$index = array_search($key, array_column($sensoren, "value_type")); # ab PHP 5.5.0
$zeile .= $sensoren[$index]["value"].",";
}
$zeile = rtrim($zeile, ",") ."\n";
file_put_contents($log, $zeile, FILE_APPEND);
?>
ok
Was macht das Programm? Der Name der Logdatei bleibt unverändert, er wird jetzt nur in der Variablen $log
gespeichert. Dann definiere ich ein Array $schluessel
aus all den value_types
, die von Interesse sind, um später nur nach diesen zu suchen. Jetzt kommt die bekannte Zeile, die die gesamte Datenstruktur entgegen nimmt und in der Variablen $json
speichert. JSON ist ja an sich nur ein Textstring und damit zwar halbwegs gut lesbar, aber nur schwer programmmäßig zu bearbeiten. Einfacher tun wir uns, wenn wir den JSON-String in ein assoziatives Array überführen. Das macht json_decode
und das Ergebnis ist dann ein assoziatives Array, das von der Struktur her dem JSON-String entspricht. Die Sensorwerte stecken in einem Array mit Namen sensordatavalues
und diesen Teil der Datenstruktur hole ich mir zur Vereinfachung in die Variable $sensoren
.
Nachdem die Daten vom Feinstaubsensor keinen Zeitstempel enthalten, müssen wir die Serverzeit dazu verwenden um die Sensordaten mit einer Uhrzeit zu verbinden. Dazu holen wir uns einen Datum-Zeit-String in die Variable $zeit
.
Dieser Zeitstempel wird auch der erste Eintrag in $zeile
. Diese Zeile wird später eine Datenzeile in der CSV-Datei, aber zuerst müssen wir sie zusammenbauen und dabei die einzelnen Werte durch Komma trennen.
Die Musik spielt dabei in der folgenden foreach
-Schleife. Hier werden der Reihe nach alle interessierenden value_types
aus dem Array $schluessel
durchlaufen. Die erste Zeile innerhalb der Schleife sucht nach dem jeweiligen value_type
und merkt sich dessen Position im Array in der Variablen $index
. Mit diesem Index können wir dann den zugehörigen Wert unter value
extrahieren und ihn gleich zusammen mit einem Komma an $zeile
hinten anhängen.
An dieser Stelle ließe sich theoretisch auch eine Datenbank versorgen. Die Bezeichnung (analog zu value_type
) haben wir in $key
und den Wert (entsprechend value
) bekommen wir mit $sensoren[$index]["value"]
.
Nach der foreach
-Schleife haben wir alle Werte in der Variablen $zeile
beisammen, aber unschönerweise steht am Ende ein Komma zu viel. Das entfernen wir mit rtrim
und fügen gleichzeitig eine Zeilenschaltung (\n
) ans Zeilenende an. Jetzt brauchen wir die Zeile nur noch in die Logdatei zu schreiben. Das passiert wie im ersten Programm mit file_put_contents
, aber mit dem Unterschied, dass wir die Datei nicht jedes mal überschreiben, sondern die neue Zeile an die vorhandene Datei hinten anhängen (FILE_APPEND
).
Und so sieht der Inhalt der Logdatei dann auszugsweise aus:
2017-11-05 15:37:25,4.50,3.50,8.50,99.90,-89
2017-11-05 15:39:53,2.67,1.43,8.50,99.90,-90
2017-11-05 15:42:22,1.37,1.00,8.30,99.90,-89
2017-11-05 15:44:51,2.20,0.90,8.00,99.90,-84
Und was soll das ok
am Ende des Programms? Das ok steht außerhalb des PHP-Bereichs, ist also kein Programmbestandteil, sondern eine Rückmeldung an den Feinstaubsensor. Ob der das wirklich auswertet, weiß ich nicht, im ersten Beispiel geht es ja auch ohne diese Rückmeldung. Aber ich hab das in einem Programmierbeispiel gesehen und schaden wird es kaum.
Weiterverarbeiten
Ich habe hier lediglich gezeigt, wie wir die Sensordaten unseres Feinstaubsensors auf einen eigenen Server bekommen und beispielhaft in einer CSV-Datei ablegen können. Damit ist aber noch nicht viel gewonnen, da diese Datei sehr schnell recht groß und unhandlich wird. Viel praktischer wäre es bei großen Datenmengen, die Werte in eine Datenbank zu speichern, MySQL zum Beispiel – PHP verfügt dazu über geeignete Module. Dann könnte ein weiteres PHP-Programm die Werte wieder aus der Datenbank extrahieren und in Form einer Webseite darstellen, zum Beispiel die aktuellen Werte mit Minimum und Maximum der letzten 24 Stunden. Denkbar wäre auch eine grafische Aufbereitung mit entsprechenden Tagesverläufen. Kreativen Programmierern sind hier kaum Grenzen gesetzt, den Umfang dieses Feinstaubprojekts würde das allerdings sprengen.
Weitere Artikel in dieser Kategorie:
- Feinstaubsensor – Teil 1: Jetzt messen wir selber!
- Feinstaubsensor – Teil 2: Einkaufsliste
- Feinstaubsensor – Teil 3: Arduino IDE installieren
- Feinstaubsensor – Teil 4: Feinstaub-Software flashen
- Feinstaubsensor – Teil 5: Konfigurationsdaten löschen
- Feinstaubsensor – Teil 6: Stromversorgung
- Feinstaubsensor – Teil 7: Zusammenbau
- Feinstaubsensor – Teil 8: Verkabelung und Aufstellung
- Feinstaubsensor – Teil 9: Konfiguration
- Feinstaubsensor – Teil 10: Veröffentlichen der Sensordaten
- Feinstaubsensor – Teil 11: Datenabruf
- Feinstaubsensor – Teil 13: Silvester – Feinstaubfest der Superlative
Vielen Dank für den sehr lesenswerten Blog und die wertvollen Erklärungen. Sehe ich das richtig, dass der Versuch, die Sensordaten des Esp8266 über den Weg „Eigene Api verwenden“ auf meinen dort spezifizierten https-Server abzuspeichern, scheitert, da der Esp8266 nicht verschlüsselt sendet?
Das kann gut sein, aber ich muss gestehen, ich hab es mit https nie probiert.
Helmut,
Seit einige wochen hier auch ein Sensor aktiv.
Datei wird jetz auch auf meine Server geschrieben: :-)
{„esp8266id“: „xxxxxxx“, „software_version“: „NRZ-2017-099“, „sensordatavalues“:[{„value_type“:“SDS_P1″,“value“:“7.40″},{„value_type“:“SDS_P2″,“value“:“2.50″},{„value_type“:“temperature“,“value“:“8.00″},{„value_type“:“humidity“,“value“:“94.30″},{„value_type“:“samples“,“value“:“617803″},{„value_type“:“min_micro“,“value“:“229″},{„value_type“:“max_micro“,“value“:“27044″},{„value_type“:“signal“,“value“:“-81″}]}
Ich möchte jetzt ein Skript mit JSON-Befehlen schreiben.
Vielleicht haben Sie einen Tip? Wie kann ich Daten konvertieren nach JSON?
Mein domotica-app Domoticz auf mein Synology versteht zum beispiel:
http://x.x.x.x:8080/json.htm?type=command¶m=udevice&idx=737&nvalue=0&svalue=30
sensor hat Namen idx mit nummer 737)
Deine skript gibt leider error:
PHP Warning: array_column() expects parameter 1 to be array, null given in /volume1/web/feinstaub/test.php on line 15
PHP Warning: array_search() expects parameter 2 to be array, null given in /volume1/web/feinstaub/test.php on line 15
Current PHP version: 5.5.33
mit Interesse und vielen Dank
Glückwunsch zum eigenen Sensor.
Die Datei, die auf Ihren Server geschrieben wird, ist bereits reinstes JSON. Nur hat es scheinbar nicht die Struktur, die Ihre App benötigt. Genau diese Anpassung können Sie machen, in dem Sie ein PHP-Script vorschalten, bzw. das Script, das die Daten vom Feinstaubsensor entgegen nimmt, erweitern. In PHP können Sie die JSON-Daten in ein strukturiertes Array (ich hoffe, das ist der richtige PHP-Ausdruck) parsen, die Struktur per Programm verändern und dann erneut JSON-encoded als Datei speichern.
Danke auch für die Anleitung.
Hier noch ein kleines perl-script, welche die Daten in eine rrd Datenbank schreibt:
#!/usr/bin/perl
#
use JSON qw(decode_json);
use RRD::Simple;
use CGI;
my $q = new CGI;
print $q->header(‚text/plain‘);
$json_text = $q->param(‚POSTDATA‘);
my $decoded = decode_json($json_text);
my @friends = @{ $decoded->{’sensordatavalues‘} };
foreach my $f ( @friends ) {
$SDS_P1 = $f->{„value“} if ($f->{„value_type“} =~ /SDS_P1/);
$SDS_P2 = $f->{„value“} if ($f->{„value_type“} =~ /SDS_P2/);
$temperature = $f->{„value“} if ($f->{„value_type“} =~ /temperature/);
$hum = $f->{„value“} if ($f->{„value_type“} =~ /humidity/);
$pres = $f->{„value“} if ($f->{„value_type“} =~ /BMP_pressure/);
$temp = $f->{„value“} if ($f->{„value_type“} =~ /BMP_temperatur/);
}
$pres = $pres/100;
my $rrd = RRD::Simple->new(file=>“/var/www/rrd/feinstaub.rrd“);
$rrd->update(
SDS_P1 => $SDS_P1,
SDS_P2 => $SDS_P2,
BMP_pres => $pres,
BMP_temp => $temp,
DHT_temp => $temperature,
DHT_hum => $hum
);
und die rrd-datenbank schaut so aus:
rrdtool create feinstaub.rrd –step 145 \
DS:SDS_P1:GAUGE:200:0:500 \
DS:SDS_P2:GAUGE:200:0:500 \
DS:BMP_temp:GAUGE:200:-30:70 \
DS:BMP_pres:GAUGE:200:900:1200 \
DS:DHT_temp:GAUGE:200:-30:70 \
DS:DHT_hum:GAUGE:200:0:100 \
RRA:AVERAGE:0.5:1:5959 \
RRA:MIN:0.5:596:3600 \
RRA:MAX:0.5:596:3600 \
RRA:AVERAGE:0.5:596:3600
Besten Dank für die Anleitung, sie hat mich ermutigt mit einer MySQL-Implementierung loszulegen. Kleiner Hinweis: Bei meinem Sensor erhalte ich den Temperatur und Feuchtigkeitswert nur alle 4 Datensätze. Um diese Art von Sensorunregelmäßigkeiten abzufangen muss der Rückgabewert des array_search in der foreach-Schleife ausgewertet werden ;-)
Da wäre interessant zu wissen, welchen Sensor Du verwendest.
Nachdem der MySQL-Import nun klappt, stellte ich fest, dass mein Sensor (SDS011, DHT22, Firmwware NRZ-2018-103) doch nicht – wie urspr. vermutet – die Temperatur und Feuchtigkeit nur alle x Datensätze überträgt, sondern, dass diese beiden Werte eher zufällig „fehlen“.
Hier mein Code als mögliche Hilfe für eigene Experimente …. jaja, sicherlich
noch optimierungsbedürftig – aber erst einmal läuft er ;-)
————————————————————————–
connect_error) {
die(„Connection failed: “ . $conn->connect_error);
}
if ($conn->query($sql) === TRUE) {
echo „New record created successfully“;
} else {
echo „Error: “ . $sql . „“ . $conn->error;
}
$conn->close();
?>
OK
———————————————————–
table werte
data_id int(11) No
timestamp timestamp No CURRENT_TIMESTAMP
sensor_id int(11) No
software varchar(30) No
SDS_P1 float Yes NULL
SDS_P2 float Yes NULL
temperature float Yes NULL
humidity float Yes NULL
samples int(11) Yes NULL
min_micro int(11) Yes NULL
max_micro int(11) Yes NULL
sigqual int(11) Yes NULL
DHT22 sollte bei Standard-Zeitintervall eigentlich schon immer liefern. aber vielleicht ist ihm derzeit zu warm. ;-) Danke für die Infos.
PHP-mySQL – Part 1
<?php
$log = "feinstaub.log";
$schluessel = array("SDS_P1", "SDS_P2", "temperature", "humidity", "samples", "min_micro", "max_micro", "signal");
$json = file_get_contents("php://input");
$daten = json_decode($json, true);
$sensoren = $daten["sensordatavalues"];
file_put_contents($log, $json);
$sql = "INSERT INTO werte (sensor_id,software, SDS_P1, SDS_P2, temperature,humidity, samples, min_micro,max_micro,sigqual) VALUES (";
$sql .= $daten["esp8266id"] . ",'" . $daten["software_version"] . "'";
foreach ($schluessel as $key) {
$index = array_search($key, array_column($sensoren, "value_type"));
if ($index !== false)
{
$sql .= "," . $sensoren[$index]["value"];
}
else
{
$sql .= ",NULL";
}
}
$sql .= ")";
file_put_contents($log, $sql, FILE_APPEND);
PHP-mySQL – Part 2
$servername = „localhost“;
$username = „user“;
$password = „pw“;
$dbname = „feinstaub“;
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die(„Connection failed: “ . $conn->connect_error);
}
if ($conn->query($sql) === TRUE) {
echo „New record created successfully“;
} else {
echo „Error: “ . $sql . „“ . $conn->error;
}
$conn->close();
?>
OK
Hi
Could you do the same in English (or in French) ?
Best regards,
Bruno Clémentin
Hallo FrankieTNG,
ich habe eine funktionierende MySQL-Datenbank.Diese ist befüllt mit den entsprechenden Tabellenwerten. Auch ist JSON unter PHP 7.2 installiert. Wenn ich nun die Part 1 +2 als PHP-Script zusammenfüge und die Datenbank-Login-Werte eingebe, erfolgen keine Einträge in die Datenbank.
Ich tippe mal, dass das Script unter PHP 7.2 nicht läuft.
Bitte um einen Tipp, wie ich das Teil zum laufen bringe.
mfg
Herbert
Hallo zusammen,
Problem gelöst.
Windows Server 2016 mit MySQL-Datenbank und PHPmyAdmin und Rasperimatic (CCU3)
Datenbank „sensor“ mit „werte“-Tabelle angelegt
Spalten erstellt:
# Name Typ Kollation Null Standard
1 timestamp timestamp Nein CURRENT_TIMESTAMP
2 ppm25 float Ja kein(e)
3 ppm10 float Ja kein(e)
4 data_id text latin1_german1_ci Ja kein(e)
5 software text latin1_german1_ci Ja kein(e)
6 temperature float Ja kein(e)
7 humidity float Ja kein(e)
PHP-Script mit Namen „sensor.php“ erstellt:
sensordatavalues[0]->value;
$PPM25=$json_ergebnis->sensordatavalues[1]->value;
$TEMPERATURE=$json_ergebnis->sensordatavalues[2]->value;
$LUFTFEUCHTE=$json_ergebnis->sensordatavalues[3]->value;
$servername = „localhost“;
$username = „Administrator“;
$password = „0815Server“;
$dbname = „sensor“;
// Check connection
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die(„Connection failed: “ . $connection->connect_error);
}
$sql = „INSERT INTO werte (timestamp,ppm25,ppm10, software, data_id, temperature, humidity) VALUES (CURRENT_TIMESTAMP,$PPM25,$PPM10,’NRZ-2018-123B‘,’ID:10xxxxxx‘,$TEMPERATURE, $LUFTFEUCHTE)“;
if ($conn->query($sql) === TRUE) {
echo „Eintrag war erfolgreich“;
} else {
echo „Error: “ . $sql . “ “ . $conn->error;
}
$conn->close();
?>
Ich habe die Abfrage-Frequenz über die CCU3 mit einem Programm gesteuert, das die Werte z.B. alle 5 Minuten abfragt. Grund für dieses Vorgehen ist, dass bei anderen Vorgehensweisen alle 2,5 Minuten ein Datensatz generiert wird. Mit meiner Art habe ich mehr Minuten-Variablen. „data_id“ und „software“ kann weggelassen werden.
Viel Spass
mfg
Herbert
Hallo, danke erstmal für den hilfreichen Artikel!
Wie funktioniert denn die (optionale) Authentifizierung bei „An eigene Api senden“? Habe bisher nichts dazu gefunden.
Vielen Dank.
Ich auch nicht. Das wird man wohl ausprobieren müssen, in welcher Form User und Passwort dann an den Server übergeben werden.
Danke Helmut für die Antwort. Ich habe herausgefunden, dass es sich um eine Http-Authentifizierung vom Typ Basis Authentifizierung handelt. Die Codezeile 2160 in der Datei „airrohr-firmware.ino“ verweist darauf:
if (strlen(basic_auth_string) != 0) {
request_head += F(„Authorization: Basic „);
request_head += String(basic_auth_string) + „\r\n“;
}
Dieser Teil sendet den Auth String.
Vielen Dank für den Hinweis – das kann sicher jemand gebrauchen. Wenn Du ein Stück PHP- oder Python-Code hast, der das entgegen nimmt, dann gerne hier posten.
Was ist eigentlich min_micro, max_micro und samples?
Was bedeutet max_micro und min_micro?
Lieber Helmut
Gibt es ein Moglichkeit das auch die Sensor ID im log geschrieben wird? Dank voraus
Die Sensor-ID wäre dann aber bei jedem Datensatz gleich.
Möglich ist das sicher, wie man oben sieht, wird die Sensor_ID als „esp8266id“ in den Daten mitgeliefert. Einfach das Feld auslesen und in jede Logzeile einfügen.
Hi, könnte für andere Leute vielleicht hilfreich sein:
Wenn Ihr an „Cannot use object of type stdClass as array“ scheitert (neues PHP), dann hilft ein „,true“ im json_decode,
$data = json_decode($json, true);
dann kommt ein Array statt eines StandardObjekts zurück.
Hallo Helmut,
vielen Dank für das schöne Tutorial. Das hat mir gut geholfen.
Leider bekomm ich eine Fehlermeldung, dass die Funktionen array_search und array_column keine Arrays als Parameter bekommen.
Den Inhalt der Post Request wird ja dem Array $sensoren übergeben – warum wird das in der foreach nicht erkannt?
Hallo Ardowan,
versuch einfach mal $json, $daten, oder $sensoren ins feinstaub.log zu speichern, dann solltest Du die Datenstruktur erkennen können.
Hi.
Die Scripte funktionieren sehr gut. Allerdings habe ich ein Problem. Manchmal wirft einer der Sensoren, hier bei Feuchtigkeit, den Wert nan aus und der kann nicht in einen Float-Wert umgewandelt werden und daher scheitert das Inserten des Datensatzes in die Datenbank. Gibt es eine Möglichkeit solche unsinnigen Werte abzufangen und ggf. durch 0.0 zu ersetzen?
Das geht sicher. Wenn das „nan“ direkt vom Sensor als String geliefert wird, können Sie mit einer if Abfrage darauf aufprüfen und in dem Fall 0.0 setzen.
Danke Helmut, für die Antwort.
Wenn es um SQL ginge hätte ich sofort eine Lösung, aber bei PHP und JSON bin ich beinahe ein Analphabet.
Ja, das nan wird so vom Sensor geliefert:
BME280 Temperatur 18.1 °C
BME280 Luftdruck 949.49 hPa
BME280 rel. Luftfeuchte nan %
und steht im vom Script erzeugten Logfile auch als nan drin…
Ja, dann frei formuliert irgendwie
if blabla == „nan“ then blabla = „0.0“
Hallo Helmut, der Feinstaubsensor sendet seine Daten seit Jahren brav an die vorgesehenen APIs. Nun habe ich versucht mit dem php-script sensor.php die Daten auf meinen lokalen Webserver zu übertragen. Es sieht aber so aus, als ob der Sensor den Server nicht erreicht. Habe XAMPP für MAC OS 8.1.1 (also nicht VM) laufen. Der Server ist mit „localhost“ oder 127.0.0.1 vom MAC, auf dem auch XAMPP installiert ist, zu erreichen. Aus dem Heimnetzwerk aber nicht geschweige denn aus dem WWW. Der Sensor ist ja aber ein Gerät im Heimnetzwerk und kann den Webserver so nicht erreichen. Problemanalyse ergab: Ich bin zu doof! Und: Habe die Struktur wohl nicht verstanden. Zur Lösung hat diese Analyse aber nicht beigetragen ;-) Kannst Du mir weiterhelfen?
Gruß
Roland
Roland
Hallo Roland,
wenn sich der Sensor WLAN-mäßig im Heimnetzwerk befindet (so sollte es sein und so hab ich Dich auch verstanden) und Dein XAMPP-Server aus dem Heimnetzwerk nicht erreichbar ist, dann kann folglich der Sensor den Server auch nicht erreichen. Die Frage ist also, in welchem Netzwerk befindet sich der Server? Am besten natürlich auch im Heimnetzwerk. Schau Dir am Mac mal die Netzwerkadressen an, daraus solltest Du erkennen können, ob eine davon (nicht die 127:0:0.1) zum Heimnetzwerk gehört. Du solltest den Server von jedem anderen Gerät im Heimnetzwerk aus pingen können.
Eine zweite Fehlerquelle könnte sein, dass XAMPP vielleicht so eingestellt ist, das es nur auf der lokalen Maschine arbeitet, aber nicht im Netzwerk. Wenn ich mich recht entsinne, kann man das in XAMPP irgendwo einstellen.
Und der dritte Punkt: Sensor und Server müssen über den selben Port kommunizieren, wenn der Sensor Port 80 anspricht, der XAMPP aber auf 8080 hört, dann klappt das nicht. Eins von beiden musst Du dann anpassen.
Ich hoffe, da waren ein paar Tipps dabei, die Dir weiterhelfen.
Viel Erfolg
Hallo Helmut,
vielen Dank. Habe Deine Tipps alle nochmals gecheckt. Die ganze Zeile in httpd.conf gelöscht und nochmals neu geschrieben (identisch). Nun funktioniert es. Keine Ahnung wieso … Zum irre werden!
Vielen Dank
Roland
Prima, dass es jetzt funktioniert. Noch kurz zur Erläuterung für diejenigen, die hier mitlesen: Der Fehler lag nicht am Feinstaubsensor, sondern an der XAMPP Konfiguration.
Hallo und danke für dieses tolle Tutorial
Ganz oben fragt jemand für den Export auf eigene https Internet Seiten
Der Port muss dann folgerichtig auf 443 geändert werden, dann rennt das wunderbar
Hallo Helmut,
seit mehreren Jahren verrichtet der Sensor seinen Dienst (ab und zu stirbt der Lüfter, 1x der 3,3V-Stabilisator im Sensormodul) und sendet die Daten auch an einen BananaPi mit dem sensor.php von Dir.
Die Platte des Pi war nun gestorben, so dass ich alles neu einrichten musste.
Aber sensor.php wollte nicht mehr:
PHP Fatal error: Cannot redeclare array_column() in /var/www/html/sensor.php on line 3
Habe es endlich hinbekommen: Funktion array_column einfach umbenannt in fn_array_column. Tatsächlich gibt es seit PHP5.5 eine gleichnamige Funktion.
Vielen Dank verspätet für die brauchbare Anleitung!
Viele Grüße
Holger
array_column:
Gerade erst oben gesehen, dass das schon beachtet wurde im aktuellen Text, sorry.
Dann hätte ja bei mir auch geholfen, die ganze Funktion (Zeilen 3-86) rauszulöschen, die bei mir noch drin ist
Hallo Herr Karger,
ich folge Ihnen beim Thema Feinstaubsensor schon lange und habe vor ca. 5 Jahren meinen mit Hilfe Ihrer Anleitung in Betrieb genommen. Jetzt bin ich umgezogen und war gezwungen, einige lieb gewordene Dinge anzupassen.
So habe ich für andere Themen im neuen Heim Mosquitto (also MQTT) auf einem Synology-Nas als Docker zum Laufen gebracht, in welches alle anderen Sensoren (seien es Tasmota-Nous oder Shellys) brav ablegen.
Gibt es wohl eine Möglichkeit, dieses auch über den Feinstaubsensor zu erreichen?
Da Mosqitto eine influx.db verwendet habe ich versucht, unter APIs den Eintrag „senden an influxDB zu verwenden.
Server, Port, Benutzer und Passwort habe ich eingetragen, aber trotzdem erhalte ich keine Daten.
Haben Sie da Erfahrungen? Ich habe beim Suchen im Netz entdeckt, das Sie sich auch mit MQTT beschäftigt haben (Thema: Balkonkraftwerke), daher meine Frage
Hallo Christian,
die Artikelserie ist ja jetzt bereits 6 Jahre alt, da kann es durchaus sein, dass sich seitens des Projekts einiges verändert hat und inzwischen auch MQTT unterstützt wird. Das müssten Sie direkt auf der Projektwebsite checken. Seinerzeit konnte der Feinstaubsensor kein MQTT sondern nutzt REST. Falls MQTT direkt nicht geht, könnten Sie aber – ähnlich wie im Artikel beschrieben – die Daten mit einem eigenen Programm per REST-API entgegen nehmen und selber in die InfluxDB schreiben.
Viel Erfolg