Ich spiele gerade mit einem ESP8266 / NodeMCU und der ArduinoIDE. HTTP und UDP funktionieren wunderbar. Ich suche eine Möglichkeit IP-Pakete (kein TCP), die an die IP-Adresse des ESP8266 gesendet werden, (am besten mit Header) zu empfangen, zu analytischen Zwecken über die Serielle auszugeben und an eine andere IP-Adresse weiter zu schicken. Mehrere Stunden WWW-umgraben haben bis jetzt nichts funktionierendes zu Tage befördert. Mir ist bekannt, dass beim ESP8266 der TCP/IP protocol stack integriert ist. Hat jemand eine Idee, wie man trotzdem an die untere Schicht des Datenverkehrs ran kommt?
Hallo, die Sourcen und Headerdateien des lwip-Stacks sind doch im SDK dabei und müßte prinzipiell auch aus der Arduino-IDE auf die Funktionen zugreifen können. Bei anderen Systemfunktionen des SDK geht das ja auch, eben darauf achten, daß das alles C ist was man da einbindet. Auf die Strukturen in ip.h müßte man zumindest lesend ohne unlösbare Probleme zugreifen können. Ist aber nicht direkt meine Baustelle, zu lange her, daß mich IP-Header mal interessiert haben... Gruß aus Berlin Michael
:
Bearbeitet durch User
Hallo Michael, lwip-Stack war das Stichwort, danke. Ich habe auf: https://yoursunny.com/t/2018/PacketDump/ ein funktionierendes Beispiel gefunden, das alle Pakete abgreift, die durch den Äther fliegen.
Hallo, Danke für den Link, hebe ich mir mal auf, wer weiß, wozu das mal gut ist. Gruß aus Berlin Michael
Meine Hobbyprogrammierkünste stoßen gerade an ihre Grenzen :-) Ich versuche über die raw_rec()-Funktion der lwIP-lib an die rohen Ethernet Pakete zu gelangen. Dazu habe ich auch ein schönes Beispiel gefunden: https://www.arduinolibraries.info/libraries/esp8266-ping Hier wird raw_rec() innerhalb der class Pinger so aufgerufen:
1 | // When LWIP detects a packet corresponding to specified protocol control
|
2 | // block, the PingReceivedStatic callback is executed
|
3 | raw_recv( |
4 | m_IcmpProtocolControlBlock, |
5 | PingReceivedStatic, |
6 | (void *)this); |
Ich würde jetzt gerne raw_recv() ausserhalb von Pinger in meiner setup-function aufrufen:
1 | void setup() { |
2 | ...
|
3 | raw_pcb* protokolControlBlock = raw_new(IP_PROTO_ICMP); |
4 | if (protokolControlBlock == nullptr) { |
5 | Serial.println("Beim Erstellen des protokolControlBlocks ist was schiefgegangen"); |
6 | } else { |
7 | Serial.println("Das Erstellen des protokolControlBlocks hat funktioniert"); |
8 | }
|
9 | |
10 | raw_bind(protokolControlBlock, IP_ADDR_ANY); |
11 | |
12 | raw_recv(protokolControlBlock, packedReceived, (void *)this); |
13 | }
|
Da ich jetzt nicht mehr innerhalb einer class bin, funktioniert 'this' nicht: invalid use of 'this' in non-member function Wie muss ich raw_recv() aufrufen? Was muss da anstatt (void *)this rein?
:
Bearbeitet durch User
Das Arduino Framework behandelt IP Verbindungen als Stream. Das Versenden oder Empfangen von Paketen ist bei Arduino nur mit UDP vorgesehen.
Einfach NULL wenn Du keine Daten uebergeben moechtest. Er uebergibt im Beispiel den this-pointer, damit er im Callback auf das Objekt zugreifen kann.
1 | raw_recv_fn |
2 | typedef u8_t(* raw_recv_fn) (void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) |
3 | Function prototype for raw pcb receive callback functions. |
4 | |
5 | Parameters |
6 | arg user supplied argument (raw_pcb.recv_arg) |
7 | pcb the raw_pcb which received data |
8 | p the packet buffer that was received |
9 | addr the remote IP address from which the packet was received |
10 | Returns |
11 | 1 if the packet was 'eaten' (aka. deleted), 0 if the packet lives on If returning 1, the callback is responsible for freeing the pbuf if it's not used any more. |
Aus der Doxygendoku von lwIp - diesen Callback musst Du implementieren. arg ist dann einfach NULL (bzw. nullptr).
Hallo, Stefanus F. schrieb: > Das Arduino Framework behandelt IP Verbindungen als Stream. Das > Versenden oder Empfangen von Paketen ist bei Arduino nur mit UDP > vorgesehen. meinst Du damit, mein Bekannter hätte z.B. sowas garnicht machen dürfen? Beitrag "Re: Esp32 Bluetooth Audio" ESP32 BT ist im Arduino Framework bisher nämlich fast garnicht eingebaut... Gruß aus Berlin Michael
:
Bearbeitet durch User
devzero schrieb: > Einfach NULL wenn Du keine Daten uebergeben moechtest. > Er uebergibt im Beispiel den this-pointer, damit er im Callback auf das > Objekt zugreifen kann. Super, hat mich ein Stückchen weiter gebracht! Jetzt bin ich hier:
1 | u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) |
2 | {
|
3 | Serial.println("packedReceived Funktionsaufruf"); |
4 | return 0; |
5 | }
|
6 | |
7 | void setup() { |
8 | ...
|
9 | raw_bind(protokolControlBlock, IP_ADDR_ANY); |
10 | |
11 | raw_recv(protokolControlBlock, packedReceived, NULL); |
12 | }
|
Das ganze Programm habe ich rangehängt. Und das führt zu folgenden Fehlermeldungen: ESP8266_WiFiClient:9: error: expected primary-expression before '*' token u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: 'pcb' was not declared in this scope u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: expected primary-expression before '*' token u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: 'packetBuffer' was not declared in this scope u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: expected primary-expression before 'const' u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: expression list treated as compound expression in initializer [-fpermissive] u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: redefinition of 'u8_t packedReceived' u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: 'u8_t packedReceived' previously defined here u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: expected primary-expression before '*' token u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: 'pcb' was not declared in this scope u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: expected primary-expression before '*' token u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: 'packetBuffer' was not declared in this scope u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ ESP8266_WiFiClient:9: error: expected primary-expression before 'const' u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) ^ /home/florian/Arduino/ESP8266_WiFiClient/ESP8266_WiFiClient.ino: In function 'void setup()': ESP8266_WiFiClient:52: error: invalid conversion from 'u8_t {aka unsigned char}' to 'raw_recv_fn {aka unsigned char (*)(void*, raw_pcb*, pbuf*, ip_addr*)}' [-fpermissive] raw_recv(protokolControlBlock, packedReceived, NULL); ^ In file included from /home/florian/Arduino/ESP8266_WiFiClient/ESP8266_WiFiClient.ino:3:0: /home/florian/.arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/s dk/lwip/include/lwip/raw.h:84:18: error: initializing argument 2 of 'void raw_recv(raw_pcb*, raw_recv_fn, void*)' [-fpermissive] void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)ICACHE_FLASH_ATTR; ^ exit status 1 expected primary-expression before '*' token
1 | u8_t packedReceived(NULL, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) |
da darf natuerlich nicht NULL stehen, schreib da mal void* arg hin. arg zeigt dann auf die Adresse, die Du im raw_recv() uebergibts (in diesem Fall NULL) Also:
1 | u8_t packedReceived(void* arg, raw_pcb * pcb, pbuf * packetBuffer, const ip_addr_t * addr) |
devzero schrieb:
1 | > u8_t packedReceived(void* arg, raw_pcb * pcb, pbuf * packetBuffer, const |
2 | > ip_addr_t * addr) |
Es geht voran, danke devzero. Die Anzahl der Fehlermeldungen ist deutlich geschrumpft :-) /home/florian/Arduino/ESP8266_WiFiClient/ESP8266_WiFiClient.ino: In function 'void setup()': ESP8266_WiFiClient:52: error: invalid conversion from 'u8_t (*)(void*, raw_pcb*, pbuf*, const ip_addr_t*) {aka unsigned char (*)(void*, raw_pcb*, pbuf*, const ip_addr*)}' to 'raw_recv_fn {aka unsigned char (*)(void*, raw_pcb*, pbuf*, ip_addr*)}' [-fpermissive] raw_recv(protokolControlBlock, packedReceived, NULL); ^ In file included from /home/florian/Arduino/ESP8266_WiFiClient/ESP8266_WiFiClient.ino:3:0: /home/florian/.arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/s dk/lwip/include/lwip/raw.h:84:18: error: initializing argument 2 of 'void raw_recv(raw_pcb*, raw_recv_fn, void*)' [-fpermissive] void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)ICACHE_FLASH_ATTR; ^ exit status 1 invalid conversion from 'u8_t (*)(void*, raw_pcb*, pbuf*, const ip_addr_t*) {aka unsigned char (*)(void*, raw_pcb*, pbuf*, const ip_addr*)}' to 'raw_recv_fn {aka unsigned char (*)(void*, raw_pcb*, pbuf*, ip_addr*)}' [-fpermissive]
:
Bearbeitet durch User
Es funktioniert! Es läuft! Genaueres kommt gleich...
Das ist der funktionierende Sketch. Er muss mit lwIP Variant V2 kompiliert werden! Kann man in der Arduino-IDE unter "Werkzeuge" einstellen. ... hatte V1.4 eingestellt, mit der geht's nicht. Jetzt sehe ich im seriellen Monitor für jeden Ping: packedReceived Funktionsaufruf Hurra! Jetzt kann ich weiter forschen :-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.