Serielle Daten mit dynamischer Länge empfangen und in Struct schreiben

Hallo Zusammen !

Ich möchte serielle Daten meiner Heizung (hier Ebus) in ein struct schreiben.
Problem: Die empfangenen Daten haben immer eine dynamische Länge.

Wie kann ich das Array (dat) im Struct dynamisch vergrößern und verkleinern ?

Hier mein bisheriger Code:

#define RXD2 16
#define TXD2 17

#define SYN 0xAA;

bool paketRec  = false;
int i;
int j;
int k;

struct eBus
{
  uint8_t qq;
  uint8_t zz;
  uint8_t pb;
  uint8_t sb;
  uint8_t nn;
  uint8_t dat[9]; // Maximale Anzahl der Bytes habe ich erstmal fest vergeben
  uint8_t crc;
} eData;

void setup() 
{
  Serial.begin(9600);
  Serial2.begin(2400, SERIAL_8N1, RXD2, TXD2);
}

void loop() 
{
  // Empfangene Daten in struct einlesen
  bytes2Struct();

  
  if(paketRec)
  {
    Serial.print("Quelle:");
    printHex(eData.qq);
    Serial.print("-");
    Serial.print("Ziel:");
    printHex(eData.zz);
    Serial.print("-");
    Serial.print("Befehl:");
    printHex(eData.pb);
    printHex(eData.sb);
    Serial.print("-");
    Serial.print("Bytes:");
    Serial.print(eData.nn);
    Serial.print("-");
    Serial.print("Data:"); 
    for(k=0; k< sizeof eData.dat / sizeof *eData.dat; k++) // Daten können hier dynamisch ausgegeben werden
    {
      printHex(eData.dat[k]);
    }
    Serial.print("-");
    Serial.print("CRC:");
    printHex(eData.crc);
    Serial.println("");
  }
}


void bytes2Struct()
{
  struct eBus *p_eBus;
  p_eBus = &eData;
  
  uint8_t sBuffer;
  
  paketRec = false;
  if(Serial2.available()) 
  {
     sBuffer = Serial2.read();

     if(sBuffer != SYN)
     {
      printHex(sBuffer);
      switch(i)
      {
        case 0 : 
          p_eBus->qq = sBuffer;
          i++;
        break;
        case 1 : 
          p_eBus->zz = sBuffer;
          i++;
        break;
        case 2 : 
          p_eBus->pb = sBuffer;
          i++;
        break;
        case 3 : 
          p_eBus->sb = sBuffer;
          i++;
        break;
        case 4 : 
          p_eBus->nn = (int) sBuffer; // Anzahl der nachfolgenden Bytes (Größe die das Feld "eBus.dat" haben müsste)
          i++;
        break;
        case 5 : // Hier werden die Daten gesammelt
          if(j < (p_eBus->nn - 1))
          {
            if(j == 0)
            {
              memset(p_eBus->dat, 0, sizeof(p_eBus->dat)); // Array leeren
            }
            p_eBus->dat[j] = sBuffer;
            j++;
          }
          else
          {
            p_eBus->dat[j] = sBuffer;
            j = 0;
            i++;
          }
        break;
        case 6 :
          p_eBus->crc = sBuffer;
          i++;
        break;
      }
     }
     else
     {
      if(i > 0) // data finish
      {
        paketRec = true;
        Serial.println("");
      }
      i = 0;
     }
  }
}

void printHex(uint8_t x) {
  if (x <= 0x0F) Serial.print("0");
  Serial.print(x,HEX);    
}

Welcher Arduino?
Besser ist die Verwendung eines Puffers mit der maximal möglichen Länge.
Gibt es Anfangs- und Endekennzeichen?

Gruß Tommy

Es ist ein NodeMCU v4 (ESP32)
Anfang ist, wenn Serial2 nicht mehr 0xAA (SYN) empfängt.
Die Anzahl der Bytes habe ich ja, aber, aber erst bei case 4.

Ich müsste bei case 4 oder spätestens 5 die Länge des Arrays (neu) deklarieren.
Geht sowas ?

Du wirst doch wohl eine Info haben oder ermitteln können, wie lang die Message maximal wird.
Ansonsten versuche das mit String abzufrühstücken, der verlängert sich dynamisch.
Ob Du damit glücklich wirst, wirst Du merken.

Bei eigenen Maßnahmen mit dynamischer Speichererweiterung sollte man genau wissen, was man tut.

Der ESP32 hat eigentlich genug RAM, da kann man auch mal 256 oder 512 Bytes als Puffer reservieren.

Gruß Tommy

Wie kann ich das Array (dat) im Struct dynamisch vergrößern und verkleinern ?

In dem du den Speicher dynamisch reservierst.
(das war kein Tipp)

thomas1984:
Es ist ein NodeMCU v4 (ESP32)

Dann nimm doch einen der dynamischen C++ Container anstatt eines C-Array.

Die Idee mit dem String ist schon Mal sehr gut ! Vielen Dank.

Wie lang die Nachricht ist, weiß ich ja. Problem ist nur, das ich nicht weiß, wie ich das Array anpasse.
Gern würde ich folgendes machen:

Array auf maximale Größe deklarieren
uint8_t dat[8]; (Mehr als 9 Bytes sind es nicht)

Im switch case 4 habe ich die tatsächliche Anzahl der Daten-Bytes
z.B. bei einer Anzahl von 4 Daten-Bytes würde ich gerne das Array neu mit uint8_t dat[3]; initialisieren,

oder in case 5 befülle ich das Array mit den Daten
hier könnte ich auch die 4 Daten in das Array schreiben, aber die entferne ich die anderen 4 Indexe, damit
ich das Array wieder richtig mit size of zählen kann ?

@combie
Hast du evtl. ein Beispiel ? Ich denke das geht mit malloc oder realloc, aber ich bekomme es einfach nicht zusammen. Immer wenn die IDE nicht mehr meckert, stürzt der ESP32 mit "crash with realloc() pointer is outside heap areas" ab.

thomas1984:
uint8_t dat[8]; (Mehr als 9 Bytes sind es nicht)

Aua!!

Dann spar dir das mit dem dynamischen Speicher. Das lohnt sich nicht wirklich. Statt dessen kann man zusätzlich abspeichern wie viele Bytes tatsächlich verwendet werden

Derfips:
Aua!!

Ganz großes AUA.

@TO: Nimm einen Puffer von 10 Bytes und merke Dir die Länge aus case 4. Bei den paar Bytes ist dynamisch völliger Unsinn.

Gruß Tommy

Ok.
Danke an Alle !