Hallo, ich habe hier ein Projekt wo ein ESP32 via UDP Datenpackete
empfängt und dann Dinge tut.
ICh habe das so gelösst, dass ich den Empfangssspuffer parse und wenn es
passt entsprechend reagiere.
Mir gefällt das irgendwie nicht, weil das eine grosse Liste werden kann.
Kann man das besser machen? Case, swich?
1
if(strstr(rx_buffer,tasklist_start)!=NULL)
2
{
3
char*filter_msg="tasklist_start";
4
char*d=strstr(rx_buffer,tasklist_start);// pointer to start of "... "
5
6
7
task_monitor();
8
}
9
10
if(strstr(rx_buffer,km)!=NULL)
11
{
12
char*filter_msg="km";
13
char*d=strstr(rx_buffer,km);// pointer to start of "... "
Moin,
Welle 🧐 S. schrieb:> Mir gefällt das irgendwie nicht, weil das eine grosse Liste werden kann.> Kann man das besser machen? Case, swich?
Davon wird aber doch die Liste nicht kleiner oder?
Gruss
WK
Welle 🧐 S. schrieb:> ICh habe das so gelösst, dass ich den Empfangssspuffer parse
Du suchst strings wie "tasklist_start" im UDP-Paket? Kannst du den
Sender modifizieren, sodass er nur einzelne Bytes statt ganzer Strings
mit dem jeweiligen "Befehl" sendet? Das wäre einfacher und effizienter
zu parsen und würde auch kürzere Pakete bedeuten.
Welle 🧐 S. schrieb:> Mir gefällt das irgendwie nicht, weil das eine grosse Liste werden kann.> Kann man das besser machen? Case, swich?
Du könntest einen statt je 2 Aufrufe machen. Und die Liste verkleinern,
wenn Du n von n Pattern ausgelesen hast. So ganz erschließt sich mir
nicht, was Du mit filter_msg machen möchtest. Oder was z.B. km tut.
PS: Wenn C++ eine Option ist (funktioniert problemlos mit ESP-IDF oder
ESP-Arduino) kann man das mit Lambdas hübscher, kompakter und effizient
umsetzen. In C ginge noch was mit Makros.
Meinst du eigentlich mit ANSI-C das, was man üblicherweise darunter
versteht, nämlich C89? Für die ESP32 nutzt man das normalerweise
nicht, lässt sich das ESP-IDF damit überhaupt übersetzen? Das ESP-IDF
nutzt per Default C17. Oder meinst du einfach eine aktuelle
standardisierte C-Version, wie eben C17?
Die ANSI hat seit C90 ja einfach die ISO-Standards für C übernommen,
also rein technisch ist C23 (standardisiert allerdings in 2024) der
aktuelle ANSI-C Standard, aber niemand nutzt den Begriff so, sondern
nutzt ANSI-C als Alias für C89.
Niklas G. schrieb:> Welle 🧐 S. schrieb:>> ICh habe das so gelösst, dass ich den Empfangssspuffer parse>> Du suchst strings wie "tasklist_start" im UDP-Paket? Kannst du den> Sender modifizieren, sodass er nur einzelne Bytes statt ganzer Strings> mit dem jeweiligen "Befehl" sendet? Das wäre einfacher und effizienter> zu parsen und würde auch kürzere Pakete bedeuten.
Um in die gleiche Kerbe zu schlagen: ist es wirklich möglich (vom
Protokoll her) daß z.B. "tasklist_start" an beliebiger Stelle im
UDP-Paket steht? Oder ist es nicht vielmehr so, daß ein UDP-Paket vom
Typ tasklist_start mit "tasklist_start" beginnt?
Man kann eine Tabelle mit Einträgen aus String und FunctionPointer
machen. Dann im Dispatcher in der Tabelle nach dem String suchen und bei
Erfolg den zugehörigen FP aufrufen.
In C++ etwas eleganter mit den Container Klassen, z.B. std::map was für
so Key Value Zugehörigkeiten gemacht ist.
Niklas G. schrieb:> Du suchst strings wie "tasklist_start" im UDP-Paket? Kannst du den> Sender modifizieren, sodass er nur einzelne Bytes statt ganzer Strings> mit dem jeweiligen "Befehl" sendet? Das wäre einfacher und effizienter> zu parsen und würde auch kürzere Pakete bedeuten.
Hallo Niklas, ja der Sender ist ein Linux.
Strings fand ich auch nicht prall ich habe nur keine andere Idee und
es ist leicht zu tracken, weil klarlext.
Bruno V. schrieb:> wenn Du n von n Pattern ausgelesen hast. So ganz erschließt sich mir> nicht, was Du mit filter_msg machen möchtest. Oder was z.B. km tut.
Hallo Bruno, ich habe der Übersichthalber was gegelassen ;)
Dann könnte man auch gleich json als Standardformat nehmen, mit
ArduinoJson gibt es ja eine sehr gute Lib die das Handling damit sehr
angenehm macht. Die Parameter per str Funktionen aufzudröseln ist auch
eine fehleranfällige Sache.
Niklas G. schrieb:> Oder meinst du einfach eine aktuelle> standardisierte C-Version, wie eben C17?>> Die ANSI hat seit C90 ja einfach die ISO-Standards für C übernommen,> also rein technisch ist C23 (standardisiert allerdings in 2024) der> aktuelle ANSI-C Standard, aber niemand nutzt den Begriff so, sondern> nutzt ANSI-C als Alias für C89.
Genau :) ich bin davon ausgegangen dass das keiner so im Details drauf
hat :)
Axel S. schrieb:> Um in die gleiche Kerbe zu schlagen: ist es wirklich möglich (vom> Protokoll her) daß z.B. "tasklist_start" an beliebiger Stelle im> UDP-Paket steht? Oder ist es nicht vielmehr so, daß ein UDP-Paket vom> Typ tasklist_start mit "tasklist_start" beginnt?
Hallo Axel, nein das kann ich frei entscheiden. Aktuell steht nur der
Funktionsaufruf in dem Packet.
J. S. schrieb:> Dann könnte man auch gleich json als Standardformat nehmen, mit> ArduinoJson gibt es ja eine sehr gute Lib die das Handling damit sehr> angenehm macht. Die Parameter per str Funktionen aufzudröseln ist auch> eine fehleranfällige Sache.
Ja, ich war nur zu faul auf der Absenderseite ein JSon Packet zu formen,
weil es ja nur simple Ein/Aus Anforderungen sind.
Json kann ich in dem Projekt auch verarbeiten. Aber das Parst auch nur
Strings.
https://github.com/sheredom/json.h
Welle 🧐 S. schrieb:> Aber das Parst auch nur Strings.
Wenn Du unbedingt auf das Parsen von Strings verzichten möchtest, mach
es mit Zahlen:
Definiere ein Funktionspointer-Array, f[] initialisiere dieses mit
Deinen aufzurufenden Funktionen. Dann brauchst Du nur eine Zahl n zu
übertragen - bei max. 256 Funktionen sogar nur ein Byte.
Dann ist der Aufruf auf dem Zielsystem:
1
(*f[n])();
Einfacher gehts nicht. Kryptischer aber auch nicht.
Welle 🧐 S. schrieb:> Mir gefällt das irgendwie nicht, weil das eine grosse Liste werden kann.> Kann man das besser machen? Case, swich?
Ja kann man machen. Theoretisch, kannst alles in eine Array von Struktur
packen, und sagen dass ein Stück Code dann alle elemente deine Array
vorknüpft und guckt ob der String dann passt, wenn ja dann wird eine
Funktionspointer aufgerufen.
Soetwas, mehr oder weniger:
typedef void (*Callback)(void);
typedef struct _MyDummyStruct {
const char findString[];//bin nicht sicher ob das so compiliert
Callback callback;
} MyDummyStruct;
MyDummyStruct myDummyStruct[2] = {
{"tasklist_start", &task_monitor},
{"km", &callback_2},
};
for (int x = 0; x < (sizeof(myDummyStruct) / sizeof(*myDummyStruct));
x++) {
if(strstr(rx_buffer, myDummyStruct[x].findString) != NULL)
{
char *d = strstr(rx_buffer, myDummyStruct[x].findString);
if (myDummyStruct[x].callback != NULL) {
myDummyStruct[x].callback();
}
}
}
void task_monitor(void) {
}
void callback_2(void) {
}
Ich lasse das strcmp einfach in einer Schleife über eine Tabelle aus
Befehlswort und Funktionsadresse laufen.
Die Tabelle endet mit einem Leerstring:
1
command_tconstcmd_table[]=
2
{
3
{MODULE_CMD_UPTIMEcmd_uptime},
4
{MODULE_CMD_GETSTATUScmd_status},
5
{MODULE_CMD_RESETcmd_reset},
6
{"",0},
7
};
Das Befehlswort ist als Macro definiert. Somit ist garantiert, daß man
sich nicht verschreiben kann, d.h. Sender und Empfänger importieren es
aus dem gleichen h-File.
Peter D. schrieb:> Ich lasse das strcmp einfach in einer Schleife über eine Tabelle aus> Befehlswort und Funktionsadresse laufen.> Die Tabelle endet mit einem Leerstring:
Danke Peter, dass greife eich auf!
Niklas G. schrieb:> Die ANSI hat seit C90 ja einfach die ISO-Standards für C übernommen,
Es ist genau umgekehrt: Die ISO hat den ANSI-Standard übernommen. C89
war ein ANSI-Standard. C90 ist praktisch 1:1 das gleiche, aber von der
ISO. Alle nachfolgenden Versionen kamen dann ebenfalls von dort.
> also rein technisch ist C23 (standardisiert allerdings in 2024) der> aktuelle ANSI-C Standard,
Nein, es ist der aktuelle ISO-Standard.
> aber niemand nutzt den Begriff so, sondern nutzt ANSI-C als Alias für> C89.
Weil eben nur C89 tatsächlich von ANSI kam.
Rolf M. schrieb:> Die ISO hat den ANSI-Standard übernommen.
Den ersten, ja.
Rolf M. schrieb:> Nein, es ist der aktuelle ISO-Standard.
Ja. Aber auch der aktuelle Standard nach ANSI, denn die ANSI hat den
ISO-Standard ratifiziert, während sowohl ISO als auch ANSI den
originalen Standard C89 zurückgezogen haben.
Eben so wie die DIN auch ENs übernimmt.
Peter D. schrieb:> Ich lasse das strcmp einfach in einer Schleife über eine Tabelle aus> Befehlswort und Funktionsadresse laufen.
So hätte ich es auch gemacht und hatte jojos oben schon vorgeschlagen.
Geht einfach, ist gut lesbar und das ohne C++ ;)
Niklas G. schrieb:> Rolf M. schrieb:>> Nein, es ist der aktuelle ISO-Standard.>> Ja. Aber auch der aktuelle Standard nach ANSI, denn die ANSI hat den> ISO-Standard ratifiziert, während sowohl ISO als auch ANSI den> originalen Standard C89 zurückgezogen haben.
Man kann ihn auch bei ANSI im webstore kaufen, aber er heißt dort
trotzdem
ISO/IEC 9899 und nicht ANSI X3.159. Sprich: Es ist kein ANSI-Standard,
sondern ein ISO-Standard, den man lediglich auch bei ANSI kaufen kann.
Auf
https://blog.ansi.org/c-programming-language-standard-iso-iec-9899-2024/
heißt es dann auch:
"While it originated in the 70s, the existing practices of C were
unified and expanded upon in the standard ANSI X3.159-1989, or C89.
Because of these origins, many people still call the C programming
language standard ANSI C. However, the C standard was adopted
internationally in 1990, and it has long been ISO/IEC 9899, which is
developed by ISO/IEC JTC 1. The integration of C practices into an
international standard sparked its association with the name ISO C."