Nel precedente articolo abbiamo visto come è possibile inviare pacchetti di advertising con il chip esp32.
Per definire il contenuto del pacchetto, abbiamo utilizzato una struct, di tipo esp_ble_adv_data_t:
La definizione di tale struct è nel file esp_gap_ble_api.h:
Sebbene i campi disponibili siano molti, a volte è necessario poter definire il contenuto del pacchetto di advertising in modo arbitrario. Per questa ragione il framework esp-idf ci mette a disposizione la modalità raw.
Invece che definire una struct, creiamo un array di byte e memorizziamo al suo interno l’intero contenuto del payload del pacchetto:
static uint8_t adv_raw_data[10] = {0x09,0x09,0x4c,0x75,0x6b,0x45,0x53,0x50,0x33,0x32}; |
quindi utilizziamo la funzione esp_ble_gap_config_scan_rsp_data_raw() per passare tale array al driver Bluetooth. Dobbiamo specificare come parametri sia l’array che la sua dimensione:
esp_ble_gap_config_scan_rsp_data_raw(scan_rsp_raw_data, 8); |
Utilizzando questa nuova funzione, cambia anche l’evento che il driver passa alla nostra funzione di callback una volta terminata la configurazione. Il nuovo evento è ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT. Come nell’esempio precedente, quando tale evento si presenta è possibile avviare il processo di advertising:
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: esp_ble_gap_start_advertising(&ble_adv_params); break; |
Raw data
Perché il processo di advertising funzioni, i dati contenuti nell’array devono corrispondere ad un payload valido.
Nell’articolo relativo agli iBeacons vi ho già mostrato la sua struttura. Rivediamola brevemente:
Il payload contiene una o più strutture AD (advertising data). Ogni struttura è formata da 3 campi:
[checklist]
- un byte iniziale che rappresenta la lunghezza (in byte) della struttura, escluso sè stesso
- un byte che rappresenta il tipo di dato contenuto nella struttura
- un numero variabile di byte che sono il dato effettivo
[/checklist]
I codici utilizzabili per definire il tipo di dato si trovano nelle specifiche Bluetooth. In base al tipo di dato, è poi necessario applicare un particolare fomato ai dati che lo seguono. Nel documento Core Specification Supplement (disponibile sempre sul sito Bluetooth.com) si trovano le informazioni necessarie.
Vediamo un semplice esempio: l’AD type 0x09 rappresenta il complete local name, ovvero il nome del dispositivo. Tale nome deve essere specificato nel campo AD data semplicemente come sequenza dei codici ASCII che corrispondono alle diverse lettere.
Possiamo utilizzare un sito web per effettuare la conversione:
Il payload per trasmettere tale nome sarà quindi:
adv_raw_data[7] = {0x06,0x09,0x4d,0x79,0x42,0x4c,0x45}; |
Il primo byte ha il valore 0x06 ovvero la somma della lunghezza del nome (5 byte) + 1 byte per il tipo di dato (0x09).
Demo
Nel video seguente (sottotitoli in italiano disponibili) mostro come utilizzare le funzionalità di raw advertising per simulare il pacchetto di advertising trasmesso dal mio iBeacon e quindi attivare il relay come mostrato nell’esempio precedente.
Il codice sorgente del programma è disponibile nel mio repository Github.
Hey there Luca, thanks for this tutorial as well as all your series. I have a little issue implementing this one though. when I start advertising, a message shows in serial monitor that reads: E (498) BT: bta_gattc_co_cache_addr_init, Line = 333, nvs flash get blob data fail, err_code = 1102. There is no problem with the advertising and data y properly shown on any device. I implemented this tutorial in another project and same thing happens. I used an ESP-WROOM-32 as well as an ESP32-WROVER with same output. Advertising is fine and I can propery advertise data, only problem is this message appearing.
Hi Leonardo, I can’t get the same error message… are you using the latest version of the esp-idf?
Hi. I have both ubuntu and Windows. In Ubuntu, I had the latest toolchain and IDF version as of January, there I have no problems. On Windows, I made a fresh install last week due to the announcement of ESP-MDF. If you may, take a look at these pictures. https://drive.google.com/open?id=1hpr_7uNdJklE-eyygD7xQmbgm8sfZDtI. in (1), I flashed the project on Ubuntu and seems fine. (2) I did the same on windows and you can see the problem. So I restarted to Ubuntu and “monitor” there and problem persist(3). Finally, I copied the project from ubuntu to windows, flash without changing anything, and there’s the problem (4). So I believe is something introduced in the latest IDF.
someone found the solution. There’s a new option in bluedroid settings which causes this message.
https://esp32.com/viewtopic.php?t=5549&sid=c7c61eee6f0c23482a674e99183e43ba#p24069
Not clear on a couple of things. Maybe someone can help?
– Can a custom scan response message be sent to each different device? I need to send a different message to each remote device without connecting. If possible, how do I do it?
– I have multiple iOS software for BLE but I have not been able to find one that displays both the Advertisement data and the scan response data dynamically as it changes at the same time
Hi Philip, I cannot help on iOS apps because I use Android. BLE advertising is sent in broadcast, each device can respond with its own response message. If you need to send messages to specific devices, you have to implement something at application level, for example include an “address” in the adv_data.
can anyone help me i want to broad cast string in order for example i want to broad cast no.1 then after pressing push button it should start advertising np.2 all the time then after again pressing push button it should advertise no.3 all the time