MiFlora Modul

Ich probiere auch mit dem ESP herum aber bei mir läuft das leider nicht sehr zuverlässig. Ich habe fünf Sensoren in unmittelbarer Nähe des ESP und er „sieht“ davon nur 2-3 und meldet diese einmalig an den MQTT-Server von IPS. Zwei davon werden mehr oder weniger regelmäßig aktualisiert, einer nicht - obwohl dieser gerade mal einen Meter entfernt ist. Ein parallell laufender Pi3 findet alle diese Sensoren aber und aktualisiert sie in IPS.

Kann einen Pi Zero empfehlen. Habe 2 davon mit je 8 Sensoren in einem selbstgebauten wasserdichen Gehäuse im Freien laufen und habe gute 15m Reichweite.
Läuft recht stabil mit dem MiFlora nach MQTT script.
BG
hoep

Gesendet von iPhone mit Tapatalk

Folgendes (zusammengesuchtes) Beispiel zum Suchen einer Pflanze:


<?php

$f = "_plantdb.csv";

$assoc_array = [];
if (($handle = fopen($f, "r")) !== false) {                   // open for reading
    if (($data = fgetcsv($handle, 1000, ",")) !== false) {    // extract header data
        $keys = $data;                                        // save as keys
    }
    while (($data = fgetcsv($handle, 1000, ",")) !== false) { // loop remaining rows of data
        $assoc_array[] = array_combine($keys, $data);         // push associative subarrays
    }
    fclose($handle);                                          // close when done
}

$plant = 'cherry tomato pepe f1';
$key = array_search($plant, array_column($assoc_array, 'pid'));

print_r($assoc_array[$key]);

Das Array ist assoziativ, also mit den Feldnamen, meine Suche geht auf „pid“.

Der Key im Originalfile ist 923, das entspricht nicht der Zeile, da es in den Textfeldern ("") diverse Zeilenumbrüche gibt.


Array
(
    [pid] => cherry tomato pepe f1
    [display_pid] => Cherry Tomato Pepe F1
    [alias] => cherry tomato pepe f1
    [image] => http://pkb.resource.huahuacaocao.com/Y2hlcnJ5IHRvbWF0byBwZXBlIGYxLmpwZw==?imageView2/1/w/%d/h/%d
    [floral_language] => Lycopersicon esculentum
Floriography: brave, patient, joyous
Is also called cherry tomato, has both ornamental values and edibility. 
The fruits are juicy, red or orange, smaller than regular tomato, cute and exquisite, the plant is short, fast growth, full of nutrients, is a good option for home vegetable gardening. 
Likes strong sunlight, fruit setting within one month after flowering for 2-3 months.
    [origin] => South America
    [production] => China
    [category] => Solanaceae, Solanum
    [blooming] => Ornamental fruit and vegetable plants, planted year around, fruits 1 month after flowering, fruiting period 1-3 months
    [color] => Flower color yellow, fruit color red, orange yellow
    [size] => Diameter ≥ 10 cm, height ≥ 15 cm
    [soil] => Peat or soil with specific nutrients
    [sunlight] => Like strong light
    [watering] => Keep soil moist, water and drain timely
    [fertilization] => Dilute fertilizers following instructions, apply 2-3 times monthly
    [pruning] => Remove dead and yellowish leaves timely
    [max_light_mmol] => 16000
    [min_light_mmol] => 4800
    [max_light_lux] => 130000
    [min_light_lux] => 3500
    [max_temp] => 32
    [min_temp] => 10
    [max_env_humid] => 70
    [min_env_humid] => 30
    [max_soil_moist] => 65
    [min_soil_moist] => 20
    [max_soil_ec] => 2000
    [min_soil_ec] => 350
)

Die JSON Dateien vom anderen Link sind scheinbar weniger Pflanzen, dafür enthalten sie base64 encoded Bilder, weshalb die Einzeldatei relativ groß sind.

Das mir „weniger Pflanzen“ ist natürlich Quatsch, wer lesen kann…

> we had to truncate this directory to 1,000 files.
> 4,539 entries were omitted from the list.

Hallo Ralf,

ich Danke Dir. Jetzt kriege ich wenigstens ein korrektes Array. und die Suche funktioniert auch. Werde aber in die CSV-Datei noch eine Spalte einfügen mit dem deutschen Namen der Pflanzen und einige Formatierungen korrigieren. Ansonsten Hammer. Vielen Dank. Jetzt komme ich hier auch weiter.

Mein Ziel wäre es, wenn ich den Namen im MQTT-Klienten vergebe und er die Instanz über den Configurator anlegt:

Einblatt = C4:7C:8D:64:1B:01

Das er dann automatisch nach dem Namen in der csv-Datei sucht und die Felder befüllt.

Gruß

Burkhard

Habe mir die ZIP runter geladen und es sind alle drin.

Hallo Nall-chan,

da der ESP die Daten ja auch an den MQTT-Server schickt (genau wie mein RPI3) sollte das kein Problem sein.

Eine Frage: Die Lösung mit dem ESP32, wenn ich die Instanz über den MQTT-Configurator erstellen lasse, legt er dann die Variablen einzeln an, oder musst DU diese dann auch noch splitten und in die einzelnen Variablen schreiben?

Gruß

Burkhard

Einzeln.
Typ und Profil muss man aber anpassen, sonst ist ja immer alles String :smiley:
Michael

Hallo Ralf,

es macht mehr Sinn, nach dem Alias zu suchen. Bei pid und display_pid hast Du unterschiedliche Schreibweisen bei den einzelnen Pflanzen. Unterarten werden in pid und display_pid zum Beispiel so geschrieben: „spathiphyllum 'bingo cupido“ in dem Alias ohne die Apostrophs

Gruß

Burkhard

@hoep

Den hatte ich laufen. Aber (fast) jedes mal wenn hier der Strom ausfällt - nicht Schuld des Versorgers sondern z.B Spezi in der Steckdosenleiste wenn der Sohn mal wieder am zocken ist - durfte ich das Image neu auf die SD-Karte einspielen weil der Zero nicht mehr gebootet hat. PXE ist keine Option da WLAN und der Zero kann das sowieso nicht wirklich. Deswegen schien der ESP eine optimale Option da absolut gegen Stromausfälle sicher, klein, günstig, MQTT - perfekt…

@kronos
Ok -hier auch schon 2x passiert. Hatte das auf die SD Karte geschoben…
BG hoep

Gesendet von iPad mit Tapatalk

Moin

Hast du die EMERGENCY_HIBERNATE an die Anzahl deiner Sensoren angepasst?

Ich bin gerade dabei die ESP Firmware noch etwas robuster zu machen, da ich ab und an mal sehr absurde Werte bekomme. Aber an sich läuft es bei mir sehr stabil mit mqtt.

Wenn das Interesse da ist und sich jemand findet der aus dem ganzen in ein nettes Modul verpackt kann ich auch gerne die Firmware des ESP anpassen so das die Ausgabe der Raspberry Pi MQTT Variante entspricht.

Viele Grüße
Ralf

Wenn du die Ausgabe so lässt, braucht es doch gar kein Modul in IPS.
Ich wollte bei der Firmware eigentlich auch hand anlegen, nur leider null Zeit dafür.
Finde das etwas unglücklich, dass die MAC Adresse der Sensoren hard konfiguriert werden müssen.
Michael

So, die ersten Schritte sind erfolgreich verlaufen. Dank Eurer Hilfe habe ich jetzt das folgende Script:

<?php

$csv = "/home/pi/Download/Pflanzen.CSV";

$assoc_array = [];
if (($handle = fopen($csv, "r")) !== false) {                   // open for reading
    if (($data = fgetcsv($handle, 1000, ";")) !== false) {    // extract header data
        $keys = $data;                                        // save as keys
    }
       while (($data = fgetcsv($handle, 1000, ";")) !== false) { // loop remaining rows of data
        $assoc_array[] = array_combine($keys, $data);         // push associative subarrays
    }
    fclose($handle);                                          // close when done
}

$plant = 'spathiphyllum bingo cupido';
$key = array_search($plant, array_column($assoc_array, 'alias'));

$array = array($assoc_array[$key]);

SetValue (42183, ($array[0]["pid"]));
SetValue (48509, ($array[0]["alias"]));
SetValue (46020, ($array[0]["max_env_humid"]));
SetValue (33354, ($array[0]["max_light_lux"]));
SetValue (53736, ($array[0]["max_soil_ec"]));
SetValue (53890, ($array[0]["max_soil_moist"]));
SetValue (13710, ($array[0]["max_temp"]));
SetValue (59397, ($array[0]["min_env_humid"]));
SetValue (29005, ($array[0]["min_light_lux"]));
SetValue (45716, ($array[0]["min_soil_ec"]));
SetValue (32355, ($array[0]["min_soil_moist"]));
SetValue (21942, ($array[0]["min_temp"]));

Ergibt dann das hier:

Grundlage ist die Datei: Pflanzen.CSV, die ich als ZIP mal hier anhänge. Jetzt erstmal auf Dienstreise. Nächste Woche setze ich mich ran, damit die Variablen automatisch erstellt werden. Für Ideen, Tipps bin ich immer dankbar.

Gruß

Burkhard

Pflanzen.zip (22 Bytes)

@heschdy

Hast du die EMERGENCY_HIBERNATE an die Anzahl deiner Sensoren angepasst?

Nein, ich hatte das auf dem vorgegebenen Wert belassen. Was für einen Wert hältst Du da für sinnvoll?

Hallo*,

ich habe das Script jetzt soweit, dass er die Variablen anlegt, das fehlende Profil für die Bodenfeuchtigkeit erstellt und dann im Anschluss je nach eingetragener Pflanze die Werte in die Variablen schreibt. Dazu muß das Script direkt unter die MQTT-Instanz gesetzt werden.

Ich weiß nicht, ob man es hätte einfacher oder besser machen können und würde mich freuen, wenn einer der Cracks mal drüber schauen könnte und mir evtl. Tipps zur Script-Gestaltung geben könnte. Ich fange dann doch nach 11 Jahren Symcon-Einsatz mal an, php zu lernen. :o

<?php
// Hier die gesuchte Pflanze mit lateinischem Namen eingeben

$plant = 'abies amabilis';

// Daten ermitteln in CSV-Datenbank

$csv = "/home/pi/Download/Pflanzen.CSV";                                        // Dateipfad an eigene Umgebung anpassen
$assoc_array = [];
if (($handle = fopen($csv, "r")) !== false) {                                   // Datei öffnen zum lesen
    if (($data = fgetcsv($handle, 1000, ";")) !== false) {                      // Kopfdaten holen
        $keys = $data;                                                          // Speichern als "Keys"
    }
       while (($data = fgetcsv($handle, 1000, ";")) !== false) {                // Wiederholen für alle Daten
        $assoc_array[] = array_combine($keys, $data);                           // Erstellen der Subarrays
    }
    fclose($handle);                                                            // Schließen, wenn fertig
}

// Erstellen fehlendes Profil "Leitfähigkeit"

if (IPS_VariableProfileExists("MiFlora_Conductivity") ===false) {               // Prüfen, ob Profil existent
    IPS_CreateVariableProfile("MiFlora_Conductivity",2);                        // Profil erstellen
    IPS_SetVariableProfileText("MiFlora_Conductivity", "", " µs/cm");           // Profil Messeinheit definieren
    IPS_SetVariableProfileValues("MiFlora_Conductivity", 0, 1000, 100);         // Profil Messgrenzen und Schritte festlegen
}

// Anlegen einer neuen Kategorie "Normwerte"

$id = IPS_GetParent($_IPS['SELF']);
$childid = @IPS_GetCategoryIDByName("Normwerte", $id);
    if ($childid === false){                                                    // Prüfen, ob Kategorie existiert
        $CatID = IPS_CreateCategory();                                          // Kategorie anlegen
        IPS_SetName($CatID, "Normwerte");                                       // Kategorie benennen
        IPS_SetParent($CatID, $id);                                             // Kategorie einsortieren unter dem Objekt mit der ID "12345"
    }

// Anlegen der Variablen

$id = IPS_GetParent($_IPS['SELF']);
$kategorie = $KategorieID = @IPS_GetCategoryIDByName("Normwerte", $id);

$Name = array(  "DAT_Pflanzenname" => 3,                                        // Array mit Variablen-Name und Variablentyp
                "DAT_Pflanzenname_Alias"=> 3,
                "DAT_Luftfeuchtigkeit_max"=> 2,
                "DAT_Luftfeuchtigkeit_min" => 2,
                "DAT_Helligkeit_lux_max" => 2,
                "DAT_Helligkeit_lux_min" => 2,
                "DAT_Leitfähigkeit_max" => 2,
                "DAT_Leitfähigkeit_min" => 2,
                "DAT_Bodenfeuchtigkeit_max" => 2,
                "DAT_Bodenfeuchtigkeit_min" => 2,
                "DAT_Temperatur_max" => 2,
                "DAT_Temperatur_min" => 2);

foreach ($Name as $Variable=>$Typ) 
        {                                 
        $Setname = $Variable;
        $KategorieID = IPS_GetCategoryIDByName("Normwerte", $id);               // Kategorie abrufen
        $childid = @IPS_GetVariableIDByName($Setname, $kategorie);
        if ($childid === false){                                                // Prüfen, ob Variablen existieren -> Ja => überspringen, nein => anlegen
            $Variable = IPS_CreateVariable($Typ);                               // Variablen erstellen und Typ vergeben
            IPS_SetName($Variable, $Setname);                                   // Variable benennen
            IPS_SetParent($Variable, $KategorieID);                             // Variable einsortieren unter dem Objekt mit der ID "$KategorieID (Normwerte)"
            }
        }

// Zuteilen der Profile

$id = IPS_GetParent($_IPS['SELF']);
$kategorie = @IPS_GetCategoryIDByName("Normwerte", $id);                        // Prüfen der richtigen Kategorie 

$Prof = array(  "DAT_Luftfeuchtigkeit_max"=> "~Humidity.F",                     // Array mit Variablenname und Profil-Typ
                "DAT_Luftfeuchtigkeit_min" => "~Humidity.F",
                "DAT_Helligkeit_lux_max" => "~Illumination.F",
                "DAT_Helligkeit_lux_min" => "~Illumination.F",
                "DAT_Leitfähigkeit_max" => "MiFlora_Conductivity",
                "DAT_Leitfähigkeit_min" => "MiFlora_Conductivity",
                "DAT_Bodenfeuchtigkeit_max" => "~Humidity.F",
                "DAT_Bodenfeuchtigkeit_min" => "~Humidity.F",
                "DAT_Temperatur_max" => "~Temperature",
                "DAT_Temperatur_min" => "~Temperature");

foreach ($Prof as $Var_Prof=>$Profil) {
            
        $VariableID = IPS_GetVariableIDByName($Var_Prof,$kategorie);            // Variablen-IDs abrufen
        IPS_SetVariableCustomProfile($VariableID,$Profil);                      // Variablen Profil zuweisen
        };

// Befüllen der Variablen

$key = array_search($plant, array_column($assoc_array, 'pid'));                 // Ermitteln der Werte zur Pflanze
$array = array($assoc_array[$key]);                                             // Erstellen des Arrays
SetValue (IPS_GetVariableIDByName("DAT_Pflanzenname",$kategorie), ($array[0]["pid"]));
SetValue (IPS_GetVariableIDByName("DAT_Pflanzenname_Alias",$kategorie), ($array[0]["alias"]));
SetValue (IPS_GetVariableIDByName("DAT_Luftfeuchtigkeit_max",$kategorie), ($array[0]["max_env_humid"]));
SetValue (IPS_GetVariableIDByName("DAT_Helligkeit_lux_max",$kategorie), ($array[0]["max_light_lux"]));
SetValue (IPS_GetVariableIDByName("DAT_Leitfähigkeit_max",$kategorie), ($array[0]["max_soil_ec"]));
SetValue (IPS_GetVariableIDByName("DAT_Bodenfeuchtigkeit_max",$kategorie), ($array[0]["max_soil_moist"]));
SetValue (IPS_GetVariableIDByName("DAT_Temperatur_max",$kategorie), ($array[0]["max_temp"]));
SetValue (IPS_GetVariableIDByName("DAT_Luftfeuchtigkeit_min",$kategorie), ($array[0]["min_env_humid"]));
SetValue (IPS_GetVariableIDByName("DAT_Helligkeit_lux_min",$kategorie), ($array[0]["min_light_lux"]));
SetValue (IPS_GetVariableIDByName("DAT_Leitfähigkeit_min",$kategorie), ($array[0]["min_soil_ec"]));
SetValue (IPS_GetVariableIDByName("DAT_Bodenfeuchtigkeit_min",$kategorie), ($array[0]["min_soil_moist"]));
SetValue (IPS_GetVariableIDByName("DAT_Temperatur_min",$kategorie), ($array[0]["min_temp"]));

Vielen Dank für Eure Unterstützung hier im Forum.

Update: Erste Optimierungen eingebaut. Das Skript prüft vor Anlegen von Kategorie, Variablen und Profil, ob diese bereits vorhanden sind. Sind sie vorhanden, wird Profil vergeben und befüllt. Sind sie nicht vorhanden, werden sie angelegt und dann mit Profil versehen und gefüllt.

Gruß

Burkhard

Moin,

default ist meine ich 3 x 60 sec. Ein Polling eines sensors dauert im Fehlerfall 20sec es wird standardmäßig 3 x wiederholt und das Array an Sensoren immer von oben durchgearbeitet. D.h. wenn du da bei 5 Sensoren nur 3x60sec hast werden wenn die ersten drei nicht erreichbar sind die verbleibenden nie abgefragt…

Also meinEmpfehlung wäre Anzahl an MAC Adressen x 60.

Mal eine grundsätzliche Verständnisfrage zu diesen Sensoren:
(ich bin nicht so der Bluetooth-Profi)

Wenn ich es richtig verstehe, werden die Sensoren sowohl in der ursprünglichen Variante von Spoosie als auch bei allen nachfolgenden Raspberry- oder ESP-Sketches regelmäßig gepollt. So läuft es auch bei mir seit Jahren problemlos.
Und es scheint mir auch deutlich so zu sein, dass die Batterien der Xiami-Sensoren nicht sehr lange halten, wenn ich die Sensoren bspw. alle 15min abfrage. Mit Abfrage alle 6 Stunden reichen die Batterien hingegen etwa über ein Jahr…

Jetzt könnte man sagen, dass für die Trägheit der Pflanze ein Wert alle 6 Stunden völlig reicht, ABER…

a) lese ich im Web überall (z.B. bei der Umsetzung mit ioBroker), dass die User UMGEHEND aktuelle Werte bekommen, sobald der Sensor einen neuen Wert ermittelt (etwa direkt nach dem Gießen). Das fände ich schon toll… ich habe hier immer für viele Stunden nach dem Gießen immer noch die Warnmeldungen in der Visu.

b) ich möchte meine ESP32-Devices zukünftig auch nach Bluetooth-Beacons (G-Tag o.ä.) suchen lassen. D.h. die Bluetooth-Suche auf dem ESP32 oder Raspberry läuft nahezu permanent in kurzer Frequenz - und nichtmehr nur alle x Stunden. Wird mir das dann nicht die Xiamo-Batterien kurzfristig leersaugen?

Danke vorab für Auflösung meines Gedankenknotens :wink:

Ich antworte mir mal selbst, da ich mich etwas schlau gelesen habe:
die Antwort auf meine Frage ist schlichtweg, dass es zwei unterschiedliche Ansätze gibt, die MiFlora abzufragen.

Nennen wir es mal „aktiv“ oder „passiv“. Letzteres baut überhaupt keine Connection zum Miflora auf und liest nur die Advertising-Daten, welche das Modul ohnehin ständig sendet (und Temperatur,Leitfähigkeit,Feuchtigkeit bereits beinhaltet). Egal wie häufig ich diese Advertising-Daten einlese, es belastet die Batterie der MiFloras genau NULL! Einziger kleiner Nachteil: in einigen Firmware-Versionen wird wohl der Batteriestatus nicht mitübertragen, hier müsste dann erst eine Connection aufgebaut werden.
Und es soll wohl sehr schwierig sein, auf einer Hardware wie ESP32 oder Raspberry den aktiven und passiven Modus „gleichzeitig“ zu realisieren. Ich für meinen Teil könnte dann notfalls auf die Batteriedaten verzichten :wink:

Jetzt muss ich mal sehen, wie ich diesen Denkansatz umgesetzt bekomme… ich strebe einen ESP32 oder Raspberry mit MQTT-Übermittlung an… auf ESP32-Basis am Liebsten mit Tasmota, hier ist die Bluetooth-Unterstützung aber noch sehr Beta.

Wenn irgendwer Ideen hat, immer her damit… ansonsten würde ich mich auch über Unterstützung freuen (Tasmota32 hab ich noch nie selbst from Scratch gebaut, da habe ich noch Lernkurve vor mir).

ESP32 mit Tasmota und MiFlora wurde vorhin im Discord mit Screenshots erfolgreich gezeigt :slight_smile:
Bin aber auch gespannt wie sich das entwickelt, weil ich kannte nur das nicht Tasmota Projekt mit dem ESP32 welches immer aktiv abfragte.
Michael