ESP32 (32) – BLE, iBeacon

luca 05/03/2018 16

Nel precedente articolo ho introdotto la tecnologia Bluetooth Low Energy e il processo di advertising.

Abbiamo visto che un dispositivo BLE può sfruttare i pacchetti di advertising per inviare dati; in tal caso il dispositivo viene chiamato broadcaster, mentre i dispositivi che ricevono i dati sono chiamati observers.

Il payload di un pacchetto di advertising ha la seguente struttura:

ibeacon-002

ADV ADDR è l’indirizzo MAC del dispositivo (indirizzo che veniva visualizzato in console dal programma sviluppato nel precedente articolo), mentre ADV DATA è un campo, lungo un massimo di 31 bytes, organizzato in una o più strutture formate da 3 elementi:

  • AD length è la lunghezza complessiva (in bytes) della singola struttura dati
  • AD type è il tipo di informazione riportata in tale struttura
  • AD data è l’informazione

Il sito ufficiale del Bluetooth Special Interest Group riporta l’elenco dei possibili AD types.

Un dispositivo può ad esempio trasmettere il proprio nome utilizzando l’AD type 0x09:

ibeacon-003

Durante lo scan, il driver Bluetooth mette a disposizione del programma i dati (ADV DATA) ricevuti nell’array scan_result->scan_rst.ble_adv. Tale array contiene valori uint8_t ed ha dimensione scan_result->scan_rst.adv_data_len.

La libreria Bluedroid contiene un metodo, esp_ble_resolve_adv_data(), che consente di ottenere il valore di un particolare AD type passando i dati grezzi (raw data). Il file di header esp_gap_ble_api.h contiene anche la definzione degli AD types più comuni:

ibeacon-004

Nel mio repository Github trovate una nuova versione del programma che effettua lo scan: utilizzando quanto spiegato sopra ora estrae anche – se disponibile – il nome del device e lo visualizza in console:

ibeacon-009

iBeacon

Una particolare famiglia di dispositivi broadcasters sono gli iBeacon. Tali dispositivi sono stati pensati da Apple per consentire interazioni con dispositivi IOS (iPhone…) basati sulla location awareness. Facciamo un esempio: un telefono iPhone può “accorgersi” di essere vicino ad un particolare iBeacon, associato ad una stanza di un museo, e proporre all’utente la visualizzazione di una breve guida delle opere esposte.

ibeacon-001

Le specifiche dei dispositivi iBeacon si trovano sul portale sviluppatore Apple. Gli iBeacon funzionano inserendo nei pacchetti di advertising un particolare payload (ADV DATA):

ibeacon-006

Il primo dato inviato è di tipo flags (0x01). Ogni bit ha un diverso significato, tipicamente gli iBeacon utilizzano il valore 0x0A.

Il secondo dato inviato è di tipo 0xFF, ovvero Manufacturer Specific Data. Lo standard Bluetooth lascia liberi i vari produttori di usare l’ID 0xFF per inviare dati custom. I dati inviati hanno lunghezza 25 bytes (0x1A – 0x01 che è la lunghezza del campo AD type).

Le specifiche Apple per gli iBeacon suddividono ulteriormente il campo AD data in diversi elementi:

ibeacon-008

Il primo campo indica il produttore; normalmente gli iBeacon utilizzano il codice 0x004C, assegnato ad Apple Inc. I successivi due indicano il tipo di iBeacon e hanno valore fisso (0x02 e 0x15). Il campo UUID, insieme con i campi Major e Minor (facoltativi, possono essere impostati a 0) identificano univocamente il singolo iBeacon. Infine il campo TX power contiene una misurazione, ad un metro di distanza dall’iBeacon, della potenza ricevuta ed è utile per rendere più accurata la stima della distanza tra il telefono e l’iBeacon stesso.

esp32

Ho sviluppato un programma per il chip esp32 che attiva un relay se rileva un particolare iBeacon. Tramite menuconfig è possibile configurare l’UUID dell’iBeacon da monitorare, il pin a cui è collegato il led e il timeout in secondi trascorsi i quali – se non viene nuovamente rilevato l’iBeacon – il programma spegne il led. E’ inoltre possibile impostare una soglia minima di potenza in modo da poter regolare la distanza di rilevamento dell’iBeacon.

Per effettuare il parsing del pacchetto ricevuto ed estrarre il valore di UUID ho utilizzato nel mio programma la tecnica descritta in questo mio articolo (parsing attraverso l’uso di struct).

Il programma verifica se il pacchetto ricevuto (evento ESP_GAP_SEARCH_INQ_RES_EVT) è stato inviato da un iBeacon verificando che tale pacchetto sia di 30 bytes e che contenga nel suo header i valori indicati sopra:

// iBeacon fixed header
ibeacon_header_t ibeacon_fixed_header = {
  .flags = {0x02, 0x01, 0x06},
  .length = 0x1A,
  .type = 0xFF,
  .company_id = 0x004C,
  .beacon_type = 0x1502
};

La verifica avviene utilizzando il comando memcmp che confronta due blocchi di memoria:

if(memcmp(adv_data, ibeacon_fixed_header, sizeof(ibeacon_fixed_header)))
  result = true;

Il sorgente del programma si trova nel mio repository Github, ecco un video che mostra il suo funzionamento:

Nel video utilizzo un iBeacon di WGX. Se vi interessa avere maggiori informazioni, in questo post ne faccio una recensione…

16 Comments »

  1. Stefano Bordini 22/03/2018 at 11:18 - Reply

    Ciao complimenti per le tue guide molto istruttive,e possibile rilevare un cellulare invece di un iBeacon,per far attivare il relay?

    • luca 22/03/2018 at 13:05 - Reply

      ciao Stefano, sicuramente sì… puoi usare una app che trasmette un pacchetto broadcast di tipo iBeacon o inventarti tu un formato che condividerai tra l’app e il codice sull’esp32.

  2. Stefano Bordini 22/03/2018 at 23:28 - Reply

    Grazie Luca provo a documentarmi devo chiudere una porta quando esco da una certa area

  3. serkan 03/04/2018 at 08:31 - Reply

    Hi,Luca
    Thank your for these tutorials. Did you try to use esp32 with both ble and wifi?

    • luca 03/04/2018 at 08:37 - Reply

      Hi! Yes, it works fine (BLE + Wifi). I think I’ll post a tutorial about it when I complete the “BLE” serie ;)

      • Achille 18/07/2018 at 18:52 - Reply

        Hi Luca,
        Thanks so much for the great tutorial.
        Could you please explain how to program the ESP32 to run both BLE and WIFI? Do you have an implemented code?
        Thank you again for your support.

        Kind regards, Achille

        • luca 04/08/2018 at 13:26 - Reply

          Hi Achille, in a future tutorial I’ll explain it!

  4. serkan 03/04/2018 at 08:54 - Reply

    I’m waiting impatiently.

  5. serkan 03/04/2018 at 19:32 - Reply

    Hi luca ağain:D What esp-idf version do you use?

    • luca 03/04/2018 at 19:45 - Reply

      I usually keep my local repository updated with Github, so I use the (almost) the latest version

  6. Martin 10/07/2018 at 21:46 - Reply

    Hi Luca,

    thanks for the great tutorial. Could you recommend a beacon that I can use with your code that is small, reliable, with a good battery life and that can be used as a keychain. I have trouble finding anything.
    Another question: What is the fastest time from startup of the ESP32 till a successful scan of a nearby beacon. It would help me a lot if I knew that.

    Kind regards, Martin

    • luca 11/07/2018 at 20:23 - Reply

      it usually takes a couple of seconds to boot the esp32

  7. Martin 10/07/2018 at 23:15 - Reply

    Could you make this sketch work with the tile mate key finder?

    • luca 11/07/2018 at 20:22 - Reply

      Hi Martin, I don’t own a tile make key finder but from what I see it’s a standard BLE device so if you know its mac address, you can scan for it

  8. Alican 03/11/2018 at 13:55 - Reply

    Hi Luca,
    Is it possible to use more than one ibeacon and could we control different pinouts with these beacons?

    • luca 10/11/2018 at 21:44 - Reply

      Sure! Each iBeacon has its own “id” so your program can look for them and act accordingly

Leave A Response »

Questo sito usa i cookie per poterti offrire una migliore esperienza di navigazione maggiori informazioni

Questo sito utilizza i cookie per fonire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o clicchi su "Accetta" permetti al loro utilizzo.

Chiudi