Quantcast
Channel: Tutorials – lucadentella.it
Viewing all articles
Browse latest Browse all 84

ESP32 (32) – BLE, iBeacon

$
0
0

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:


Viewing all articles
Browse latest Browse all 84

Trending Articles