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;
|
In Deinem Beispiel steht der Text wohl ab Adresse 0x69.
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 von einem Moderator gelöscht.
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.
int b=5 liegt bei Adresse 0x89
und float c=1.2 (9A 99 99 3F) liegt bei 0x8D
Warum nutzt du raw-sockets und ?L2?-Broadcast?
Und Daten kann man auch wunderbar und portabel in ASCII verpacken.
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..
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.
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
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 | }
|
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.
Hier habe ich nochmal bool: false und true gesendet.
Welle 🧐 S. schrieb:
> Erst kommen 32 byte für den String (...)
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.
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.
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?
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.
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.
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.
|