Feinstaubsensor – Teil 12: Sensordaten selbst speichern

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

An eigene API sendenJetzt 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:

38 Kommentare

  1. Frank

    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?

    Antworten
    1. Helmut (Beitrag Autor)

      Das kann gut sein, aber ich muss gestehen, ich hab es mit https nie probiert.

      Antworten
  2. Pieter

    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&param=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

    Antworten
    1. Helmut (Beitrag Autor)

      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.

      Antworten
  3. Paul

    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

    Antworten
  4. FrankieTNG

    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 ;-)

    Antworten
    1. Helmut (Beitrag Autor)

      Da wäre interessant zu wissen, welchen Sensor Du verwendest.

      Antworten
  5. FrankieTNG

    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

    Antworten
    1. Helmut (Beitrag Autor)

      DHT22 sollte bei Standard-Zeitintervall eigentlich schon immer liefern. aber vielleicht ist ihm derzeit zu warm. ;-) Danke für die Infos.

      Antworten
  6. FrankieTNG

    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);

    Antworten
  7. FrankieTNG

    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

    Antworten
  8. Bruno Clémentin

    Hi

    Could you do the same in English (or in French) ?

    Best regards,

    Bruno Clémentin

    Antworten
  9. Springer, H.

    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

    Antworten
  10. Springer, H.

    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

    Antworten
  11. Björn

    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.

    Antworten
    1. Helmut (Beitrag Autor)

      Ich auch nicht. Das wird man wohl ausprobieren müssen, in welcher Form User und Passwort dann an den Server übergeben werden.

      Antworten
  12. Björn

    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.

    Antworten
    1. Helmut (Beitrag Autor)

      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.

      Antworten
  13. Steevee

    Was ist eigentlich min_micro, max_micro und samples?

    Antworten
    1. Gerhard Horn

      Was bedeutet max_micro und min_micro?

      Antworten
  14. Theo Jurriens

    Lieber Helmut

    Gibt es ein Moglichkeit das auch die Sensor ID im log geschrieben wird? Dank voraus

    Antworten
    1. Helmut (Beitrag Autor)

      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.

      Antworten
  15. Stefan

    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.

    Antworten
  16. Ardowan

    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?

    Antworten
    1. Helmut (Beitrag Autor)

      Hallo Ardowan,

      versuch einfach mal $json, $daten, oder $sensoren ins feinstaub.log zu speichern, dann solltest Du die Datenstruktur erkennen können.

      Antworten
  17. Herbert Brandner

    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?

    Antworten
    1. Helmut (Beitrag Autor)

      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.

      Antworten
  18. Herbert Brandner

    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…

    Antworten
    1. Helmut (Beitrag Autor)

      Ja, dann frei formuliert irgendwie
      if blabla == „nan“ then blabla = „0.0“

      Antworten
  19. Roland

    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

    Antworten
    1. Helmut (Beitrag Autor)

      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

      Antworten
  20. Roland

    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

    Antworten
    1. Helmut (Beitrag Autor)

      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.

      Antworten
  21. Jürgen

    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

    Antworten
  22. Holger D.

    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

    Antworten
  23. Holger D.

    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

    Antworten
  24. Christian

    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

    Antworten
    1. Helmut (Beitrag Autor)

      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

      Antworten

Schreiben Sie einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert