ESP RGBWW Controller - Firmware v5

Begonnen von pjakobs, 01 Januar 2025, 21:14:31

Vorheriges Thema - Nächstes Thema

pjakobs

manchmal dauert es etwas länger dafür wird es etwas mehr.

Die letzte experimental Version war weiterhin enorm instabil, so sehr, dass ich wieder auf die letzte develop zurück gegangen bin.
Der Hintergrund war: viele große json Strukturen, die ich mit ArduinoJSON erzeugt hatte.
ArduinoJSON ist toll, aber es kann halt auch keinen Speicher erzeugen wo keiner ist, und weil es intern ein komplettes DOM (Document Object Model) im RAM hält und daraus beim Serialisieren einen String macht, braucht es immer mehr als die doppelte tatsächliche Größe des json Strings.

Das hat an einigen Stellen dazu geführt, dass nicht der Heap, sondern der Stack nicht ausgereicht hat. Wenn der Heap voll ist, dann scheitert ein
malloc - das lässt sich meistens abfangen, aber wenn der Stack überläuft stürzt der Controller meist einfach hart ab.

Nch langem hin und her und dem Versuch, eine eigene streaming Json Klasse zu schreiben ist Mike, der Entwickeler der Sming ConfigDB wieder eingesprungen und wir haben die Library so umgebaut, dass sie json-rpc, das hier nötige Protokoll, aus einem vorgegebenen Schema bauen kann. Jetzt liegen alle strukturellen Teile der Json Struktur im Schema und damit im Flash, nur noch die veränderlichen Daten werden im RAM gehalten.

Beispiel:
ein Color Request sieht im Schema so aus:
{
            "type": "object",
            "title": "color",
            "$comment": "body for the color request/response and the color_event notification; a colour is always raw XOR hsv",
            "oneOf": [
                { "$ref": "params/$defs/raw" },
                { "$ref": "params/$defs/hsv" }
            ]
        }

raw und hsv sind als Datentypen so beschrieben:
    "raw": {
      "type": "object",
      "properties": {
        "r": { "$ref": "value-types/$defs/raw-value" },
        "g": { "$ref": "value-types/$defs/raw-value" },
        "b": { "$ref": "value-types/$defs/raw-value" },
        "ww": { "$ref": "value-types/$defs/raw-value" },
        "cw": { "$ref": "value-types/$defs/raw-value" }
      }
    },
    "hsv": {
      "type": "object",
      "properties": {
        "h": { "$ref": "value-types/$defs/hue-value" },
        "s": { "$ref": "value-types/$defs/percentage-value" },
        "v": { "$ref": "value-types/$defs/percentage-value" },
        "ct": { "$ref": "value-types/$defs/color-temperature" }
      }
wenn ich jetzt eine json-rpc message senden will, um einen hsv Wert zu setzen, dann sieht das etwa so aus:
{
    "jsonrpc":"2.0",
    "method":"color",
    "params":
    {
        "hsv":
        {
            "h":0,
            "s":87,
            "v":58,
            "ct":0
        }
    }
}

Die ConfigDB Methode hält dabei nur die Zahlenwerte im RAM, was deutlich sparsamer ist.
Bei diesem kleinen Beispiel ist das noch nicht so wesentlich, aber etwa die /info Struktur ist knapp ein kByte und das ist dann unter Umständen zu viel für den 8266.

Im Moment ist nur das Erzeugen (serialisieren) von json Strukturen auf ConfigDB umgestellt, der Code kann auch das umgekehrte: eine als String oder Stream ankommende json Struktur deserialisieren und die entsprechenden Werte zugänglich machen. Das ist der nächste Step, der auch nochmal ein bisschen Speicher sparen sollte.

Die aktuelle Version ist als V5.0.0-967-experimental über das OTA zu haben.

Desweiteren herzliches Dankeschön an @2space, der das Lightinator-HA-Modul getestet und zwei Fehler gemeldet hat, die sind jetzt, hoffe ich, auch behoben (für Home Assistant habe ich keine gute Testumgebung).

Das Modul ist unter https://github.com/pljakobs/Lightinator_HA_Module zu finden.

Grüße

pj


pjakobs

RAM ist immer noch ein Problem, aber es wird besser.
Ich staune immer mehr, was alles auf einem ESP8266 mit maximal 30kB freiem Heap möglich ist - aber auch wo die Grenzen sind.
Ich fürchte, ich hab es schon einmal gesagt, aber: Experimental nähert sich der Brauchbarkeit, nachdem ich hier eine Weile mit sehr unzuverlässigen Leuchten gelebt habe wird es jetzt wieder besser, aber leider noch nicht wirklich gut.

Das Problem ist: vieles in der ESP Firmware verlässt sich darauf, genug Speicher zu haben, und wenn das nicht zutrifft, crasht das Gerät leider, im Moment ist das nicht mehr häufig in meinem Code oder im Sming Code, sondern irgendwo viel weiter unten, LWIP oder sogar im ESP Wifi Stack.

Aber: immerhin kann ich jetzt Stack Traces von gecrashten Controllern decodieren, weil ich Code eingebaut habe, der, wenn der Controller crasht, den Stackdump lokal in den Speicher der Real Time Clock schreibt (der ist einerseits direkt und ohne Umweg über ein Dateisystem etc. beschreibbar, andererseits übersteht er einen reboot).
Nach dem Reboot schaut die Firmware dann, ob ein Crashdump vorhanden ist, und schickt den über rsyslog an einen Server, der ihn dann auswertet, ein Beispiel ist im Anhang.

Aber es bleibt wie es ist: RAM ist ein Problem auf den kleinen Geräten.
Sobald ich die aktuelle experimental Version wieder stabil hab, muss ich wohl oder übel aufhören, Code für den 8266 hinzuzufügen, das Teil ist komplett ausgereizt. Alle weiteren Funktionen werden dann wohl Esp32 only sein.

pj

vbs

Super Trick mit dem Speichern in der RTC  8)

pjakobs

einfach und effektiv. Ich hab schon überlegt, das in eine kleine Library zu gießen. Die ganze CrashDump Struktur sind 240 Bytes, die kann man dann auch locker über mqtt verschicken und so prima remote Crash analyse machen.