Reprezentacija uređaja
Uređaji imaju dva seta parametara:
tvorničke –
factory_device.jsonkorisničke –
user_device.json
Tvornički parametri određuju hardverske parametre koji se ne mogu mijenjati i koje uređaji posjeduju kada izađu iz fabrike. Korisnički parametri su oni koji su poznati tek prilikom ugradnje uređaja u pametnu kuću i oni predstavljaju ličnu kartu svakog pojedinačnog uređaja.
Tvornički parametri bi se u pravilu trebali nalaziti u centralnoj bazi podataka. Ova baza podataka sadrži opise svih uređaja koji su prepoznati. S druge strane, korisnički parametri se pohranjuju samo u lokalnoj bazi podataka na nivou kuće.
Pošto mikrokontroleri obično posjeduju vrlo ograničene resurse, nezgodno je vršiti procesiranje JSON datoteka na samom mikrokontroleru. Pogodnije je iz JSON datoteka generisati C++ datoteke koje se popunjavaju samo osnovnim deklaracijama koje su specifične za uređaj, dok programer kasnije implementira funkcionalnost.
Generišu se sljedeće datoteke:
iot_device.h.in
iot_device.hDatoteka
iot_device.cppsa praznim implementacijama funkcijaRazne pomoćne datoteke unutar direktorija
autogen
JSON datoteke
Datoteka factory_device.json
{
"name": "TODO",
"vendorId": "TODO",
"model": "TODO",
"functions": [
{
"name": "TODO", "friendly": "TODO",
"valueType": "TODO", "valueRange": [ "TODO" ], "unit": "TODO"
}
],
"data": [
{
"name": "TODO", "friendly": "TODO",
"valueType": "TODO", "unit": "TODO"
}
]
}
Uputa
Tekst TODO programeru služi kao indikator da odgovarajući atribut nije
još uvijek konfigurisan.
Atributi uređaja
Atribut name
Naziv modela uređaja.
Atributi vendorId, model
Ovi atributi predstavljaju identifikaciju uređaja i jedinstveni su za svaki uređaj istog modela, od istog proizvođača.
Niz data
Sadrži podatke koje se mogu zatražiti od uređaja. Ovo su najčešće neka mjerenja, ili trenutno stanje uređaja.
Atribut name
- Format: Ispravan naziv C++ funkcije.
Jedinstveni identifikator koji ujedno predstavlja i ime metode u C++ klase
Device. Ova metoda je po svom karakteru getter.
Atribut friendly
Naziv pod kojim će korisnik vidjeti ovaj podatak na GUI prikazu.
Atribut valueType
- Moguće vrijednosti:
float,int,bool,<ENUM-TYPE>- Default:
floatOdređuje tip podatka koji se dobija sa uređaja. Ovaj podatak je payload odgovarajućeg topic-a. Može biti
float,int,bool, ili naziv korisnički-definiranog enumeriranog tipa. Konkretne vrijednosti ovog enum-a se zadaju putem atributavalueRangekoji je opisan u nastavku. U headeruiot_device.hće se generisati definicija ovog enum tipa.Ako se ne navede atribut
valueType, onda će se uzeti da je onvoid, što znači da ova funkcija ne zahtijeva nikakav ulazni podatak.
Atribut valueRange
Određuje skup vrijednosti koje može uzeti enum čiji je naziv sadržan u atributu
valueType.
Atribut unit
Mjerna jedinica ulaznog parametra ove funkcije koja se treba prikazati u GUI. Ako se ne zada ovaj atribut, uzima se da je prazan string. Ako je
valueTypejednakvoid, onda ovaj atribut nema nikakvu ulogu.
Niz functions
Niz funkcija uređaja. Funkcija je bilo koja radnja koju uređaj može obavljati. Funkcija može da prima neki parametar, koji predstavlja nešto što korisnik zadaje pritiskom dugmeta, izborom iz menija ili sl. Korisnik ovu komandu u GUI vidi pod imenom koje se zadaje atributom
friendly. U klasiDeviceće se generisati metoda sa nazivomnamekoju programer treba da implementira za konkretni uređaj. Generisana metoda je po svom karakteru setter.Alternativno, funkcija može biti specificirana kao niz podfunkcija (multi function). Ovo je korisno ako dvije funkcije konceptualno pripadaju istoj skupini (na primjer funkcije
upaliiugasiza neku pametnu lampu utiču na ON/OFF stanje lampe).
Atribut valueType
- Moguće vrijednosti:
float,int,bool,void,<ENUM-VALUE>- Default:
voidIma sličnu ulogu kao istoimeni atribut u sklopu podatka uređaja . Jedna razlika je da ovaj atribut može imati dodatnu vrijednost
void. Ovaj parametar predstavlja ulaznu vrijednost koja se šalje uređaju da bi izvršio funkciju. To je ujedno i parametar odgovarajuće C++ funkcije. Tipvoidznači da uređaj ne zahtijeva nikakav parametar za izvršenje funkcije.
Atribut valueRange
U slučaju da je
valueTypeneki brojni tip, ovaj atribut treba biti niz od dva elementa koji sadrži donju i gornju granicu vrijednosti. U slučaju da jevalueTypekorisnički definirani enum tip, ovaj niz sadrži sve moguće vrijednosti ovog enum tipa u obliku stringova.
Atribut unit
Ima istu ulogu kao istoimeni atribut u sklopu funkcija.
Atribut if
Određuje kada je funkcija omogućena za upotrebu. Uvijek je formata
<DEVICE_DATA> = <VALUE>pri čemu su<DEVICE_DATA>i<VALUE>zamijenjeni konkretnim vrijednostima. Dakle funkcija je omogućena kada je podatak<DEVICE_DATA>jednak<VALUE>.Napomena
Unutar atributa
ifsvi razmaci se ignorišu.
{
"name": "setBrightness", "friendly": "Set Brightness",
"valueType": "float", "valueRange": [ 0.0, 100.0 ], "unit": "%"
}
Ovo je primjer primitivne funkcije koja ne sadrži nikakve podfunkcije. Naziv
funkcije je setBrightness i to je ujedno naziv odgovarajuće C++ funkcije i
MQTT teme. Korisnik treba da vidi ovu funkciju sa ljepšim imenom “Set
Brightness”. Tip vrijednosti koju prima funkcija je float i to je ujedno
tip parametra kojeg prima odgovarajuća C++ funkcija. Opseg vrijednosti koje može
imati parametar je od 0.0 do 100.0. Mjerna jedinica parametra je %.
Napomena
U slučaju tipa float, atribut valueRange se koristi samo da bi se na GUI
ograničio opseg vrijednosti koje korisnik može unijeti. Ovaj atribut se ne
koristi prilikom implementacije uređaja na mikrokontroleru.
[
{ "name": "turnOn", "friendly": "Turn On", "if": "getState=Off" },
{ "name": "turnOff", "friendly": "Turn Off", "if": "getState=On" }
],
U ovom slučaju funkcija je sastavljena od dvije podfunkcije koje se pojedinačno tumače kao u prethodnom primjeru.
Osnovna zamisao ovakvog zadavanja funkcije je da se na GUI dvije ili više radnji
može prikazati korištenjem istog widget-a. U ovom slučaju bi se mogao koristiti
widget Button čiji je tekst jednak sadržaju atributa friendly one
podfunkcije koja je omogućena. Korisnik može pritisnuti ovo dugme da bi
aktivirao onu funkciju čiji je naziv prikazan u tekstu dugmeta.
Stanje omogućenosti funkcije određuje atribut if. Funkcija turnOn je
omogućena ako je podatak getState jednak Off, a u suprotnom je omogućena
funkcija turnOff.
Datoteka user_device.json
Lična karta svakog konkretnog uređaja.
{
"serialNo": "TODO",
"location": "TODO",
"ip": "192.168.1.TODO",
"subnetMask": "255.255.255.0 TODO",
"defaultGateway": "192.168.1.1 TODO",
"brokerHost": "TODO"
}
Uputa
Tekst TODO programeru služi kao indikator da odgovarajući atribut nije
još konfigurisan.
C++ datoteke
Napomena
Ovaj odjeljak je od interesa samo za programere uređaja.
Datoteka device.h.in
#ifndef IOT_DEVICE_H
#define IOT_DEVICE_H
/*** Enums ***/
namespace Device
{
// Basic device information
inline const char *getName() { return "$name"; }
inline const char *getVendorId() { return "$vendorId"; }
inline const char *getModel() { return "$model"; }
/*** Function declarations ***/
/*** Data declarations ***/
void initialize();
};
#endif // IOT_DEVICE_H
Ova datoteka je predložak za datoteku iot_device.h koja se treba generisati u
MBED workspace-u. Gdje god se u datoteci nađu alfanumerički znakovi ispred
kojih se nalazi znak $ treba se ubaciti vrijednost odgovarajućeg atributa
uređaja. Također, svaka linija omeđena znakovima /*** ***/ će biti
zamijenjena automatski generisanim deklaracijama/definicijama odgovarajućih
funkcija. Sve što je potrebno za generisanje ove datoteke se nalazi u
odgovarajućoj datoteci factory_device.json. Datoteka
user_device.json se ovdje ne koristi.
Ako je u datoteci factory_device.json definiran sljedeći atribut uređaja:
{
"...": "...",
"vendorId": "ETF_SIAU",
"...": "..."
}
sljedeća linija iz datoteke iot_device.h.in
const char *getVendorId() const { return "$vendorId"; }
će biti zamijenjena sa:
const char *getVendorId() const { return "ETF_SIAU"; }
Datoteka main.cpp
#include <mbed.h>
#include "iot_device.h"
#include "autogen/user_device.h"
#include "autogen/mqtt_wrapper.h"
int main(void)
{
ethernetConnect(IP_ADDR, SUBNET_MASK, DEFAULT_GW);
mqttConnect(BROKER_HOST);
mqttAutoSubscribe();
Device::initialize();
while (true) mqttYield(100);
return 0;
}
Ova datoteka sadrži osnovnu logiku programa. Programer može po potrebi proširiti
funkcionalnost ove datoteke. Preprocesorske konstante IP_ADDR,
SUBNET_MASK itd. se mogu pronaći u datoteci autogen/user_device.h i
generisani su na osnovu datoteke user_device.json.