UDP packet (packetBuffer) zerlegen?

Hallo zusammen,

ich bin gerade dabei mich in die UDP Übertragung einzuarbeiten.
Dafür hab ich mich hier und da schon eingelesen und vor allem auf fipsok.de die Beispiele nachvollzogen.
Ich schicke vorweg ich bin nicht der Mega C Programmierer. Habe mir bis jetzt das Meiste durch lesen oder probieren selbst beigebracht.
Die Beispiel im TAB Esp8266 UDP Spezial klappen eigentlich alle!

Jetzt steh ich aber für mich vor einem Problem

Der Sender sendet zum Beispiel durch diese Zeile:
Udp.printf("Temperatur: %.2f°C", tempC);
die Funktion deren Inhalt der „Name“ und der eigentliche Temperatur wert ist.

Der Empfänger gibt in dem Beispiel aber lediglich den ganzen packetBuffer seriell aus.

Nun meine Frage:
Wie kann ich die Funktion
Udp.printf("Temperatur: %.2f°C", tempC);
bzw. den packetBuffer auf der Empfängerseite wieder zerlegen um sie weiter zu verarbeiten?

Möchte sozusagen wissen was für ein Wert zum Beispiel Temperatur, Luftfeuchte,…

gesendet wurde und die dazugehörige Zahl dann weiter verarbeiten um irgendetwas zu steuern.

Abgesehen davon, daß ein für uns Menschen gut lesbarer Text für so ein Vorhaben ungünstig ist, schaue Dir mal sscanf an.

Besser wäre ein an sich schon strukturierte Zeichenkette, wie sie beispielsweise von JSON verwendet wird oder in CSV-Dateien üblich ist.

Das taugt nur für ein kompaktes Demo.

Wenn du mehrere Zahlen senden möchtest dann macht es Sinn die gaaaanz anders zusammenzusetzen

Wenn es denn wichtig ist eine Betitelung der Zahl zu haben
Temperatur:12,34;Feuchte:56,78%;

In diesem Aufbau gibt es jetzt charakteristische Zeichen die die Einzelteile voneinander trennen:
Ein Zeichen nach dem Doppelpunkt Zahlenwert beginnt
Strichpunkt da ist die Zahl zu Ende und die Nächste Betitelung beginnt

Ein Zeichen nach dem Doppelpunkt Zahlenwert beginnt
Strichpunkt da ist die Zahl zu Ende

Man scannt also die Zeichenkette auf den Doppelpunkt auf Strichpunkte
scanf macht das

Poste mal wie deine zusammengesetzten Daten aussehen

vgs

Einfacher geht es wenn man statt "Temperatur:" nur "T" schreibt. Ein Buchstabe. Dann kann man einfach switch/case verwenden. Und hat auch sofort den Anfang der Zahl um sie zu Konvertieren.

1 Like

Hi, danke für die schnellen Infos.

ich hab bis jetzt nur die Beispiele von Fips...
Ich hab eben einen Temepraturwert eines DS18B20 und ein Lichtmesser in Lux (anderen Sensor hatte ich nicht).

Beides sind float Zahlen.

Das mit : und ; hab ich verstanden.

Ich will nur irgendwie auseinander halten was ich schicke...
Ich müsste die Werte auch nicht einmal zusammen schicken...
Aber auch wenn ich die nacheinander schicke...
Woher weiß der Empfänger was ich geschickt habe?

Wenn du ein Telegram mit beiden Zahlen sendest weiß er es aus der Reihenfolge. Man braucht aber trotzdem ein Trennzeichen oder konstante Länge.

Wenn du zwei Telegramme sendest dann könntest du als erstes Zeichen "T" wie Temperatur senden oder "L" wie Lux.
Dann untersucht man das erste Zeichen.

Wenn du das jetzt noch näher auseinander klamüsert haben willst dann musst du mal deinen code als code-section posten
You can post code by using this method that adds the code-tags
There is an automatic function for doing this in the Arduino-IDE
just three steps

  1. press Ctrl-T for autoformatting your code
  2. do a rightclick with the mouse and choose "copy for forum"
  3. paste clipboard into write-window of a posting

best regards Stefan

Einmal mit Trennzeichen und einmal mit zwei Telegrammen:

void setup()
{
  Serial.begin(9600);

  char str[] = "21.3;15.0";
  Serial.print("Temp: ");
  Serial.println(atof(strtok(str, ";")));
  Serial.print("Feuchte: ");
  Serial.println(atof(strtok(NULL, ";")));

  Serial.println("---------");            
  
  parseData("T25.3");
  parseData("F10.0");
}

void loop ()
{
}

void parseData(const char* str)
{
  switch(str[0])
  {
    case 'T':
      Serial.print("Temp: ");
      Serial.println(atof(str + 1));
      break;
    case 'F':
      Serial.print("Feuchte: ");
      Serial.println(atof(str + 1));
      break;
  }
}

Die Konvertierung nur um die Zahl gleich auszudrucken ist unsinnig. Aber man kann das natürlich auch abspeichern.

Hi,
alles soweit verstanden.
Aber ich glaub ich steh auf dem Schlauch...
Mir geht nicht runter wieder Empänger IN dem Paket filtern kann?

Ich hab echt noch keinen eigenen Code. Nur das von Fips...
und an der Stelle an der gesendet wird steht

void sendUdp(float tempC) {
  Udp.beginPacket(unicastIP, PORT);
  Udp.printf("Temperatur: %.2f°C", tempC);
  Udp.endPacket();

uh wow. Sehr kompakt programmiert und schönes Beispiel für strok

Wie gesagt, für print() kann man atof() auch weglassen, da man den Teil-String auch so direkt ausgeben kann.

Normal macht man eher sowas:

float temp = atof(strtok(str, ";"));

Jetzt poste halt mal was dieses Demoprogramm auf der Empfängerseite im seriellen Monitor ausgibt

Achso, sorry...
Einfach den kompletten packetBuffer im Seriellen Monitor...

void loop() {
  uint16_t packetSize = Udp.parsePacket();              // Eingehende UDP-Pakete empfangen.
  if (packetSize) {                                     // Prüfen ob UDP-Pakete empfangen wurden.
    Udp.read(packetBuffer, sizeof(packetBuffer));       // Einlesen des UDP Paket in den Bufffer.
    packetBuffer[packetSize] = 0;                       // String Ende hinzufügen.
    Serial.println(packetBuffer);                       // Visualisierung des empfangenen Packets.

Aber ich glaub ich probier morgen mal mit den Infos von euch herum!!!

Vielen Dank!!!

möglichst kompakt = schwerer zu verstehen

Auseinander gezogen = leichter zu verstehen


float myTemp;
float myFeuchte;


void setup() {
  Serial.begin(9600);

  char str[] = "21.3;15.0";
  myTemp    = atof(  strtok(str, ";")  );
  myFeuchte = atof(  strtok(NULL, ";") );
  Serial.print("Temp: ");
  Serial.println(myTemp);
  Serial.print("Feuchte: ");
  Serial.println(myFeuchte);

  Serial.println("---------");            
  
  parseData("T25.3");
  parseData("F10.0");
}

void loop ()
{
}

void parseData(const char* str) {
  switch(str[0]) {
    
    case 'T':
      myTemp = atof(str + 1);
      Serial.print("Temp: ");
      Serial.println(myTemp);
      break;
      
    case 'F':
      myFeuchte = atof(str + 1);
      Serial.print("Feuchte: ");
      Serial.println(myFeuchte);
      break;
  }
}

In #2 habe ich sscanf vorgeschlagen, hier jetzt das mit einem ESP32 getestete Programm dazu:

void setup()
{
  Serial.begin(115200);
  Serial.println("\nStart");
}

void loop() {
  float tempC = random(1500, 2500) / 100.0;
  char packetBuffer[30] = {"\0"};
  snprintf( packetBuffer, sizeof(packetBuffer), "Temperatur: %.2f°C", tempC);
  Serial.print(packetBuffer);
  Serial.print('\t');
  float t = 0;
  sscanf (packetBuffer,"%*s %f°C", &t);
  Serial.println(t);
  delay(1000);
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.