Wie kann man mit ESP8266/ArduinoIDE auf IP-Pakete zugreifen?

OP #5468411
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?
#5468476
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
OP #5475377
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?
Gast #5475481
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).
#5475510
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
OP #5475518
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
Angehängte Dateien:
Gast #5475538
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)
OP #5475555
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]
OP #5475575
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 :-)
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren