Forum: Mikrocontroller und Digitale Elektronik ESPNOW Linux!


von Welle 🧐 S. (w3llschmidt)


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;

: Bearbeitet durch User
von Christoph M. (mchris)


Angehängte Dateien:

Lesenswert?

In Deinem Beispiel steht der Text wohl ab Adresse 0x69.

: Bearbeitet durch User
von Welle 🧐 S. (w3llschmidt)


Lesenswert?

Danke Christoph!

Ok mit festen Adressen könnte man arbeiten.
Aber den Rest finde ich nicht :(
1
    strcpy(buf->a, "THIS IS A CHAR");
2
3
    buf->b = 5;
4
5
    buf->c = 1.2;
6
7
    buf->d = true;

Beitrag #7811230 wurde vom Autor gelöscht.
von Christoph M. (mchris)


Lesenswert?

Ich bin mir nicht sicher, ob die Adresse immer gleich ist. Eine mögliche 
Lösung wäre, die Daten am  mit einer Magic-Number zu versehen und diese 
im Empfangsframe zu suchen.

von Christoph M. (mchris)


Lesenswert?

int b=5 liegt bei Adresse 0x89
und float c=1.2 (9A 99 99 3F) liegt bei 0x8D

von G. K. (zumsel)


Lesenswert?

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

: Bearbeitet durch User
von Welle 🧐 S. (w3llschmidt)


Angehängte Dateien:

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

: Bearbeitet durch User
von G. K. (zumsel)


Lesenswert?

Welle 🧐 S. schrieb:

> 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

Tu was du nicht lassen kannst.

von Joerg W. (joergwolfram)


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

von Welle 🧐 S. (w3llschmidt)


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
    }

von Welle 🧐 S. (w3llschmidt)


Angehängte Dateien:

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.

: Bearbeitet durch User
von Welle 🧐 S. (w3llschmidt)


Angehängte Dateien:

Lesenswert?

Hier habe ich nochmal bool: false und true gesendet.

von Welle 🧐 S. (w3llschmidt)


Lesenswert?

Welle 🧐 S. schrieb:
> Erst kommen 32 byte für den String (...)

von J. S. (jojos)


Lesenswert?

Welle 🧐 S. schrieb:

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

Passt doch, xtensa (und auch X86 und Cortex-M) hat little endianness.

von N. M. (mani)


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.

von Welle 🧐 S. (w3llschmidt)


Angehängte Dateien:

Lesenswert?

N. M. schrieb:
> 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.

Hallo Mani,

ist es das was Du meinst?

: Bearbeitet durch User
von N. M. (mani)


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.

von Welle 🧐 S. (w3llschmidt)


Angehängte Dateien:

Lesenswert?

Danke für den Anstoss mit Wireshark, ich habe vorher die ganze Zeit 
gehirnt warum mein Packet nicht wie das bei Espressif beschrieben 
aussieht :)

Das ganze Radiotap Geraffel hatte ich verdrängt.

: Bearbeitet durch User
von N. M. (mani)


Lesenswert?

Kein Ding.
Ich finde Wireshark was Protokolle angeht immer genial.
Nicht nur für Ethernet WLAN...

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.