A BLINK nevű alkalmazás
A Blink az egyik legegyszerűbb alkalmazás. Ennek a bemutatásával kezdődik a legtöbb tutorial.
Azokon a hálózati érzékelőkön, amelyekre a nesC programokat írjuk, van három lámpa.
A Blink csak annyit tesz, hogy a piros lámpát ki-be kapcsolja 1 Hz-es frekvenciával.
A program csupán két fájlból áll: Blink.nc és BlinkM.nc.
Az előzőekben említettem, hogy egy alkalmazás lényegében egy konfiguráció.
Jelen esetben ez a Blink konfiguráció, ami a Blink.nc fájlban van benne.
A fájl tartalma:
configuration Blink {
}
implementation {
components Main, BlinkM, SingleTimer, LedsC;
Main.StdControl -> SingleTimer.StdControl;
Main.StdControl -> BlinkM.StdControl;
BlinkM.Timer -> SingleTimer.Timer;
BlinkM.Leds -> LedsC;
}
Láthatjuk, hogy nincs semmi a specifikációs részben.
Ez természetes: így van minden „fő-konfigurációnál”, hiszen kívülre már nem kell semmiféle kapcsolatot tartania ennek a komponensnek.
Az implementációs rész első sorára pillantva megállapíthatjuk, hogy a konfiguráció (vagyis lényegben a programunk) négy komponensből tevődik össze.
Ebből csak a BlinkM-et írtuk meg mi, a másik három a TinyOS része.(a TinyOS lényegében komponensek halmaza).
A Main az a komponenes, amely minden nesC alkalmazásban benne kell legyen. A Main komponens felhasznál egy StdControl nevű interfészt.
Ennek a definíciója:
interface StdControl
{
command result_t init();
command result_t start();
command result_t stop();
}
Egy TinyOS program futása során először a Main.StdControl.init() parancs fog végrehajtódni.
Ez többször is végrehajtódhat, de start() és stop() parancsok végrehajtódása után már nem.
A Blink konfiguráció implementációs részének második sorából láthatjuk, hogy a BlinkM komponens meg fog valósítani egy StdControl interfész példányt (hiszen a nyíl mindig egy felhasználttól egy megvalósított felé mutat).
Ez így is van:
BlinkM.nc:
module BlinkM {
provides {
interface StdControl;
}
uses {
interface Timer;
interface Leds;
}
}
implementation {
command result_t StdControl.init() {
call Leds.init();
return SUCCESS;
}
command result_t StdControl.start() {
// elindít egy időzítőt ami 1000ms-onként jelez
return call Timer.start(TIMER_REPEAT, 1000);
}
command result_t StdControl.stop() {
return call Timer.stop();
}
event result_t Timer.fired()
{
//ha kaptunk egy jelzést akkor kapcsolgatjuk a lámpát
call Leds.redToggle();
return SUCCESS;
}
}
A BlinkM modul meg fogja valósítani az StdControl interfészt.
Ez azt jelenti, hogy implementálnia kell az ebben az interfészben található parancsokat.
Ezeken kívül még implementálni kell azokat az eseményeket, amelyek a felhasznált interfészekben vannak.
Nézzük ezt a két interfészt:
Timer.nc
…
interface Timer {
command result_t start(char type, uint32_t interval);
command result_t stop();
event result_t fired();
}
Leds.nc
interface Leds {
async command result_t init();
async command result_t redOn();
async command result_t redOff();
async command result_t redToggle();
async command result_t greenOn();
async command result_t greenOff();
async command result_t greenToggle();
async command result_t yellowOn();
async command result_t yellowOff();
async command result_t yellowToggle();
async command uint8_t get();
async command result_t set(uint8_t value);
}
Megjegyezés: az async kulcsszóval ebben a dokumentációban nem foglalkozunk, most sem fontos nekünk, egyszerűen ne vegyük figyelembe.
Látjuk, hogy csak egyedül a Timer interfészben van esemény, itt is csak egy. Ezt kell BlinkM-ben implementálni.
A program végrehajtása:
A Main elindítja a BlinkM valamint a SingleTimer init() majd start() parancsát.
A BlinkM init()-je elindítja a Leds init()-jét (azaz bekapcsolja), a start() pedig a SingleTimer.start(...)-ot (elindítja az időzítőt).
Amikor letelik egy másodperc, a SinlgeTimer -ből egy riasztás érkezik a BlinkM-hez (azaz egy hívás a BlinkM által megvalósított fired() eseményhez).
Ezt úgy implementáltuk, hogy egyszerűen csak hívja meg a LedsC komponensben a redToggle() parancsot, ami ki-be kapcsolja a lámpát.
Ha újra letelik egy másodperc akkor újrakezdődik a ciklus.