ESPNOW Linux!

OP #7811217
Lesenswert?

Hallo Interessierte,

ich bin dabei in einem Projekt Sensordaten (ESP32, ADC) via ESPNOW an einen Linux host zu senden.

Gegeben ist das aktuelle ESPNOW Beispiel:

https://github.com/espressif/esp-idf/blob/master/examples/wifi/espnow/main/espnow_example_main.c

Ich habe lediglich den Payload angepasst:

1
/* Prepare ESPNOW data to be sent. */
2
void example_espnow_data_prepare(example_espnow_send_param_t *send_param)
3
{
4

5
    example_espnow_data_t *buf = (example_espnow_data_t *)send_param->buffer;
6

7
    assert(send_param->len >= sizeof(example_espnow_data_t));
8

9
    buf->type = IS_BROADCAST_ADDR(send_param->dest_mac) ? EXAMPLE_ESPNOW_DATA_BROADCAST : EXAMPLE_ESPNOW_DATA_UNICAST;
10
    buf->state = send_param->state;
11
    buf->seq_num = s_example_espnow_seq[buf->type]++;
12
    buf->crc = esp_crc16_le(UINT16_MAX, (uint8_t const *)buf, send_param->len);
13
    buf->magic = send_param->magic;
14
    
15
    strcpy(buf->a, "THIS IS A CHAR");
16
    buf->b = 5;
17
    buf->c = 1.2;
18
    buf->d = true;
19
}

Auf der Linuxseite läuft das hier:

https://github.com/thomasfla/Linux-ESPNOW/blob/master/wifiRawReceiver/main.c

Was mir dann korrekt das ESPNOW Packet empfängt (WLANif im Monitor mode):

1
len:349
2
----------------------------new packet-----------------------------------
3

4
0x00, 0x00, 0x38, 0x00, 0x2f, 0x40, 0x40, 0xa0, 0x20, 0x08, 0x00, 0xa0, 0x20, 0x08, 0x00, 0x00, 
5
0x74, 0x1c, 0x18, 0x67, 0x01, 0x00, 0x00, 0x00, 0x10, 0x02, 0x6c, 0x09, 0xa0, 0x00, 0xee, 0x00, 
6
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x1b, 0x18, 0x67, 0x00, 0x00, 0x00, 0x00, 
7
0x16, 0x00, 0x11, 0x03, 0xee, 0x00, 0xc0, 0x01, 0xd0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 
8
0xff, 0xff, 0xc4, 0x4f, 0x33, 0x0f, 0xfe, 0x71, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x28, 
9
0x7f, 0x18, 0xfe, 0x34, 0x97, 0xbb, 0x87, 0xad, 0xdd, 0xff, 0x18, 0xfe, 0x34, 0x04, 0x01, 0x00, 
10
0x00, 0x88, 0x02, 0x7e, 0xb7, 0x29, 0xe2, 0xe3, 0xbb, 0x54, 0x48, 0x49, 0x53, 0x20, 0x49, 0x53, 
11
0x20, 0x41, 0x20, 0x43, 0x48, 0x41, 0x52, 0x00, 0x2c, 0x17, 0xc9, 0x86, 0x9a, 0xed, 0xba, 0xe5, 
12
0x87, 0x4d, 0x22, 0x9f, 0x8b, 0xdc, 0xf1, 0xfe, 0xaa, 0x05, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x99, 
13
0x3f, 0x01, 0x36, 0x5d, 0x76, 0xdd, 0xb8, 0xfe, 0x95, 0xc4, 0xac, 0xd2, 0xb5, 0x99, 0xa5, 0xfc, 
14
0x65, 0x06, 0x51, 0x2d, 0xe2, 0xf7, 0x43, 0xa3, 0xdd, 0x12, 0xa2, 0xf4, 0x1c, 0xbf, 0x4b, 0x73, 
15
0x3c, 0x88, 0x7c, 0x3d, 0xf1, 0x07, 0x3d, 0xab, 0x8a, 0x95, 0x5a, 0xd6, 0x73, 0xd3, 0x50, 0x36, 
16
0x15, 0xe7, 0x03, 0x51, 0x1f, 0xf3, 0xee, 0xbc, 0x83, 0x59, 0x21, 0xe3, 0x28, 0x46, 0xf2, 0xa8, 
17
0x3e, 0x19, 0xe8, 0x32, 0xa9, 0x8f, 0x0b, 0xcc, 0x7f, 0xc5, 0xb7, 0xc2, 0x65, 0xf1, 0xba, 0xa9, 
18
0xe3, 0x27, 0x89, 0x12, 0x1c, 0x3a, 0x1f, 0x6d, 0xef, 0x27, 0x0a, 0xb0, 0x52, 0xb3, 0xe7, 0x4a, 
19
0xe3, 0xdf, 0xb2, 0x00, 0xb5, 0xe6, 0x69, 0xae, 0x6d, 0xe2, 0x6d, 0x00, 0xd2, 0xbf, 0x03, 0x90, 
20
0x40, 0x32, 0x13, 0x34, 0xb4, 0x54, 0x1c, 0x8f, 0xdf, 0x8a, 0x03, 0xe8, 0xd0, 0x6f, 0xde, 0x92, 
21
0x5c, 0xba, 0x82, 0xa2, 0xeb, 0xe0, 0xad, 0xfc, 0x92, 0x07, 0x40, 0xd3, 0x31, 0x55, 0x44, 0x75, 
22
0x39, 0x0f, 0x3b, 0xe4, 0xe9, 0xb7, 0xf9, 0xaa, 0xc1, 0x35, 0x09, 0x58, 0xc5, 0xbe, 0x19, 0x8d, 
23
0x8e, 0xd0, 0x8a, 0xae, 0x68, 0x3a, 0x53, 0x4f, 0xed, 0x6a, 0x27, 0x3a, 0x59, 0xc2, 0x6c, 0xf7, 
24
0x88, 0xa8, 0xcd, 0x80, 0x29, 0x78, 0x27, 0xfb, 0xe5, 0xb0, 0x09, 0xf0, 0x5a, 0xdf, 0x7f, 0xae, 
25
0x3d, 0x62, 0x8a, 0x21, 0x8c, 0x14, 0xe2, 0x1c, 0x63, 0x18, 0xb2, 0x56, 0x1b,

Dort finde ich auch folgende Daten wieder:

wifi:mode : sta (c4:4f:33:0f:fe:71) 0xc4, 0x4f, 0x33, 0x0f, 0xfe, 0x71

buf->a, "THIS IS A CHAR"); 0x54, 0x48, 0x49, 0x53, 0x20, 0x49, 0x53, 0x20, 0x41, 0x20, 0x43, 0x48, 0x41, 0x52,

Meine Absender MAC und meinen String (strcpy(buf->a, "THIS IS A CHAR")).

Nun bin ich aber leider am Ende.

Wie finde ich in dem HEX-Packet was ich gesendet habe und bekomme es wieder Sinvoll zusammen?

Siehe a) b) c) d) (Meine Testfälle):

1
/* User defined field of ESPNOW data in this example. */
2
typedef struct {
3
    uint8_t type;                         //Broadcast or unicast ESPNOW data.
4
    uint8_t state;                        //Indicate that if has received broadcast ESPNOW data or not.
5
    uint16_t seq_num;                     //Sequence number of ESPNOW data.
6
    uint16_t crc;                         //CRC16 value of ESPNOW data.
7
    uint32_t magic;                       //Magic number which is used to determine which device to send unicast ESPNOW data.
8
    char a[32];
9
    int b;
10
    float c;
11
    bool d;
12
} __attribute__((packed)) example_espnow_data_t;
Beitrag #7811230 wurde von einem Moderator gelöscht.
OP #7811344
Lesenswert?

G. K. schrieb:

Warum nutzt du raw-sockets und ?L2?-Broadcast? Und Daten kann man auch wunderbar und portabel in ASCII verpacken.

Hallo Zumsel, der Trick by ESPNOW ist das die die Packete in einem nackten 802.11 Frame übertragen ohne Protokoll ... das ist sehr schnell (usec) und leichtgewichtig ... allersings passen nur 250byte rein, was für Sensordaten/Steuerbefehle mehr als genug ist ... es geht natürlich nur Headsup - allerdings draussen bis 100m (500m mit Antennengewinn), indoor je nach Bausubstanz..

Angehängte Dateien:
#7811752
Lesenswert?

Ich stand schon vor einem ähnlichen Problem, habe es aber dann mit einem "Gateway" auf einem eigenen ESP32 Modul gelöst (Übertragung dann via UART2). Und wenn ich sehe, dass man die Frames mehr oder weniger problemlos mitschneiden und "spoofen" kann, bin ich im Nachhinein froh, dass ich Verschlüsselung und Authentifizierung gleich mit in das übergeordnete Protokoll eingebaut habe.

Ursprünglich hatte ich übrigens BLE vorgesehen, das hat aber letztendlich viel längere "On" Zeiten auf den batteriebetriebenen Sensoren verursacht.

Jörg

OP #7811986
Lesenswert?

Joerg W. schrieb:

Und wenn ich sehe, dass man die Frames mehr oder weniger problemlos mitschneiden und "spoofen" kann, bin ich im Nachhinein froh, dass ich Verschlüsselung und Authentifizierung gleich mit in das übergeordnete Protokoll eingebaut habe.

Hallo Jörg, klar kannste die mitschneiden, es sind Broadcast :) Unicast sind natürlich verschlüsselt.

Unicast ist mir aber zu Aufwändig, weill man Schlüssel und MACs austauschen/hinterlegen muss.

1
    if (IS_BROADCAST_ADDR(des_addr)) {
2
        /* If added a peer with encryption before, the receive packets may be
3
         * encrypted as peer-to-peer message or unencrypted over the broadcast channel.
4
         * Users can check the destination address to distinguish it.
5
         */
6
        ESP_LOGD(TAG, "Receive broadcast ESPNOW data");
7
    } else {
8
        ESP_LOGD(TAG, "Receive unicast ESPNOW data");
9
    }
OP #7812232
Lesenswert?

Sieht gut aus, die Positionen scheinen fest.

Erst kommen 16 byte für den String und dann je 2byte für INT,FLOAT,BOOL. Ganz oben die MAC vom ESP32.

1
// Structure example to send data
2
// Must match the receiver structure
3
typedef struct struct_message 
4
{
5
  char a[32];
6
  int b;
7
  float c;
8
  bool d;
9
} struct_message;

Warum die Werte INT,FLOAT,BOOL Rückwärts im Buffer stehen, keine Ahnung.

Angehängte Dateien:
#7812313
Lesenswert?

Das kennt ihr? https://hackaday.io/project/161896-linux-espnow/log/154698-how-esp-now-really-works

Bzw den beschriebenen Frame Aufbau: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html

Ich würde mir vermutlich kurz einen Dissector für Wireshark schreiben. Dann kann man einfach Mal so mithören und das Zeug sich vernünftig anschauen. Den Dissector kannst du später dann auch in deiner eigenen Applikation nutzen.

#7812462
Lesenswert?

Welle 🧐 S. schrieb:

ist es das was Du meinst?

Ne nicht wirklich. Aber geht vermutlich auch. Viele Wege führen nach Rom.

Ich setze mir bei so Sachen gerne einen Lua Dissector auf. Nicht weil ich Lua mag, sondern weil es dann Plattform unabhängig ist: https://wiki.wireshark.org/lua/dissectors Zum anschauen, analysieren, filtern usw echt praktisch.

TShark kann mit dem gleichen Dissector auch JSON/XML o.ä. streamen. Wenn man sich dann an den Stream hängt hat man die Daten in seiner Applikation ohne selbst wissen zu müssen wie sie dissectiert werden müssen.

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