Temperror
Bluetooth Low Energy
About
- BLE
- dva typy zariadení
- central
- peripheral
- budeme robiť central pre Xiaomi Mijia Bluetooth Temperature Smart Humidity Sensor
- trošku reverzného inžinierstva, ktoré však urobil niekto iný
Objectives
- zoznámiť sa s BLE
Content
Introduction
Predtým, ako sa vrhneme do samotného vývoja aplikácie, sa zoznámime s BLE senzorom v zariadení a pozrieme sa na dostupné zariadenia v blízkom okolí.
Úloha
Do svojho zariadenia si nainštalujte aplikáciu nRF Connect for Mobile.
Úloha
Pomocou nástroja nRF Connect zistite, aké BLE zariadenia sa nachádzajú vo vašom okolí.
Aby všetko prebehlo úspešne, vaše zariadenie musí byť vybavené Bluetooth-om a tento musí byť zapnutý. Pre zapnutie Bluetooth vo vašom telefóne hľadajte v rýchlych nastaveniach túto ikonu:
V zozname zariadení by ste mali vidieť zariadenie s názvom MJ_HT_V1, ktoré reprezentuje uvedený Xiaomi senzor.
Úloha
Zobrazte si advertisement správy zariadenia.
Informácie ako aj advertisement si zobrazíte kliknutím na položku v zozname BLE zariadení.
Na získanie informácií o aktuálnej teplote, vlhkosti a stave batérie sa k zariadeniu nepotrebujete pripájať.
Project Temperror
Projekt Temperror bude fungovať ako mobilná aplikácia pre Xiaomi BLE senzor.
V tomto kroku pripravíme všetko potrebné pre vytvorenie projektu.
Úloha
Vytvorte nový projekt s názvom Temperror, ktorý sa bude nachádzať v balíku sk.tuke.smart.temperror
a umiestnite ho do priečinka temperror/
.
Úloha
V súbore config.xml
doplňte opis aplikácie spolu s informáciami o vás ako o autorovi aplikácie.
Úloha
Pridajte do projektu platformu android
a nainštalujte plugin cordova-plugin-ble-central
.
Úloha
Nahraďte .html
súbor aplikácie a .css
súbor jej vzhľadu nasledovnými súbormi.
Ako kostru vašej aplikácie použite tento súbor index.html
:
<!DOCTYPE html>
<html>
<head>
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width" />
<link rel="stylesheet" type="text/css" href="css/index.css" />
<title>Temperror</title>
</head>
<body>
<div id="app">
<div id="temperature">0°</div>
<div id="humidity">0%</div>
<div id="battery">0%</div>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
Ako kostru kaskádnych štýlov vašej aplikácie použite tento .css
súbor:
#app {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
min-height: 100vh;
}
#temperature {
font-size: 7em;
}
#humidity {
font-size: 2em;
}
Úloha
Overte svoju implementáciu.
Scan and Discover BLE Peripherals
V tomto kroku zistíme, aké BLE zariadenia sa nachádzajú v okolí.
Úloha
Po udalosti deviceready
zavolajte funkciu ble.scan()
.
Funkcia ble.scan()
oskanuje a zistí, aké BLE zariadenia sa nachádzajú v blízkom okolí.
.scan([],
ble5,
function(device) {
console.log(JSON.stringify(device));
,
}function(error){
console.error(error);
}; )
Úloha
Miesto zobrazenia všetkých zariadení vyfiltrujte len tie, ktoré sa volajú MJ_HT_V1
.
Filtrovanie vyriešime jednoducho - pomocou príkazu if
, v ktorom sa opýtame na názov zariadenia:
.scan([],
ble5,
function(device) {
if(device.name === 'MJ_HT_V1'){
console.log(JSON.stringify(device));
},
}function(error){
console.error(error);
}; )
Advertising
V tomto krokou získame informácie o teplote, vlhkosti a úrovni batérie senzora. Tie sa nachádzajú v advertising-u vysielaného zariadenia.
Úloha
Zobrazte obsah členskej premennej advertising
objektu zariadenia.
Informácie o aktuálnej teplote, vlhkosti a stave batérie, sa nachádzajú v advertising-u. Ich konkrétnu podobu je možné vidieť práve v aplikácii nRF Connect. Aby sme s týmito údajmi vedeli pracovať, vypíšeme si ich na obrazovku cez objekt zariadenia:
console.log(device);
Výstup môže vyzerať napríklad takto:
{
advertising: ArrayBuffer(62) {}
id: "58:2D:34:32:D3:1F"
name: "MJ_HT_V1"
rssi: -52
}
Členská premenná advertising
je teda typu ArrayBuffer
. Aby sme s dátami vedeli pracovať, potrebujeme z neho spraviť pole konkrétneho typu. Vzhľadom na povahu údajov z neho spravíme typ Uint8Array
:
const data = new Uint8Array(device.advertising);
S obsahom tohto poľa už nie je problém pracovať - k jednotlivým prvkom je možné pristupovať pomocou index operátora []
.
Pri porovnávaní údajov z aplikácie nRF Connect a obsahom poľa data
si všimneme, že obsah advertising-u je v aplikácii nRF Connect reprezentovaný v šestnástkovej sústave. Aby sme mohli tieto údaje porovnať, vytvoríme funkciu toHexString()
, ktorá príslušnú konverziu poľa zabezpečí:
function toHexString(byteArray) {
return Array.from(byteArray, function(byte) {
return ("0" + (byte & 0xff).toString(16)).slice(-2);
.join("");
}) }
Následne môžeme obsah poľa vypísať ako reťazec hex-a znakov:
console.log(toHexString(data));
Následné porovnanie advertising-u z aplikácie nRF Connect (z režimu RAW) a reťazca hex znakov je rovnaké (až na rozličnú dĺžku).
Úloha
Z advertisement-u zistite, aká je teplota a vlhkosť na senzore.
Na to potrebujeme získať údaje služby s id 0xfe95
. Aby sme sa k nim dostali, vystrihneme z údajov advertisement-u pole začínajúce od indexu 5. Upravíme teda vytvorenie poľa typu Uint8Array
nasledovne:
const data = new Uint8Array(device.advertising).slice(5);
Senzor Xiaomi Mijia posiela 4 rozličné typy správ advertising-u. Tieto správy závisia od hodnoty uloženej na indexe 13. Význam jednotlivých hodnôt ilustruje nasledovná tabuľka:
data[13] |
type of value | bytes to read |
---|---|---|
0x04 |
temperature | 16 + 17 |
0x06 |
humidity | 16 + 17 |
0x0a |
battery | 16 |
0x0d |
temperature and humidity | temp: 16 + 17 hum: 18 + 19 |
Po vytvorení 16b z dvoch 8b hodnôt je ešte potrebné hodnotu teploty a vlhkosti vydeliť hodnotou 10. Teplota je udávaná v stupňoch celzia a vlhkosť v percentách.
Obyčajne môžu údaje služby z advertising-u vyzerať napríklad takto:
95 FE 50 20 AA 01 57 29 AE 33 34 2D 58 0D 10 04 DB 00 CC 01
čo zodpovedá teplote 21.9 stupňov celzia a vlhkosti na úrovni 46%.
95 FE 50 20 AA 01 5E 29 AE 33 34 2D 58 06 10 02 CB 01
čo zodpovedá vlhkosti na úrovni 45.9%.
Z uvedených príkladov je možné vidieť, že pre uloženie údajov je použitý malý endián.
Najčastejšie bude dochádzať k odosielaniu správ typu 0x0d
. Typ správy si teda môžeme pre kontrolu vypísať:
console.log(data[13]);
Následne môžeme ošetriť výskyt typu 0x0d
pomocou príkazu switch
. Pre ilustráciu uvádzame zostavenie hodnoty teploty pomocou bitových operácií a zostavenie hodnoty vlhkosti aritmetickým výpočtom:
switch(data[13]){
case 0x0d:
const temp = (256 * data[17] + data[16]) / 10;
const hum = ((data[19] << 8) | data[18]) / 10;
break;
}
console.log(temp);
console.log(hum);
Podobným spôsobom môžeme ošetriť aj ostatné typy správ. Výsledná podoba volania funkcie ble.scan()
môže vyzerať napr. nasledovne:
.scan(
ble,
[]3,
function(device) {
if (device.name === "MJ_HT_V1") {
const data = new Uint8Array(device.advertising).slice(5);
switch (data[13]) {
case 0x0d:
.temperature = (256 * data[17] + data[16]) / 10;
app.humidity = ((data[19] << 8) | data[18]) / 10;
appbreak;
case 0x04:
.temperature = (256 * data[17] + data[16]) / 10;
appbreak;
case 0x06:
.humidity = ((data[19] << 8) | data[18]) / 10;
appbreak;
case 0x0a:
.battery = data[16];
appbreak;
default:
console.error(`Unknown type of advertising: ${type}.`);
}
}
.innerText = `${app.temperature}°`;
temperature.innerText = `${app.humidity} %`;
humidity.innerText = `${app.battery} %`;
battery,
}function(error) {
console.error(error);
}; )
Úloha
Overte správnosť svojej implementácie.
Ak ste postupovali správne, na obrazovke vášho mobilného zariadenia by ste mali vidieť aktuálnu teplotu a vlhkosť v miestnosti, ako aj stav batérie senzora.
Additional Tasks
- Zabezpečte, aby sa skenovanie spúšťalo v pravidelných intervaloch. Pre realizáciu úlohy môžete použiť napr. volanie funkcie
setInterval()
. Dajte si však pozor na to, aby bol čas skenovania kratší, ako interval opätovného spúšťania. - Upravte aplikáciu tak, aby dokázala zobraziť aj zoznam viacerých dostupných senzorov tohto typu a až po kliknutí na vybraný zobrazí jeho aktuálne hodnoty.
Additional Links
- cordova-plugin-ble-central - Bluetooth Low Energy (BLE) Central plugin for Apache Cordova (aka PhoneGap)
- nRF Connect - nRF Connect for Mobile is a powerful generic tool that allows you to scan, advertise and explore your Bluetooth Low Energy (BLE) devices and communicate with them.
- Talking to a Xiaomi Mijia Temperature Sensor
- Introduction to Bluetooth Low Energy - A basic overview of key concepts for BLE
- Endianita - Endianita je v informatike spôsob uloženia čísel v pamäti počítača, ktorý definuje, v akom poradí sa ukladajú jednotlivé jednotky informácie príslušného údajového typu.