Merge pull request #3 from Untori/bluetooth

Bluetooth
This commit is contained in:
Raffaele Mignone 2020-07-10 17:35:54 +02:00 committed by GitHub
commit c7240fa790
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -149,6 +149,12 @@ Potendo opera unicamente nello spazio utente non è stato possibile superare que
[^dont-kill-my-app]: Molti produttori Android per aumentare la durata della batteria dei propri dispositivi tendono a stoppare e ridurre le funzionalità delle applicazioni. Maggiori dettagli possono essere trovati al seguente link \url{https://dontkillmyapp.com}.
Tutte le funzionalità legate al bluetooth sono state *incapsulate* all'interno della classe `BluetoothManager`.
L'interfaccia di questa classe espone due metodi, `startService()` e `stopService()` che consentono di avviare e stoppare sia la scansione che la trasmissione del beacon.
Poiché queste operazioni vanno ad interagire con le funzionalità del sistema operativo, l'istanza di questa classe deve essere collegata ad un oggetto di tipo `Context`.
Si è scelto di collegare l'oggetto `BluetoothManager` all'*application* e non ad una `Activity` in quanto i servizi devono essere utilizzati anche quando non sono presenti *activity* in *foreground*.
Per questo motivo è stata sviluppata anche una classe `BluetoothApplication` che va ad estendere le funzionalità di `Application` e fornisce a sua volta due metodi di start e stop che vanno a richiamare quelli esposti da `BluetoothManager` in modo tale da rendere possibile il controllo dei servizi legati al bluetooth anche da altre componenti dell'applicazione.
### Trasmissione
Il dispositivo dell'utente deve eseguire il broadcast di un beacon bluetooth contenete l'UUID identificativo.
@ -156,7 +162,7 @@ Questa operazione è stata svolta attraverso la classe `BeaconTransmitter` messa
Inoltre per la modalità di funzionamento *C* è stato necessario prevedere un meccanismo di rotazione delle chiavi.
Questa rotazione viene settata attraverso la funzione `rotateTCN()` che sfrutta un `Handler` per programmare la rotazione dell'UUID.
``` {.kotlin #lst:rotate-tcn caption="Codice necessario alla torazione del tcn."}
``` {.kotlin #lst:rotate-tcn caption="Codice necessario alla rotazione del tcn."}
private fun rotateTCN() {
val advertiseHandler = Handler()
val changeTCN: Runnable = object : Runnable {
@ -201,11 +207,50 @@ Per questo motivo si è scelto di utilizzare il livello LOW che permette di rile
### Scansione
Le operazioni di scansione sono meno limitate dalle funzionalità dell'API di Android e per questo motivo c'è stata maggiore libertà di scelta.
In particolare è stato possibile settare sia l'intervallo temporale che deve intercorrere tra una scansione e la successiva, sia la durata della singola scansione.
Si è scelto di far trascorrere un minuto tra una scansione e la prossima e di avere una scansione della durata di un secondo.
Per quanto detto già in precedenza in base ai vari dispositivi e alle varie condizioni di funzionamento l'intervallo tra una scansione e la successiva potrebbe essere più ampio rispetto a quello stabilito.
Entrambi i parametri sono stati settati tramite una costante in modo tale da poter configurare facilmente il comportamento dell'applicazione.
Quando l'applicazione rivela un beacon nelle vicinanze esso viene trasmesso ad un'ulteriore componente applicativa tramite l'impiego del `LocalBroadcastManager` @BroadcastsOverview.
Questa componente non consuma direttamente il beacon, ma ha il compito di smistarlo ad ulteriori componenti in base alla modalità di funzionamento dell'applicazione.
Il codice necessario a smistare i dati di contatto è stato riportato nel @lst:contact-receiver.
Come si può notare nella linea 2, la prima operazione consiste nel recupero dei dati di contatto dall'`Intent`, mentre dalla linea 7 si seleziona la funzione da invocare in base alla modalità di funzionamento.
``` {.kotlin .numberLines #lst:contact-receiver caption="Codice necessario allo smistamento dei dati di contatto."}
// ...
val contactData = intent?.getSerializableExtra(CONTACT_DATA_KEY)
as ContactData?
val mode = getMod(context)
val onMode = when (mode) {
Mode.MOD_A -> this::contactOnModeA
Mode.MOD_B -> this::contactOnModeB
Mode.MOD_C -> this::contactOnModeC
}
onMode(context, contactData)
```
Nel caso della modalità *A* il beacon viene trasmesso alla classe `NetworkReceiver` che si occupa di trasmettere il contatto al server remoto.
Mentre nel caso delle modalità *B* e *C* il beacon viene consumato dalla classe `StoreReceiver` la quale si occupa della memorizzazione permanente del contatto all'interno di un database locale.
### Stima della distanza
In base all'intensità dell segnale (***rssi***) misurato dal dispositivo ricevente è possibile ottenere una stima della distanza che intercorre tra chi invia il beacon e chi lo riceve attraverso l'@eq:distanza.
Per poter calcolare la distanza è necessario conoscere anche il valore di $n$ e $TxPower$.
$n$ è una costante che generalmente assume valori compresi tra uno e quattro e ci permette di modellare i diversi ambienti in cui si può operare.
Generalmente s'impone $n$ pari a due quando si ipotizza di lavorare in ambienti *free space*.
$$
d = 10^{\frac{TxPower - rssi}{10 \cdot n}}
$$ {#eq:distanza}
$TxPower$ è la potenza di trasmissione nominale che si misurerebbe alla distanza di un metro dalla sorgente del segnale.
Il valore di $TxPower$ deve essere precedentemente ricavato per ogni emettitore e deve essere inviato all'interno del beacon bluetooth.
Lavorando con dispositivi eterogenei tra di loro non è stato possibile calcolare in modo esatto questo valore ma si è scelto di utilizzare un valore che mediamente si adattasse a tutti i dispositivi utilizzati in fase di test.
## UI