Forum: Mikrocontroller und Digitale Elektronik Wie kann man mit ESP8266/ArduinoIDE auf IP-Pakete zugreifen?


von Florian W. (florenzw)


Lesenswert?

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?

von Michael U. (amiga)


Lesenswert?

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
von Florian W. (florenzw)


Lesenswert?

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.

von Michael U. (amiga)


Lesenswert?

Hallo,

Danke für den Link, hebe ich mir mal auf, wer weiß, wozu das mal gut 
ist.

Gruß aus Berlin
Michael

von Florian W. (florenzw)


Lesenswert?

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
von Stefan F. (Gast)


Lesenswert?

Das Arduino Framework behandelt IP Verbindungen als Stream. Das 
Versenden oder Empfangen von Paketen ist bei Arduino nur mit UDP 
vorgesehen.

von devzero (Gast)


Lesenswert?

Einfach NULL wenn Du keine Daten uebergeben moechtest.
Er uebergibt im Beispiel den this-pointer, damit er im Callback auf das 
Objekt zugreifen kann.

von devzero (Gast)


Lesenswert?

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).

von Michael U. (amiga)


Lesenswert?

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
von Florian W. (florenzw)


Angehängte Dateien:

Lesenswert?

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

von devzero (Gast)


Lesenswert?

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)

von Florian W. (florenzw)


Lesenswert?

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
von Florian W. (florenzw)


Lesenswert?

Es funktioniert! Es läuft! Genaueres kommt gleich...

von Florian W. (florenzw)


Angehängte Dateien:

Lesenswert?

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
Noch kein Account? Hier anmelden.