Tecniche di routing in reti WSN - Netlab
Transcript
Tecniche di routing in reti WSN - Netlab
Università degli Studi di Pavia Facoltà di Ingegneria Sede di Mantova Corso di Laurea Triennale in Ingegneria Informatica Tecniche di routing in reti WSN Relatore: Prof. Paolo Gamba Tesi di laurea di: Davide Silvestri Correlatore: Dott. Ing. Emanuele Goldoni Anno Accademico 2008/09 Ringraziamenti “Cento volte al giorno ricordo a me stesso che la mia vita interiore e esteriore è basata sulle fatiche di altri uomini, vivi e morti, e che io devo sforzarmi al massimo per dare nella stessa misura in cui ho ricevuto. Albert Einstein Giunto al termine di questo lavoro, desidero ringraziare chi, in maniera più o meno diretta e più o meno consapevole, ha contribuito alla sua realizzazione. Innanzitutto vorrei porgere i miei ringraziamenti al prof. Paolo Gamba, per avermi permesso di lavorare su un argomento decisamente stimolante in un ambiente sereno e funzionale. Un sentito ringraziamento va al Dott. Ing. Emanuele Goldoni, che con i suoi consigli mi ha aiutato a portare a termine un lavoro complesso e articolato, e che con la sua conoscenza e la sua pazienza ha reso le mie giornate in laboratorio più serene e produttive. Vorrei inoltre ringraziare il Dott. Alberto Savioli, per la sua pronta disponibilità a intraprendere insieme a me le varie sperimentazioni che di volta in volta era necessario affrontare. Volevo poi ringraziare di cuore tutti i miei amici: Pietro, Gianmaria, Angelo, Luca, Andrea, Marco, Alberto, Nicolò, William, con i quali sono cresciuto e grazie ai quali ho passato giornate indimenticabili, che hanno saputo starmi vicino nel momento del bisogno e farmi divertire nei periodi più difficili. Un pensiero particolare va a Tobia, un amico speciale, un confidente, un compagno di squadra, una persona unica che è venuta a mancare e ha lasciato un vuoto profondo, con cui tanto avrei voluto condividere un evento così importante come la laurea. Impossibile dimenticarmi poi di mia cugina Francesca, che sempre si è dimostrata disponibile a consigliarmi ed incitarmi nei momenti più faticosi, e di Marco, con il quale ho condiviso tutto il mio percorso universitario, che ha saputo aiutarmi a preparare ogni esame e con il quale spero di prepararne ancora molti altri. Ed infine un ringraziamento speciale a tutta la mia famiglia: a mia sorella Angelica, a mio fratello Raffaello e ai miei genitori, Paolo e Rossana, a cui più è dedicato questo lavoro di tesi e a cui devo tutto. Grazie per avermi insegnato valori come l’onestà, il sacrificio, l’umiltà, grazie per avermi permesso di studiare, grazie per avermi sopportato nei giorni in cui ero intrattabile (e sono stati tanti), grazie per avermi spronato a darmi sempre da fare, grazie per tutte quelle interminabili discussioni e ancora grazie per tutte quelle volte che non ho trovato le parole giuste per farvi sapere quanto io vi sia riconoscente per tutto quello che mi avete dato. Indice Ringraziamenti iii Indice v 1 Introduzione 1 2 Le Wireless Sensor Network 2.1 Un po’ di storia . . . . . . . . . . 2.2 Applicazioni . . . . . . . . . . . . 2.3 Architettura hardware di un nodo 2.3.1 Componenti hardware . . 2.4 Piattaforme Hardware . . . . . . 2.5 Architettura di rete . . . . . . . . 2.5.1 Livello fisico . . . . . . . . 2.5.2 Livello Data Link . . . . . 2.5.3 Livello Network . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 WSN per il monitoraggio ambientale 3.1 Soluzioni esistenti . . . . . . . . . . . . 3.2 Il progetto CERERE . . . . . . . . . . 3.2.1 Architettura di rete . . . . . . . 3.2.2 Hardware utilizzato nel progetto 4 Il protocollo di routing CERTO 4.1 Vincoli progettuali . . . . . . . . . . 4.2 Topology control . . . . . . . . . . . 4.3 Power Management . . . . . . . . . . 4.4 Compiti di un nodo . . . . . . . . . . 4.4.1 Ingresso nella rete . . . . . . . 4.4.2 Trasmissione dei beacon . . . 4.4.3 Rilevazione ed invio dati . . . 4.5 Routing . . . . . . . . . . . . . . . . 4.5.1 Fase di Connection . . . . . . 4.5.2 Fase Data . . . . . . . . . . . 4.6 Data aggregation . . . . . . . . . . . 4.7 I limiti dell’implementazione esistente v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 4 5 7 7 8 10 11 12 13 . . . . 15 15 18 19 20 . . . . . . . . . . . . 23 23 24 25 26 26 28 29 30 30 30 31 31 vi INDICE 5 La nuova implementazione del protocollo CERTO 33 5.1 La modalità API . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 5.2 XBee: le librerie per i nodi . . . . . . . . . . . . . . . . . . . . . . . 34 5.3 Serial: le librerie per il gateway . . . . . . . . . . . . . . . . . . . . 35 6 Analisi dei risultati sperimentali 6.1 Test sulla topologia della rete . . . 6.1.1 Rete a stella . . . . . . . . . 6.1.2 Rete ad albero . . . . . . . 6.1.3 Rete mista . . . . . . . . . . 6.2 Analisi temporale dei dati in arrivo 6.3 Paragone tra sorgenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Conclusioni e sviluppi futuri 39 39 39 41 41 42 43 45 A API Mode: la costruzione di una frame A.1 Struttura dati API . . . . . . . . . . . . . . . . . . . A.2 Stato del modem . . . . . . . . . . . . . . . . . . . . A.3 Comandi AT . . . . . . . . . . . . . . . . . . . . . . A.4 Risposta ad un comando AT . . . . . . . . . . . . . . A.5 Richiesta TX (Trasmissione) ad un indirizzo a 16 bit A.6 Pacchetto RX (Ricezione) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 47 48 48 50 50 50 B Il Formato dei messaggi utilizzato B.1 Messaggio di Ask Association . . B.2 Messaggio Send Data . . . . . . . B.3 Messaggio di Gateway Response . B.4 Messaggio di Answer Orphan . . B.5 Messaggio di Beacon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 53 53 54 54 55 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C Codice Sorgente della tesi 57 C.1 MoteAPI.pde . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Bibliografia 63 Capitolo 1 Introduzione I recenti sviluppi in ambito tecnologico hanno portato alla creazione di una nuova classe di periferiche di calcolo: dotate di sensori intelligenti, alimentate da batterie a lunga durata, in grado di comunicare via radio a distanze di centinaia di metri e dalle dimensioni molto ridotte. Oggi quindi non si parla più del classico sensore passivo, che semplicemente modula su base elettrica un certo parametro ambientale, ma di un vero e proprio mini-computer. Un piccolo calcolatore autonomo in grado cioè di rilevare i dati provenienti dall’ambiente circostante ed elaborarli localmente per poi condividerli via radio con i sensori vicini, per raggiungere infine un nodo centrale che coordina e dirige l’attività dell’intera rete di sensori. Si immagini la possibilità di poter monitorare, comodamente seduti davanti al proprio computer, un’area agricola molto vasta, visualizzando direttamente sul monitor quale zona necessiti maggiormente di acqua, oppure, nel caso di aree boschive, in quale zona si stia verificando un incendio o ci sia qualcosa di anomalo. Oppure ancora la possibilità di controllare costantemente zone impervie e inaccessibili all’uomo, sapendo quanto più preventivamente possibile cosa vi stia succedendo, dando così modo di avere il tempo di evitare catastrofi naturali quali inondazioni, terremoti o frane. Tutto questo, oggi, non è più mera utopia, e le risorse che università e aziende di tutto il mondo stanno impegnando in questa nuova tecnologia sta facendo compiere passi da gigante. Sono state create applicazioni militari, per il controllo aereo e marino di alleati e nemici; applicazioni urbane, per il monitoraggio del traffico in grandi città o per il controllo delle auto in grandi parcheggi; applicazioni agricole, per la supervisione di vasti raccolti e vaste aree; e sempre più aspetti della vita quotidiana stanno traendo vantaggio da possibili applicazioni che ogni giorno nascono e vengono sviluppate con lo scopo di migliorare la qualità della vita. Ciò che è stato realizzato all’interno del laboratorio di Telecomunicazioni presso la sede di Mantova, nel progetto di tesi [21], da cui questo elaborato ha preso ispirazione, è un sistema di monitoraggio ambientale basato su una rete di sensori wireless adatto ad uno scopo di agricoltura di precisione e studio del territorio. Il risultato ottenuto è stato un sistema completo, autoconfigurante, economico e pronto all’uso, grazie al quale un utente, tramite il proprio browser, è in grado di visualizzare e gestire i dati rilevati dall’intera area agricola coperta. CERERE, questo è il nome che è stato deciso per il sistema realizzato, è stato 1 progettato e sviluppato da zero, ovvero sono stati creati i protocolli di rete e l’applicativo necessario al suo funzionamento. In seguito è stata sviluppata la banca dati adibita al collezionamento dei dati e il sistema di visualizzazione, tramite l’implementazione di un database, di un web server e di una applicazione web. L’obiettivo di questa tesi è stato riprendere gli algoritmi e i protocolli di routing precedentemente sviluppati al fine di effettuarne il porting ad una modalità radio più complessa che sia in grado, però, di offrire maggiori garanzie in termini di velocità di trasmissione, affidabilità e robustezza all’errore. Come verrà spiegato in seguito nello svolgersi dell’elaborato si è cercato di mantenere la maggior somiglianza possibile al formato messaggi e alle tecniche di routing iniziali, in modo da valutare correttamente le reali differenze che la sola modalità radio implementata ha introdotto. Nel Capitolo 2 verranno approfondite le WSN, spiegando in dettaglio cosa sono, come sono nate e quali piattaforme Hardware e Software sono ad oggi disponibili. Il Capitolo 3 è stato diviso in due parti: nella prima verranno elencate alcune delle molte soluzioni che negli ultimi anni sono state create per il monitoraggio ambietale, elencadone di ognuna caratteristiche tecniche, pregi e difetti noti. Nella seconda parte, invece, verrà discusso CERERE, mostrandone ogni aspetto tecnico, dall’architettura di rete all’hardware utilizzato. Nel Capitolo 4 verrà poi presentato il protocollo di routing CERTO, lo schema ideato dal progettista di CERERE per la regolamentazione del routing e l’ingresso nella rete. Verranno analizzati aspetti quali vincoli progettuali, accorgimenti adottati, obiettivi e tecniche implementate. Il Capitolo 5 mostrerà la nuova modalità API e come è stato affrontato e riscritto l’intero applicativo dei nodi e del gateway. Verranno inoltre spiegate le nuove librerie adottate e gli effetti che hanno portato sul codice. Nel Capitolo 6 viene proposta un’analisi comparativa tra la precedente implementazione del programma di gestione dei nodi e la nuova creazione, valutandone parametri quali memoria volatile utilizzata, memoria di massa utilizzata, affidabilità del protocollo e un’analisi temporale sui dati in arrivo. Il Capitolo 7, infine, riporterà le valutazioni finali sul nuovo sistema ottenuto, proponendo nuove idee per implementazioni future. Capitolo 2 Le Wireless Sensor Network Una WSN (Wireless Sensor Network) è una rete di semplici dispositivi elettronici caratterizzati da un modulo radio, una piccola quantità di RAM e da processori a basse prestazioni, che implementano un’intelligenza distribuita sul territorio al fine di monitorare le caratteristiche fisiche dell’ambiente. Ogni dispositivo che costituisce la rete può essere dotato di diversi sensori, con i quali periodicamente valuta le condizioni ambientali in cui si trova per poi inviare tali misurazioni ad un nodo centrale, in genere sede di un database, in cui vengono collezionati tutti i dati ed elaborati. Tutto questo solitamente permette poi di mostrare all’utente finale il risultato dell’intera attività di monitoraggio svolta, in modo che chiunque possa controllare l’ambiente in modo semplice ed affidabile (Figura 2.1). Figura 2.1: Architettura di rete di una WSN. Nonostante i sensori abbiano un hardware piuttosto limitato, le funzionalità che devono implementare sono numerose e talvolta possono risultare piuttosto complicate da gestire. Ogni nodo deve infatti gestire i flussi di comunicazione provenienti dal modulo radio, i consumi energetici al fine di massimizzare la durata della batteria e inoltre deve effettuare le misurazioni quando necessario. Infine, un nodo deve occuparsi autonomamente di fasi come l’ingresso nella rete, eventuali sincronizzazioni, inoltro di dati e altre situazioni classiche in una rete multi hop. 3 4 CAPITOLO 2. LE WIRELESS SENSOR NETWORK L’evoluzione di questa tecnologia negli ultimi decenni è stata davvero notevole, si è passati da nodi piuttosto ingombranti a dispositivi dalle dimensioni nell’ordine dei millimetri cubi, da consumi elevati di energia a prototipi la cui batteria può durare per più di qualche mese, e con il passare del tempo si raggiungeranno traguardi sempre più importanti a prezzi sempre più contenuti. 2.1 Un po’ di storia Le WSN sono relativamente giovani ma, durante i pochi decenni in cui si sono sviluppate, hanno subito dei miglioramenti impressionanti: questo è avvenuto sicuramente grazie al grande sviluppo della tecnologia ma, in buona parte, anche alle grandi quantità di energie e fondi che università e imprese hanno investito in quello che si pensa possa diventare parte integrante della nostra vita in un futuro non troppo lontano, così come lo sono ora personal computer e telefoni cellulari. Le Wireless Sensor Network hanno avuto origine durante la guerra fredda: gli Stati Uniti d’America furono i primi a creare reti acustiche con obiettivi di sorveglianza sottomarina, analoghe a quelle che vengono usate ancora oggi per rilevare attività sismiche. Poco dopo, nel Nord America furono creati delle reti radar utilizzando come sensori gli aerei Airborn Warning and Control System (AWACS) [1], con l’obiettivo di aiutare e migliorare la difesa aerea. La grande spinta nella direzione delle WSN fu però negli anni ’80, quando la DARPA (Defence Advanced Research Projects Agency) finanziò la creazione di Distributed Sensor Network (DSN)[15] per determinare se il protocollo TCP/IP insieme alla rete ARPA potessero essere usati come reti di sensori. Il progetto prevedeva la creazione di una rete in cui i nodi fossero tutti equispaziati l’uno dall’altro e in cui ognuno fosse in grado di comunicare con gli altri, con l’obiettivo di facilitare lo scambio e l’elaborazione distribuita di dati e risultati per funzionalità di signal processing e tracking. I componenti di queste reti erano sensori acustici, protocolli di comunicazione di alto livello, algoritmi di calcolo e software distribuito. Nei due decenni a cavallo degli anni ’80 e ’90 vennero sviluppate numerose applicazioni militari sulla base dei risultati derivati dalle DSN che, grazie ad un grosso processo di commercializzazione, portarono all’implementazione dei primi standard e, di conseguenza, alla vendita di prodotti commerciali dal prezzo minore. Così facendo si arrivò presto ad adoperare queste reti di sensori in applicazioni militari in cui ogni nodo della rete necessitasse di scambiare con gli altri informazioni sugli obiettivi, talvolta anche molto distanti, ottenendo risposte soddisfacenti in tempi molto brevi. Alcuni esempi di impiego di questa tecnologia furono reti radar per la rilevazione di obiettivi aerei, reti di sensori acustici negli oceani per rilevare sottomarini e reti di sensori schierate sul campo di battaglia. Con l’avvento del nuovo millennio la tecnologia si è evoluta ulteriormente e ha permesso una nuova generazione di sensori: i MEMS (Micro ElectroMechanical Systems) [14], ovvero circuiti integrati in forma altamente miniaturizzata su uno stesso substrato di silicio . In questi ultimi anni si è assistito inoltre alla creazione di numerosi standard (ZigBee, Bluetooth [4], Wi-Fi, WiMax [11]) a cui si sono aggiunte poi le produzioni di nuovi processori a basso costo e basso consumo che, 2.2. APPLICAZIONI 5 di fatto, hanno agevolato la diffusione dei sensori e delle possibilità di applicazione nelle WSN. 2.2 Applicazioni Le applicazioni in cui potrebbe essere utilizzata una WSN sono davvero innumerevoli e in continuo sviluppo (Figura 2.2). Ad oggi, tuttavia, le principali implementazioni di reti di sensori sono in campo militare, ambientale, sanitario, casalingo e commerciale [10]. Figura 2.2: Esempi di possibili applicazioni di WSN. Applicazioni militari Le applicazioni militari, come citato precedentemente, sono state tra le prime ad usufruire dei vantaggi messi a disposizione dalle reti di sensori wireless. In particolare, caratteristiche come tolleranza ai guasti, facilità e rapidità di distribuzione e autoorganizzazione hanno permesso applicazioni su ampio raggio, a cui va aggiunto anche un costo via via decrescente per questo tipo di sensori che molto ha inciso sulla sostituzione dei precedenti dispositivi ben più costosi. Tra le applicazioni citate in letteratura le più note sono sicuramente il monitoraggio di forze alleate o equipaggiamenti, la sorveglianza del campo di battaglia, il riconoscimento dei nemici, la stima dei danni o il riconoscimento del tipo di attacco(nucleare, biologico o chimico). Applicazioni ambientali Negli ultimi anni si è puntato molto su applicazioni di reti di sensori wireless per il monitoraggio ambientale e animale. Le applicazioni sono tra le più disparate: dal controllo di misure fisiche quali temperatura, umidità e luminosità in una foresta, al monitoraggio di allevamenti di piccoli animali. Tra le applicazioni di carattere 6 CAPITOLO 2. LE WIRELESS SENSOR NETWORK più strettamente ambientale sono ricorrenti in letteratura sistemi per il controllo di eventuali incendi in una foresta o per il controllo delle inondazioni. Un esempio è il sistema Alert System [2]: creato e adoperato in America, è in grado di rilevare le quantità di pioggia caduta, il livello dell’acqua di un fiume e condizioni climatiche come ad esempio temperatura, umidità, etc. per poi avvisare un nodo centrale dove un operatore controlla i risultati ottenuti. Applicazioni medico-sanitarie Gli utilizzi dei sensori in ambito medico-sanitario sono indirizzati principalmente a fornire un’interfaccia a persone affette da handicap, al monitoraggio di dati fisiologici, ma anche a sistemi che garantiscano la corretta amministrazione ospedaliera sia dei pazienti che dei medici, in modo da semplificare il problema della rintracciabilità. Applicazioni domestiche Negli ultimi anni sono state investite molte energie anche nella domotica, la scienza che si occupa fondamentalmente dell’automazione delle case, dove un sistema intelligente coordina gli azionamenti o gli spegnimenti degli elettrodomestici, sistemi idraulici o termici. In questo contesto le WSN risultano essere molto utili: è il caso, per esempio, di reti formate da sensori di temperatura utili ad attivare, a tempo debito, eventuali sistemi di controllo dell’aria condizionata o del riscaldamento, sensori in grado di abilitare attuatori per l’accensione o lo spegnimento di elettrodomestici a distanza o sensori di umidità del terreno per attivare il sistema di irrigazione quando necessario. Grazie ad una WSN diventa così possibile far interagire sistemi di origine diversa, in cui i vari sensori comunicano tra loro scambiandosi le rispettive misurazioni ed essendo così in grado di prendere la migliore decisione in base alla logica di cui sono stati forniti, con l’obiettivo di facilitare e migliorare la vita all’interno della propria abitazione. Applicazioni urbane Per quanto riguarda applicazioni di carattere commerciale sono state proposte diverse possibilità in cui una WSN potrebbe trovare un utile impiego, alcuni di queste sono per esempio il monitoraggio del traffico, in cui tramite un sistema di sensori posizionati su strade molto trafficate è possibile controllare eventuali intasamenti e code, per poi fornire indicazioni agli automobilisti su come evitare tali inconvenienti o semplicemente per fare delle statistiche. Un’altra applicazione potrebbe essere il rilevamento di furti di auto: nodi sensore vengono disposti per scoprire e identificare minacce che avvengono in una determinata zona geografica. Tutte le informazioni rilevate vengono poi inviate tramite Internet agli utenti così da poter essere analizzate per prendere i giusti provvedimenti. 2.3. ARCHITETTURA HARDWARE DI UN NODO 2.3 7 Architettura hardware di un nodo Ogni nodo all’interno di una WSN è un dispositivo elettronico dotato di una CPU, una certa quantità di memoria, un modulo radio, uno o più sensori, degli attuatori e una fonte di alimentazione. In Figura 2.3 viene mostrato uno schema che rappresenta l’architettura hardware di un nodo. Figura 2.3: Architettura hardware di un nodo. 2.3.1 Componenti hardware • Processore: è la CPU del dispositivo e ha il compito di gestire la logica con cui ogni nodo deve agire: dalle misurazioni da effettuare tramite i sensori agli algoritmi di routing e di gestione del risparmio energetico. Per applicazioni embedded di questo genere vengono solitamente utilizzati dei microcontrollori, poiché richiedono poca energia, hanno spesso una sufficiente quantità di memoria integrata e non necessitano di alcun controller di memoria, sono inoltre facilmente programmabili anche tramite software open source, e, infine, si integrano bene con componenti quali sensori e attuatori e hanno delle modalità di risparmio energetico che ne permettono l’alimentazione da batteria per lunghi periodi. • Memoria: ogni nodo possiede piccole memorie sia volatili che di massa, in genere proprie del microcontrollore, che vengono utilizzate rispettivamente per salvare le variabili durante l’esecuzione e per memorizzare il programma da eseguire all’accensione. • Modulo radio: componente fondamentale in una rete di sensori wireless costituito da un ricetrasmettitore ad onde radio che, solitamente, opera nella banda ISM secondo lo standard IEEE 802.15.4 [5]. • Sensori ed attuatori: nelle maggior parte delle WSN vengono utilizzati sensori passivi omnidirezionali: passivi perché non modificano in alcun modo l’oggetto della misurazione, omnidirezionali perché non importa la direzione in cui tali misurazioni vengono effettuate. 8 CAPITOLO 2. LE WIRELESS SENSOR NETWORK I nodi in genere non dispongono di attuatori particolari, ma semplicemente di alcuni interruttori governabili via software a cui è possibile collegare circuiti studiati e creati appositamente per l’applicazione. • Fonte di alimentazione: le più comuni forme di alimentazione adottate sono le batterie. Queste hanno però il problema di una durata limitata nel tempo, per cui da anni si stanno studiando soluzioni aggiuntive quali l’implementazione di pannelli solari o nuove tecnologie in grado di sfruttare l’energia prodotta da vibrazioni meccaniche per produrre energie tramite piezo, oppure ricavare l’energia necessaria tramite micro-turbine basate su MEMS [19] che sfruttino piccoli flussi di aria o liquidi presenti nell’ambiente circostante. 2.4 Piattaforme Hardware Negli ultimi anni molte società hanno dato alla luce diversi modelli utilizzabili nelle proprie applicazioni in reti di sensori. La scelta di quale dispositivo adottare dipende da svariati fattori: ingombro ammissibile per ogni nodo, costo sostenibile, contesto di utilizzo, efficienza energetica, etc. I modelli maggiormente diffusi, tuttavia, sono: • MicaMote: sviluppati intorno alla fine degli anni ’90 dall’Università di Berkeley, in California, in collaborazione con Intel. Ad oggi sono disponibili quattro diversi modelli, differenti in caratteristiche tecniche e costi: Mica, Mica2, Mica2Dot (Figura 2.4), MicaZ. Sono dotati di microcontrollore Atmel e da analisi di mercato risultano essere i più utilizzati nelle WSN. Figura 2.4: Nodo Mica2Dot. • EYES: prodotto da Infineon in un progetto sponsorizzato direttamente dall’Unione Europea di nome Energy Efficient Sensor Networks. Questi dispositivi, di cui un esemplare viene mostrato in Figura 2.5, sono equipaggiati con microcontrollore Texas Instruments MP 430 e radio TDA 520. • Scatterweb: prodotti dalla Freie Universitat Berlin sono una famiglia di dispositivi dalle caratteristiche tecniche molto varie: alcuni implementano in modo nativo un web server mentre altri possono offrire svariate modalità di comunicazione, tra cui Bluetooth, radio a bassa potenza, CAN, etc. In 2.4. PIATTAFORME HARDWARE 9 Figura 2.5: Nodo EYES. Figura 2.6 viene riportata la foto del nodo Scatterweb MSB-430, l’ultimo prodotto realizzato dall’università di Berlino. Figura 2.6: Nodo Scatterweb MSB-430. • FireFly: nodi basati su Atmega 128, con 8 KB di memoria RAM, 128 KB di memoria ROM e modulo radio compatibile 802.15.4 della Cipcon. La caratteristica peculiare di questi dispositivi risiede nella presenza di un porta SDIO (Secure Digital Input Output), che permette l’utilizzo di memorie di tipo Flash (visibile in Figura 2.7) e un orologio hardware per una sincronizzazione accurata. Figura 2.7: Nodo FireFly. 10 CAPITOLO 2. LE WIRELESS SENSOR NETWORK • Arduino e XBee Shield: Arduino [3] è una piattaforma open-source che si basa su hardware e software flessibili per il physical computing. Le schede possono essere assemblate autonomamente oppure è possibile comprarne alcune già pronte (in Figura 2.8 l’esemplare Arduino Diecimila); è inoltre possibile studiarne i progetti di riferimento per ampliarli o riadattarli alle proprie esigenze. Figura 2.8: Arduino Diecimila. Figura 2.9: XBee shield. Arduino, oltre al vantaggio di essere molto economico rispetto alle altre soluzioni mostrate, risulta compatibile con lo shield XBee (Figura 2.9), che offre un modulo radio conforme allo standard 802.15.4 e con il quale si completa formando un nodo sensore in grado di comunicare senza fili. 2.5 Architettura di rete L’architettura di rete di una Wireless Sensor Network prende spunto dal modello OSI (Open Systems Interconnection), rappresentato in Figura 2.10, nella quale, però, non vi è una netta separazione tra i vari livelli. 2.5. ARCHITETTURA DI RETE 11 In particolar modo i livelli 2 e 3 si sovrappongono tra loro per motivi e caratteristiche intrinseche di una Sensor Network, dove è richiesto un alto grado di efficienza, leggerezza e di tolleranza ai cambiamenti della rete che, quindi, porta inevitabilmente alla violazione del principio di separazione dei livelli. Proprio il Figura 2.10: Il modello OSI. secondo e il terzo livello rappresentano i tratti caratteristici di una rete di sensori wireless. È vero infatti che sebbene anche il livello fisico sia molto importante, tutte le reti sfruttano moduli radio dalle caratteristiche simili: bassa potenza di trasmissione, basso consumo, basso bitrate. Il livello fisico non è quindi distintivo, utile al fine di distinguere il profilo di una WSN. Per quanto riguarda il livello di trasporto, invece, molte volte non viene implementato, e si differenzia dal suo omologo nelle reti TCP/IP classiche per una maggiora semplicità. I livelli sovrastanti infine vengono presi in considerazione solo per il gateway o host su cui girano particolari applicativi. Fanno eccezione le reti ZigBee e altre soluzioni proprietarie che implementano parte del layer Applicativo nei nodi. Nei prossimi paragrafi verrà fatta una presentazione generale dei primi tre strati dell’architettura di rete nelle Wireless Sensor Network. 2.5.1 Livello fisico Lo standard utilizzato infatti, è quello che meglio si adatta alle caratteristiche ideali che una rete di sensori wireless dovrebbe avere, e cioè un consumo energetico molto basso così da garantire un’autonomia quanto più lunga possibile, una discreta copertura (è possibile comunicare con alcuni nodi distanti anche 100 metri) e una velocità di trasmissione dati non troppo elevata, viste le dimensioni e la semplicità dei dati che ogni nodo può elaborare. 12 CAPITOLO 2. LE WIRELESS SENSOR NETWORK La Figura 2.11 mostra il confronto di alcuni tra gli aspetti più importanti delle varie tecnologie sopra citate. Figura 2.11: Confronto tra varie tecnologie wireless. Dal punto di vista implementativo infine, nell’802.15.4 si è optato per una modulazione DSSS (Digital Sequence Spread Spectrum)[22], operativa in tre bande: 868 MHz in Europa, 915 MHz in USA e 2.4 GHz in tutto il mondo. 2.5.2 Livello Data Link Il livello Data Link è costituito da due sottolivelli: LLC e MAC. Il primo, detto Logical Link Control è un sublayer con il compito di fare da tramite tra il livello fisico e il MAC sovrastante, consentendo l’interoperabilità tra diversi tipi di rete. Il livello MAC (Medium Access Control), invece, si occupa di funzioni quali l’assemblaggio dei dati in frame tramite l’aggiunta di un header, contenente informazioni sul destinatario, e un trailer, contenente informazioni per la correzione di eventuali errori; il disassemblaggio delle frame ricevute e le politiche di accesso al canale condiviso. Visti gli obiettivi di una rete di sensori wireless, il requisito fondamentale di un MAC per WSN è la necessità di risparmiare più energia possibile. Risulta quindi indispensabile gestire fattori quali eccessivo overhead, l’idle listening, collisioni di pacchetti dati e l’overhearing, senza contare che l’accesso regolato al canale porta allo scambio di messaggi di controllo che contribuiscono alla perdita di energia a disposizione. Per minimizzare questi sprechi sono stati creati tre diversi gruppi di protocolli MAC: Schedule-based,Contention-based e ibridi [16]. I primi protocolli elencati si basano su una regolazione dell’accesso al canale tramite una schedulazione, pre-assegnata ad ogni nodo, in modo che un solo nodo alla volta possa occupare il canale trasmissivo. I protocolli Contention-based, invece, si basano su una regolazione dell’accesso on-demand, ovvero assegnano il mezzo trasmissivo al nodo che ne fa domanda, cercando di minimizzare eventuali collisioni ricorrendo ad algoritmi casuali distribuiti per schedulare l’accesso al canale tra i contendenti. I protocolli ibridi, infine, cercano di combinare i punti di forza dei protocolli Schedule-based e Contention-based, rafforzando i loro punti deboli. 2.5.3 Livello Network Il livello Network si occupa fondamentalmente del routing: in una rete di sensori il cui scopo è quello di raccogliere dati dall’ambiente circostante e inviarli tutti ad un nodo centrale per le elaborazioni diventa fondamentale il metodo con cui i pacchetti con le misurazioni vengono inoltrati dai nodi verso il sink. Tecniche di routing come quelle adottate per la rete Internet, per esempio, non sono adatte alle reti di sensori wireless, che non dispongono dell’affidabilità che invece possiedono i collegamenti via cavo o della disponibilità di risorse dei normali calcolatori. Per questi motivi sono state sviluppate particolari tecniche di routing adatte all’hardware su cui sarebbero state implementate e con controlli tipici delle comunicazioni senza fili. Tipicamente il routing in una rete di sensori wireless inizia con la scansione di nodi attivi nelle vicinanze, così che ogni nodo si possa creare una mappa locale della rete oppure semplicemente possa scegliere quale sia il miglior nodo a cui in seguito invierà tutte le proprie misurazioni. In seguito sono state sviluppate diverse tecniche, ognuna con i propri pregi e difetti, per garantire il collegamento di ogni nodo con il sink. Alcuni protocolli prevedono, per esempio, una diffusione in broadcast delle informazioni possedute, in modo da diffondere i dati rilevati in locale così da poter costruire una mappa globale su ogni nodo. Altri invece prevedono un calcolo in locale del miglior nodo da scegliere per raggiungere il gateway, sulla base di elementi quali il valore di RSSI, il numero di hop dal sink, il numero di nodi già associati a eventuali nodi cluster-head [17], etc. Capitolo 3 WSN per il monitoraggio ambientale L’agricoltura è uno tra i campi che più beneficiano del continuo sviluppo delle wireless sensor networks. Numerosi progetti di reti di sensori wireless sono stati sviluppati per poter aiutare a migliorare l’attività di monitoraggio di vaste aree, quali per esempio ampie zone agricole. Verranno di seguito presentate alcune delle innumerevoli soluzioni che sono state progettate e realizzate sia in ambito commerciale che universitario, presentando di ognuna pregi e difetti noti. Nella sezione successiva verrà poi presentato il progetto CERERE (Crop and Environmental wiREless monitoRing SystEm), la soluzione sviluppata da zero che si baserà sul protocollo di routing CERTO (CErere Routing proTOcol) oggetto di questa tesi. 3.1 Soluzioni esistenti Numerose opzioni sono disponibili ad oggi per il controllo ambientale tramite applicazioni che poggiano su una rete di sensori. Di tutte le possibilità presenti in letteratura sono state qui riportate solamente alcuni esempi utili a mostrare le funzionalità finora raggiunte ed implementate. Monitoraggio di una risaia In [18] è stata sviluppata una soluzione per il controllo di una risaia che permette il salvataggio dei dati rilevati da ogni nodo in un database centrale e che permette di avvisare l’addetto al monitoraggio di eventuali parametri anomali attraverso un breve messaggio di testo sfruttando la rete GSM. Il progetto è inoltre costituito da un applicativo MIDP (Mobile Information Device Profile) che permette la consultazione dei dati direttamente dal cellulare. L’architettura di rete mostrata in Figura 3.1 rappresenta uno schema di come la rete di sensori si collega al nodo gateway, il quale, una volta ricevute le rilevazioni di temperatura, umidità e livello dell’acqua dai vari nodi, li spedisce via Internet ad un database centrale in cui verranno elaborati. 15 16 CAPITOLO 3. WSN PER IL MONITORAGGIO AMBIENTALE Figura 3.1: L’architettura di rete del sistema realizzato. I nodi utilizzati in questo progetto sono dei Mica Mote con sistema operativo TinyOS e comunicano con il gateway attraverso un protocollo di routing sviluppato dagli stessi autori del progetto a cui hanno dato il nome in codice ISBG (Information Selection Branch Growing). Tale protocollo si basa sull’idea di suddividere equamente il lavoro tra tutti i nodi della rete, basandosi su un algoritmo di routing ad albero che cerca di minimizzare il tempo di delay end-to-end sviluppando i rami della rete dove i nodi foglia hanno un minor numero di hop dal gateway. Test effettuati su questo progetto hanno condotto ad ottimi risultati, sia in termini di durata delle batterie di ogni singolo nodo, sia in termini di affidabilità della trasmissione dei dati. A2 S - Automated Agricolture System Il progetto [20] è stato sviluppato con il fine di aiutare il monitoraggio ambientale all’interno di campi agricoli e serre. Anche in questo esempio è stato sviluppato un algoritmo di routing ad albero in cui, però, è possibile decidere di addormentare un nodo a propria scelta inviando un pacchetto direttamente dai sink. In aggiunta alle rilevazioni di temperatura, umidità e luminosità tramite i sensori a bordo dei nodi, è inoltre possibile comandare un attuatore per l’attivazione e la regolazione delle luci. In Figura 3.2 è stata riportata un’immagine tratta dal sito degli sviluppatori in cui si mostra la struttura della rete e, più precisamente, la divisione presente che, di fatto, divide l’intero schema in tre sottometti distinte, ognuna delle quali comunica i dati ai rispettivi sink, i quali inviano comunicando tra loro in Wi-Fi inviano tutte le misurazioni ricevute ad un unico gateway che inoltra i dati via Internet ad un web server su cui è installato il software applicativo di gestione. Anche in questo progetto è stata sviluppata un’applicazione mobile che permetta la consultazione dei dati direttamente tramite palmare o telefono cellulare. Da numerosi test effettuati dagli autori è emerso come l’ambiente delle serre sia particolarmente ostile alla propagazione delle onde radio: i risultati mostrano infatti che, sebbene i nodi possano comunicare con un ottimo grado di affidabilità se posti in Line of sight ad oltre 70 metri, all’interno di una serra non è possibile mantenerli 3.1. SOLUZIONI ESISTENTI 17 Figura 3.2: Schema di rete del sistema realizzato. a distanze superiori ai 20 metri: in caso contrario i molti fili metallici e le numerose foglie ostacolerebbero la propagazione delle onde radio e porterebbero alla perdita di una notevole quantità di dati. SensorScope SensorScope [13] è un sistema di monitoraggio ambientale out-of-the-box, cioè un sistema completo e subito operativo dal primo utilizzo, senza una necessità di configurazioni particolari da parte dell’acquirente. Inizialmente sviluppato per il monitoring all’interno di edifici, il progetto sviluppato dal politecnico di Losanna è stato recentemente riadattato per fare in modo che possa collezionare dati anche in ambienti esterni, con l’obiettivo di migliorare con queste misurazioni i modelli matematici che prevedono disastri naturali quali per esempio inondazioni, smottamenti del terreno o valanghe. La rete è composta da nodi Shockfish TinyNode con sistema operativo TinyOS, con modulo radio operante nella banda delle frequenze radio ultra alte (UHF) ad una velocità massima di trasmissione di 76kbps, con una quantità di memoria RAM di 10 KB e una memoria ROM di 48 KB, il tutto alimentato da batterie ricaricabili per mezzo di pannelli solari e muniti di sensori addizionali. Oltre ai più comuni sensori di temperatura, luminosità e umidità presenti sulla maggior parte dei nodi di questo tipo, infatti, sono presenti sensori per la misura della velocità e direzione del vento e della pioggia. 18 CAPITOLO 3. WSN PER IL MONITORAGGIO AMBIENTALE Il costo particolarmente elevato di ognuna di queste stazioni che si aggira intorno ai 1000 euro, aggiunto all’ingombro che ogni nodo porta con sé (oltre il metro e mezzo di altezza), rendono l’intero sistema poco accessibile al pubblico. Il protocollo MAC implementato in questi nodi utilizza un metodo di accesso al canale tramite backoff, in quanto non è supportato il carrier sense, ossia l’ascolto del canale prima di ogni eventuale trasmissione. Per quanto riguarda il protocollo di routing ogni nodo decide a chi inviare i propri dati sulla base di due fattori: la qualità del link, che viene determinata tramite l’invio di alcuni bit di prova e non tramite RSSI, che viene ritenuto poco affidabile, e un valore casuale per fare in modo di equibilanciare il carico sui vari nodi. Le tabelle di routing sono salvate sulla memoria di ogni nodo e vengono periodicamente aggiornate tramite messaggi provenienti dal sink contenenti l’età dei nodi vicini, la distanza in hop dal gateway e la qualità del sink. Per la sincronizzazione è stato implementato un metodo tramite il quale periodicamente ogni nodo invia un messaggio di richiesta di sincronizzazione ad un nodo più vicino al sink, il quale risponde con un messaggio in broadcast in modo da informare eventuali altri nodi vicini. Per quanto riguarda la gestione dei dati il sistema si basa su un server centrale che riceve tutti i dati insieme ad un timestamp tramite rete GPRS direttamente dal sink; dati che vengono in seguito stampati sul sito di SensorScope [9] e su Microsoft SensorMap [8]. In Figura 3.3 viene riportato uno schema riassuntivo della rete appena mostrata. Figura 3.3: Schema di rete del sistema SensorScope. 3.2 Il progetto CERERE CERERE è l’acronimo di Crop and Environmental wiREless monitoRing SystEm, un sistema realizzato all’interno della realtà universitaria mantovana con gli obiettivi di rispettare i seguenti requisiti: • Out-of-the-box: la soluzione deve essere pronta all’uso, non deve richiedere interventi particolari di configurazione da parte dell’utente. • Economicità: il sistema deve essere rivolto a tutti coloro che necessitino di nuovo e semplice modo per monitorare il proprio terreno agricolo. I costi devono pertanto essere il più contenuti possibile. 3.2. IL PROGETTO CERERE 19 • Non invasività: il sistema deve aiutare l’agricoltore senza occupare troppo spazio o risorse: i nodi, quindi, devono essere il più piccoli possibile e avere una vita media della batteria molto lunga. • Espandibilità: il sistema deve supportare l’aggiunta di ulteriori nodi in nuove aree, i quali devono essere programmati per autoconfigurarsi e aggiungersi alla rete esistente senza creare problemi. • Open source: il sistema è stato pensato per essere aperto a chiunque lo volesse migliorare, sono stati pertanto utilizzati solamente software open source. • Interfacciabilità: i dati rilevati e quelli presenti nel database devono essere facilmente visualizzabili e analizzabili con altri applicativi software. • Completezza: il sistema deve comprendere tutto ciò che è necessario per renderlo subito operativo: dalla architettura di rete al sistema di gestione, memorizzazione, visualizzazione dei dati. La lista appena mostrata nasce dal tentativo di sopperire alle mancanze dimostrate dalle soluzioni presenti in letteratura, di cui sono stati riportati alcuni esempi nel capitolo precedente. Si è puntato in particolar modo sull’economicità del sistema, lacuna comune ai progetti già esistenti, che ha portato inevitabilmente alla scelta di nodi economici e dalle caratteristiche hardware piuttosto limitate. Questo ha causato un inevitabile dispendio di energie per trovare un protocollo di routing adatto alle capacità di ogni singolo nodo, che bene si adattasse alle esigenze di creare una rete autoconfigurante e che, allo stesso tempo, richiedesse poche risorse, quelle a disposizione sui nodi scelti. Il risultato è il protocollo di routing CERTO di cui si parlerà diffusamente nel Capitolo 4. 3.2.1 Architettura di rete L’architettura realizzata nel progetto è di tipo multi-tier. Come si può notare dalla Figura 3.4, tale architettura è composta da diversi componenti. Il Mote Tier comprende tutte le componenti del nodo della WSN, cioè il bootloader di Arduino, il protocollo MAC, il protocollo di routing, l’algoritmo di schedulazione e il meccanismo di risparmio energetico. Proseguendo verso sinistra in Figura 3.4 possiamo notare il Gateway Tier, ovvero il gateway (o sink) che si occupa di gestire l’intera rete di sensori e i dati in arrivo salvandoli in un database. Comprende anch’esso il protocollo MAC e uno di routing, anche se quest’ultimo leggermente differente da quello dello strato Mote. Viene poi il Server Tier, che si occupa di prelevare i dati dal database per creare documenti XML così che le misurazioni salvate possano essere disponibili anche per applicazioni esterne. Lo strato server ha inoltre il compito di costruire grafici con le statistiche calcolate, le mappe richieste dall’utente e di gestire eventuali allarmi. Vi è infine il Client Tier, costituito da applicazioni che consentono di visualizzare e analizzare i dati rilevati dai nodi e lo stato attuale della rete, impostare allarmi e modificare alcuni parametri del sistema e della rete di sensori. 20 CAPITOLO 3. WSN PER IL MONITORAGGIO AMBIENTALE Figura 3.4: Architettura multi-tier del progetto CERERE. 3.2.2 Hardware utilizzato nel progetto Dall’analisi del mercato effettuata si è arrivati alla scelta dei nodi SquidBee come elementi costituenti della rete di sensori, in quanto relativamente molto economici rispetto alle altre soluzioni e anche perché sono equipaggiati con sensori di temperatura, umidità e luminosità, che risultano essere molti utili nell’attività di monitoraggio ambientale che si vuole implementare. Tali sensori possono essere utilizzati per controllare diversi fattori, tra cui per esempio che la temperatura non si abbassi o si innalzi troppo, onde evitare, rispettivamente, che le piante si ghiaccino o che possano essere a rischio incendio; che il valore di umidità del terreno sia sufficiente a garantire una adeguata idratazione della vegetazione; che ogni pianta sia raggiunta nell’arco di una giornata da una sufficiente quantità di luce solare. Nonostante questa propensione agli ambienti agricoli, comunque, i nodi Squidbee non mancano di presentare alcuni difetti che ne limitano di fatto l’impiego, dipendenti, appunto dal costo così contenuto. Uno tra questi, il principale, è che ogni nodo risulta essere molto dispendioso dal punto di vista energetico; non è in grado, cioè, di garantire una vita adeguatamente lunga nel caso in cui venga alimentato tramite batteria, per cui è facile immaginare come risulti scomoda una rete con qualche decina di sensori in cui ogni giorno, o una volta a settimana, il contadino debba sostituire le batterie di tutti i sensori per poter ottenere le rilevazioni di cui ha bisogno. Allo stesso tempo però, come è facile immaginare, non tutte le zone possono essere raggiunte dalla rete elettrica e questo rende impossibile, o quanto meno molto scomodo, l’utilizzo massiccio di questa soluzione. Dai grafici in Figura 3.5 si possono notare le differenze di consumi energetici tra moduli radio XBee (quelli utilizzati nel progetto all’interno dei nodi Squidbee) e moduli micaZ, nodi più costosi compatibili con lo standard 802.15.4/ZigBee, dotati di CPU ATMega 128L con 512 KB di Flash. Va aggiunto inoltre che i nodi si basano sul protocollo IEEE 802.15.4 per i 3.2. IL PROGETTO CERERE 21 Figura 3.5: Grafici riportanti le differenze di consumi in trasmissione e ricezione e nelle fasi di idle e sleep. primi due livelli dello stack di rete ma mancano dei restanti livelli, che vengono implementati dal programmatore al momento della progettazione. Perciò, il setup e la manutenzione di una rete di sensori wireless basata su nodi Squidbee è risultato in un lavoro piuttosto complesso e articolato, che ha richiesto una notevole quantità di tempo per la messa a punto. Figura 3.6: Il nodo SquidBee utilizzato come sink. Per quanto riguarda la scelta del sink è stato adoperato un nodo SquidBee, mostrato in Figura 3.6 privo di sensori e microcontrollore collegato direttamente al mini-PC scelto come gateway di modo che i dati transitanti per il modulo radio XBee possano raggiungere direttamente la seriale del mini computer su cui è stato installato, inoltre, anche un DBMS molto leggero per la gestione dei dati collezionati: uSQLite. Queste scelte sono state fatte sulla base dell’ambiente in cui il sink dovrebbe presumibilmente andare a trovarsi, cioè all’interno dell’ambiente agricolo, alimentato probabilmente da pannelli solari. Sulla base di queste considerazioni è stato scelto come gateway il mini-pc Koala Nano PC [6] dell’azienda italiana KOAN S.A.S, riportato in Figura 3.7, il quale è caratterizzato da dimensioni molto ridotte (115 x 115 x 35,4 mm), dotato di CPU Vortex a 300 MHz (senza coprocessore matematico), 128 MB di RAM DDR2, scheda video integrata XGI Volari Z9S, Scheda Ethernet Figura 3.7: Il mini-pc scelto come gateway in CERERE. 10/100 integrata, 2 porte USB (necessarie per collegare il sink), 2 porte seriali, 1 slot Compact Flash, e 1 porta PS/2. Il tutto alimentato da un trasformatore a 5V con un consumo massimo di 1080 mA (il che significa 6W di consumo massimo). Il Nano PC viene venduto al prezzo di 106 Euro. Per quanto riguarda il web server, infine, ne è stata scelta una versione molto leggera di nome Lighthttpd, un javascript Toolkit (Dojo) e Php, da installare su una macchina con distribuzione Linux, dimensionata sulla base della stima degli accessi previsti. In particolare, per questo progetto, è stata utilizzata una macchina presente in laboratorio dotata di una CPU AMD Athlon 3200+ con distribuzione Ubuntu. Capitolo 4 Il protocollo di routing CERTO In questo progetto è stato utilizzato il protocollo di routing CERTO (CErere Routing proTOcol), ideato e creato dall’ingegnere Filippo De Stefani con lo scopo di implementare in un unico schema le regole di routing e di network formation che ogni nodo appartenente alla rete deve seguire. Questo protocollo prende spunto da altri presenti in letteratura e ha come punto cardine quello di risultare leggero e performante nonostante le basse prestazioni dell’hardware a disposizione. 4.1 Vincoli progettuali I vincoli progettuali a cui si è dovuto sottostare nella creazione del programma derivano fondamentalmente dall’hardware che costituisce ogni singolo nodo, in particolar modo: • Memoria limitata: la memoria flash di Arduino dipende dal microcontrollore montato. Quello presente inizialmente e adoperato per le prove è caratterizzato da una memoria Flash di 14 KB, di cui comunque solo 8 KB sono stati utilizzati, lasciando quindi uno spazio sufficiente per gestire la routine di sleep/wakeup del modulo radio e lo stand-by del microcontrollore. • modulo radio pre-programmato: il modulo radio XBee implementa nativamente il protocollo 802.15.4 come livello fisico mentre viene utilizzato il CSMA/CD a livello MAC. Non è stato dunque possibile modificare in modo significativo le funzionalità di questi livelli, ma solamente modificarne alcuni parametri utili in modo da adattarlo alle esigenze. • mancanza di un modulo GPS: l’assenza di un modulo GPS non permette l’individuazione del nodo in ogni istante. Questo è risultato però irrilevante ai fini dell’applicazione presupponendo i nodi statici, di cui si conosce l’esatta ubicazione nel momento dell’installazione degli stessi. Inoltre un modulo GPS sarebbe costato molto in termini sia economici che di energia assorbita dal nodo, pensato invece per una vita il più lunga possibile. Un ulteriore vincolo che è stato necessario imporre deriva da come l’applicazione è stata pensata e realizzata: dopo diverse prove si è deciso di impostare come tempo della fase Connection 4 secondi, sufficienti per ricevere 4 richieste di connessione 23 24 CAPITOLO 4. IL PROTOCOLLO DI ROUTING CERTO simultaneamente, mentre altri 8 secondi sono stati assegnati alla fase Data, in cui il gateway può ricevere dati da 16 figli utilizzando slot da 0.5 secondi, per un totale di 12 secondi del periodo di attività. Questo comporta una durata di intervallo minimo superiore ai 12 secondi, che d’altro canto risulta completamente motivata dalla scelta progettuale in cui ci si aspetta misurazioni in intervalli nell’ordine dei minuti o decine di minuti. Un’altra considerazione di cui tener conto riguarda la possibilità di impostare la durata totale di ogni intervallo. È infatti possibile, nel momento del lancio dell’applicativo del gateway, decidere un valore qualsiasi (purché superiore a 12 secondi) per la durata di ogni intervallo, mentre va considerato che, se la modifica viene fatta durante l’esecuzione, la perdita del messaggio di beacon da parte di uno dei figli ne causerà di fatto la perdita di sincronizzazione, per cui il nodo, dopo 4 intervalli della durata della precedente configurazione, si rimetterà in cerca di un padre, causando di conseguenza un periodo di tempo in cui verranno persi tutte le sue misurazioni. 4.2 Topology control In questo progetto non è stato preso in considerazione alcun meccanismo di topology control che serva per determinare la posizione esatta di un nodo. La possibilità di utilizzare un GPS è stata scartata a priori visti gli obiettivi del progetto iniziale, in cui si è puntato ad ottenere una rete economica; sebbene questa sarebbe stata la soluzione migliore, i costi che ciò avrebbe richiesto sarebbero stati molto elevati e, essendo i nodi fissi, non è stato ritenuto necessario predisporre ogni nodo di un modulo così costoso. Anche altre tecniche di localizzazione non sono state ritenute soddisfacenti, la tecnica dell’RSSI per esempio, mediante la quale si stima la distanza di un nodo in base al rapporto di potenza segnale/rumore, richiederebbe un grande numero di nodi per ottenere valori significativi, mentre in questo progetto si desidera avere nodi distanziati il più possibile l’uno dagli altri. Come hanno dimostrato diversi test, infatti, i moduli radio possono comunicare senza perdere un numero eccessivo di pacchetti (meno del 5%) anche a distanze di centinaia di metri, lunghezze che rendono le misurazioni dell’RSSI pressoché inutili. L’unica tecnica di topology control implementata è stata fatta non sulla posizione da cui ogni nodo preleva le proprie misurazioni, ma sulla struttura della rete ad albero che si viene a formare. Il gateway, infatti, registra ad ogni richiesta di connessione l’indirizzo del nuovo entrante, il serial low per identificarlo univocamente, il padre che il nodo ha scelto e il numero di hop che lo distanziano dal sink stesso. Tutte queste informazioni, associate ai dati riguardanti la posizione di ogni nodo stabilite al momento dell’installazione nella zona agricola senza di fatto montare su ogni nodo dispositivi appositi, danno una mappa sufficientemente precisa della struttura della rete. 4.3. POWER MANAGEMENT 4.3 25 Power Management I moduli radio XBee implementano il MAC 802.15.4, per cui non è stato possibile sceglierne uno alternativo o crearne uno proprio. La possibilità che questi moduli offrono è quella di modificare alcuni parametri, tra cui per esempio le modalità di MAC. Sono possibili infatti tre diverse modalità tra cui scegliere: 802.15.4 con Ack, 802.15.4 senza Ack, MaxStream compatibile con 802.15.4. Quest’ultima è stata quella scelta nel progetto, sia per la compatibilità con 802.15.4, sia perché permette di rilevare i pacchetti duplicati, di ripetere il Clear Channel Assessment in caso di errore e di utilizzare comandi di Network Discovery e di risoluzione degli identificativi. In ultima analisi, quindi, questa modalità è stata preferita alle altre perché in grado di garantire una migliore efficienza della rete in termini di integrità di pacchetti, a scapito di un piccolo aumento della mole di dati in transito introdotto dalla testata Maxstream che viene aggiunta in testa ad ogni pacchetto, necessaria per poter fornire queste caratteristiche. Il protocollo di sleep/wakeup scelto per affiancare questa modalità MAC è di tipo scheduled rendezvous. Questa scelta è stata dettata dai fini del progetto: si desidera infatti ottenere una rete di sensori in cui periodicamente i nodi si sveglino e inviino i propri dati, senza particolari vincoli di latenza. Protocolli diversi da quello scelto, come per esempio sleep/wakeup on demand o sleep/wakeup asincroni sono stati scartati per vari motivi. Il primo, infatti, richiede la presenza di un secondo modulo radio sempre attivo con il compito di svegliare o addormentare il nodo in base alle richieste provenienti dal gateway o da altri nodi, ma tutto ciò avrebbe causato un aumento di costi sproporzionato alle necessità del progetto. Il secondo, invece, si basa sull’idea che qualsiasi momento sia l’ideale per trasmettere perché è sempre possibile trovare un nodo attivo. Non viene richiesta, quindi, alcun tipo di sincronizzazione, ma questo esula dall’idea di base della rete in cui ogni nodo si sveglia solamente per un piccolo tempo rispetto a quello in cui dorme, per cui non offre le garanzie necessarie per la consegna dei pacchetti. Gli schemi scheduled rendezvous, invece, prevedono una schedulazione delle fasi di sleep/wakeup che viene impostata su ogni nodo a partire dal gateway, tale da garantire un buon grado di sincronizzazione per tutti gli elementi attivi. Ogni nodo una volta entrato nella rete, infatti, si sincronizza col padre e utilizza il valore letto nel messaggio di sincronizzazione come durata di intervallo, all’inizio del quale accendersi per inviare i propri dati al sink. Per la creazione di questo tipo di schema è stata presa ispirazione dai protocolli S-MAC e T-MAC, a cui sono state apportate modifiche di modo da rendere il tutto consono ed adeguato alle esigenze. Dal primo di questi due schemi presenti in letteratura, è stata copiata l’idea di dividere il periodo di attività in due sottofasi: nella prima i nodi ricevono ed inoltrano i messaggi di sincronizzazione e di richieste di associazione, mentre nella seconda si occupano esclusivamente dell’invio e dell’inoltro dei dati rilevati. Va notato inoltre che, come in S-MAC, i nodi sono loosely synchronized, cioè non necessitano di un alto livello di sincronizzazione. Dal secondo degli schemi precedentemente citati è stata invece presa l’idea di dividere la sottofase Data in slot, ognuno assegnato in modo univoco ad un nodo, così da evitare collisioni ed assicurare ad ogni elemento della rete il proprio spazio per l’invio delle misurazioni. Il progetto di partenza presentava un meccanismo di risparmio energetico che 26 CAPITOLO 4. IL PROTOCOLLO DI ROUTING CERTO permetteva di accendere e spegnere la radio nei periodi in cui era necessario, mentre era stata tralasciata la gestione dello stand-by del microcontrollore prevista come sviluppo futuro. Nella nuova implementazione del programma dei nodi è stata tralasciata anche la gestione dell’accensione/spegnimento del modulo radio, in quanto l’obiettivo principe di questa tesi è stato portare i moduli radio a comunicare in API mode, che garantisce una maggiore affidabilità rispetto all’implementazione precedente, ma differisce leggermente per quanto riguarda le fasi di sleep/wakeup del modulo, che quindi sono state tralasciate in previsione di sviluppi futuri, predisponendo comunque il codice ad un facile aggiornamento. 4.4 Compiti di un nodo Di seguito verrà descritto il ciclo di vita di ogni nodo, a partire dalla sua accensione sino all’istante in cui diventa parte della rete e invia le proprie misurazioni. 4.4.1 Ingresso nella rete Al momento dell’accensione di un nodo il programma impiega quindici secondi per inizializzare correttamente il modulo radio. Questo tempo è stato stabilito dopo diversi test, con tempi inferiori a quello scelto sono stati riscontrati comportamenti scorretti in cui venivano persi pacchetti destinati all’invio o silenziosamente scartati pacchetti in arrivo al modulo XBee. images/Ingresso3.png Figura 4.1: Fase iniziale di Beacon Scan, il nodo è in attesa di beacon. Al termine di questa fase vengono inviati alla radio i comandi per settare il canale e il parametro di PAN ID in quanto parametri necessari per la corretta creazione di una sottorete (nodi aventi canale o PAN ID differenti possono avere uguale indirizzo in quanto appartenenti, di fatto, a differenti reti). Viene poi inviato il comando per ottenere il serial low del modulo, ossia la parte bassa composta da 32 bit di un identificativo di 64 bit che viene assegnato ad ogni radio dal produttore 4.4. COMPITI DI UN NODO 27 e che viene utilizzato dal gateway al momento dell’assegnazione degli indirizzi per distinguere i vari nodi, un po’ come il meccanismo adottato nelle reti IP in cui viene utilizzato come identificativo l’indirizzo MAC delle schede di rete. A questo punto il nodo è in possesso di tutte le informazioni necessarie per cercare un padre e ottenere un indirizzo che di fatto lo rende parte della rete di sensori. Il momento in cui la fase di inizializzazione della radio è terminata e si passa alla fase di ricerca di un padre, o Beacon Scan (Figura 4.1), viene segnalato con l’accensione di un led; da questo istante il modulo radio si mette in ascolto sul canale in attesa di beacon, messaggi che vengono inviati da ogni nodo all’inizio della fase di attività(Figura 4.2) riportanti l’indirizzo del nodo che l’ha generato, il numero di hop che li separa dal gateway, il numero di figli che attualmente gestisce, la durata dell’intervallo da impostare per la corretta sincronizzazione. Figura 4.2: Fase iniziale di Beacon Scan, i nodi appartenenti alla rete inviano i propri beacon. Una volta ricevuto un beacon, il nodo attende ancora tre secondi prima di entrare nella routine di scelta, per evitare che vadano persi possibili padri candidati. Nel caso in cui un nodo riceva un solo beacon il nodo sceglie come padre l’indirizzo riportato nell’unico pacchetto ricevuto, altrimenti sceglie il padre con minor numero di salti dal gateway, a meno che questo non abbia già più di quattro figli (soglia variabile che può essere impostata nel programma). Nel caso in cui tutti i migliori candidati abbiano lo stesso numero di hop viene scelto quello con minor numero di figli. Eseguita la scelta il nodo si spegne, aspettando il prossimo intervallo di attività per poter inviare la propria richiesta di Ask Association (Figura 4.3). Se tutto viene eseguito correttamente il nodo si risveglierà qualche istante prima dell’inizio dell’intervallo, resterà in attesa del nuovo beacon e, una volta ricevuto, inoltrerà la propria richiesta di ingresso al padre scelto, il quale la inoltrerà a sua volta verso il gateway. Una volta giunta al gateway, la richiesta viene analizzata scorrendo la tabella 28 CAPITOLO 4. IL PROTOCOLLO DI ROUTING CERTO Figura 4.3: In questa fase il nodo invia la propria richiesta di associazione al padre prescelto. dei figli alla ricerca del serial low letto nel messaggio, se si dovesse trovare una corrispondenza significa che il nodo già era stato parte della rete per cui viene spedito indietro un messaggio contenente l’indirizzo precedentemente assegnato, diversamente ne viene assegnato uno nuovo e viene aggiunta la nuova corrispondenza serial low–indirizzo MY nella tabella dei figli. Il messaggio di risposta deve raggiungere il figlio durante la fase connection dello stesso intervallo in cui è stata inviata la richiesta di associazione, altrimenti il nodo attenderà un ulteriore intervallo prima di scegliere un altro padre. Se la risposta arriva a destinazione nel tempo prestabilito, il nodo diventa di fatto parte integrante della rete, acquisendo un indirizzo MY che utilizzerà nelle successive comunicazione con gli altri nodi della rete, quindi attenderà il prossimo intervallo attivo per poter inviare i dati rilevati dai propri sensori al padre. 4.4.2 Trasmissione dei beacon Una volta connesso il nodo entra nella routine che gestisce tutta la fase attiva delle comunicazioni, dall’inoltro dei beacon e delle richieste/risposte di connessione, all’invio dei propri dati e di quelli di eventuali figli. Ogni nodo calcola il tempo per cui dovrà dormire a partire dall’istante di tempo in cui ha ricevuto l’ultimo beacon e aggiungendo il valore letto in questo messaggio nel campo adibito alla durata di ogni intervallo. Da questo momento il nodo si sveglierà nell’attesa del beacon da inoltrare ad eventuali figli per la sincronizzazione o ad eventuali nodi orfani che vogliano unirsi alla rete. In questa fase ogni nodo connesso non fa altro che attendere il beacon proveniente dal proprio padre, sostituire l’indirizzo del mittente con il proprio, sostituire il numero di hop e il numero di figli con i propri dati e inoltrare in broadcast il messaggio. La mancata ricezione di un beacon non preclude il normale svolgimento delle 4.4. COMPITI DI UN NODO 29 attività di ogni nodo, quali per esempio il sopracitato inoltro di richieste o risposte di connessione o invio di dati. Si è notato, infatti, che il ritardo introdotto da nodi intermedi nell’elaborazione del beacon originato dal gateway non può essere sempre considerato costante, per cui si manifestano dei casi in cui nodi distanti alcuni hop dal sink si svegliano leggermente tardi, causando la perdita del messaggio di sincronizzazione. In ogni caso, comunque, questo avviene abbastanza raramente e che, includendo un opportuno tempo di guardia all’inizio ed alla fine di ogni slot di invio dati, ciò non causa alcun tipo di sfasamento a livello di invio dei dati, e ogni ogni nodo riesce comunque ad inviare in quello che per il gateway rappresenta il giusto slot assegnato. Nel caso in cui, però, i beacon persi diventassero quattro, allora significa che il nodo ha perso la sincronizzazione, oppure che è successo qualcosa al padre per cui è necessario procedere alla ricerca di un nuovo padre affinché i dati possano arrivare correttamente al server centrale. 4.4.3 Rilevazione ed invio dati Terminata la fase di Connection(la fase di sincronizzazione tramite beacon e inoltro di messaggi di tipo Ask Association o Gateway Response) ogni nodo entra nella fase Data. In questa fase ogni nodo determina l’intervallo in cui è abilitato a trasmettere a partire dal secondo byte del proprio indirizzo MY. È stato infatti assegnato l’indirizzo 1000 in esadecimale al gateway, mentre i successivi vengono assegnati a mano a mano che la rete viene popolata. Ciò significa che al primo figlio entrante verrà assegnato come MY l’indirizzo esadecimale 1001, da cui, considerando solo il secondo byte (0x01), il nodo dedurrà che l’intervallo in cui gli è permesso trasmettere sarà il primo slot. Tenendo in considerazione gli intervalli di guardia di cui si è precedentemente discusso, il nodo, una volta all’interno del proprio slot, procederà con la rilevazione dai propri sensori dei dati misurati, valori di luminosità, umidità e temperatura che vengono quantizzati su una scala di 1024 possibili valori, che quindi necessitano di due byte ognuno per l’invio. Una volta creato il pacchetto con i propri dati, il nodo lo invia direttamente al padre, e successivamente, solamente nel caso in cui abbia figli, si mette in ascolto di eventuali messaggi dati da inoltrare al gateway. Va notato che, nel caso in cui un nodo abbia uno o più figli, resterà in attesa per tutta la durata della fase Data e non solo per gli slot assegnati ai figli, che sono riportati nella tabella dei figli presenti in ogni nodo, in quanto la fase di sleep/wakeup up del modulo radio ha presentato alcuni inconvenienti, si è notato infatti che la radio tende a perdere i pacchetti ricevuti subito dopo l’uscita dalla fase di sleep. Questo argomento non è stato approfondito a causa di mancanza di tempo; ritengo comunque che uno studio più accurato del caso sopra esposto possa portare ad un notevole aumento della vita di ogni singolo nodo, permettendo di addormentare il modulo radio negli slot in cui sicuramente non riceveranno alcun dato e quindi salvare una buona dose di energia della batteria che permetterà una vita più lunga ad ogni singolo nodo. 30 4.5 CAPITOLO 4. IL PROTOCOLLO DI ROUTING CERTO Routing La tecnica di routing adottata in questo progetto è molto semplice e dipende dalla fase attiva in cui un nodo può trovarsi: Fase di Connection o Fase Data. 4.5.1 Fase di Connection Ogni nodo connesso alla rete rimane in ascolto di qualsiasi pacchetto destinato al proprio indirizzo. Il primo pacchetto che deve essere ricevuto all’inizio di ogni fase connection è il messaggio di sincronizzazione (beacon). Quando un nodo riceve questo tipo di pacchetto salva l’istante di tempo nel campo timestamp del record adibito al padre, in modo da mantenere aggiornata la sincronizzazione, successivamente cambia i campi riguardanti il numero dei figli e il numero di hop dal gateway inserendo i propri valori prima di procedere all’inoltro del pacchetto in broadcast. Nel caso in cui venga ricevuto un pacchetto di richiesta di ingresso nella rete (Ask Association), il nodo analizza il campo riguardante l’indirizzo di quello che il richiedente ha scelto come padre: se l’indirizzo coincide con il proprio, allora la richiesta viene inoltrata solamente se è ancora disponibile spazio nella tabella dei figli, altrimenti significa che è necessario solamente un forwarding del pacchetto verso il gateway, per cui vengono salvati in una struttura il serial low del nodo generante la richiesta e l’indirizzo di chi ha inviato il pacchetto. In entrambi i casi, come ultima operazione prima dell’inoltro al proprio padre, viene inserito nel campo riservato al last forwarder il proprio indirizzo. Nel caso in cui il messaggio in arrivo sia una risposta dal gateway (Gateway Response), viene analizzato nuovamente il campo riservato al padre scelto dal nodo orfano: nel caso in cui coincida con il proprio indirizzo significa che è necessario aggiungere un nuovo figlio nella tabella apposita e modificare il messaggio in uno di tipo Answer Orphan, ossia un messaggio da inviare in broadcast contenente il nuovo indirizzo che il gateway ha scelto e che l’orfano riconosce confrontando il proprio serial low con quello contenuto nel pacchetto; nel caso in cui l’indirizzo analizzato sia diverso dal proprio, allora significa che il messaggio necessita solamente di un forwarding verso il basso, per cui si cerca nella tabella di routing il record associato al serial low del messaggio, e successivamente si procede all’inoltro avendo cura di modificare il campo last forwarder inserendo il proprio indirizzo. 4.5.2 Fase Data Ogni nodo conosce lo slot in cui è abilitato ad inviare i propri dati così come è stato descritto precedentemente. Durante questo slot, quindi, vengono inviati al proprio padre le misurazioni effettuate. Nei restanti slot ogni nodo resta in ascolto del canale solamente nel caso in cui abbia figli, in modo da poter inoltrare eventuali misurazioni in arrivo. In tal caso, una volta ricevuto un pacchetto con le misurazioni ogni nodo non deve far altro che inoltrare immediatamente il pacchetto al proprio padre, senza alcuna modifica, così da far arrivare i dati al gateway. 4.6. DATA AGGREGATION 4.6 31 Data aggregation Non è stato adottato alcun algoritmo di data aggregation, per motivi riconducibili alla scelta fatta da chi ha progettato CERERE [21]. Partendo da quanto scritto nella tesi da cui questo progetto ha preso ispirazione il sistema è stato pensato per ottenere le misurazioni in tempo reale, per cui se l’utente imposta il valore che determina la durata dell’intervallo a 5 minuti, significa che otterrà una misurazione di luminosità, una di umidità e una di temperatura esattamente ogni 5 minuti. Una strategia di data aggregation avrebbe avuto senso nel caso in cui si fosse deciso di effettuare l’invio dopo n misurazioni, con n arbitrario; questo però avrebbe causato non solo pacchetti di dimensione direttamente proporzionale al numero di misurazioni contenute, ma anche il rischio di perdere tutte le n misurazioni nel caso di una scorretta sincronizzazione dei nodi. Questa valutazione non tiene però in considerazione un aspetto importante che caratterizza la rete. Il sistema è stato infatti pensato in modo tale che ad ogni figlio venga assegnato uno slot in cui è abilitato a trasmettere, questo limita il massimo numeri di elementi della rete al numero dei possibili slot, ottenuti dalla divisione del valore che indica la fase Data per il valore che rappresenta la durata di uno slot. Questo limite potrebbe essere superato implementando una tecnica di data aggregation tale per cui un nodo, che potrebbe essere visto come cluster-head nella rete, aggreghi tutti i dati provenienti dai figli in un unico pacchetto da inoltrare al proprio padre in direzione del gateway, di modo che durante gli slot adibiti agli altri figli, il cluster-head possa comunque ricevere dati, che invierà solo al momento opportuno. Così facendo, mentre prima in un singolo slot poteva trasmettere solamente un nodo, ora i nodi abilitati alla trasmissione possono essere più di uno, in base a quanti nodi vengono definiti cluster-head. Questa tecnica permetterebbe così di aumentare il numero di elementi possibili nella rete, con la conseguenza, tuttavia giustificabile, di un aumento della difficoltà implementativa. Inizialmente era stato pensato, inoltre, un meccanismo di data encoding, ossia un metodo tramite il quale vengono spediti solamente la prima volta i valori misurati e poi vengono inviati i valori successivi calcolati come differenza dai precedenti. Anche questa tecnica però è risultata essere poco conveniente in ultima analisi in quanto: non è presente alcuna garanzia di consegna dei pacchetti, lo spazio che occupa la routine per implementare questa tecnica è notevole su un dispositivo che in genere ha a disposizione una memoria molto esigua, i vantaggi in termini di dati inviati non sono paragonabili agli svantaggi menzionati. 4.7 I limiti dell’implementazione esistente Il modulo radio XBee permette tre diverse modalità di invio/ricezione dati e viene identificato dal parametro identificato con il nome di API mode. L’applicativo iniziale da cui si è preso spunto per la tesi adottava la prima delle tre modalità possibili, il transparent mode o modalità API disabilitata. Con questa opzione i dati vengono bufferizzati nel buffer DI fino a che non viene raggiunto il numero massimo di caratteri che un pacchetto può contenere (definito dal costruttore come 100 byte), oppure fino a quando non scade il lasso di tempo specificato nel parametro RO (timeout di pacchettizzazione). Se avviene uno di questi due eventi, o se viene inviato al modulo radio la sequenza di comandi AT GT + CC + GT, viene creato un pacchetto con i dati contenuti nel buffer e poi viene inviato al destinatario scelto. Come si può facilmente intuire dalla breve descrizione appena fatta, questa modalità è la più semplice da implementare, in quanto per inviare un pacchetto è sufficiente entrare in command mode, settare il destinatario desiderato, uscire dalla modalità comandi e stampare su seriale direttamente i dati. Questa modalità, però, non offre alcuna garanzia di consegna dei pacchetti, e introduce un problema ancora più complicato da risolvere: cosa succede se arriva solo parte dei dati che sono stati inviati? Infatti, per come l’applicazione è stata pensata e progettata, la perdita di un intero pacchetto non causa praticamente alcun problema alla rete, verrà solamente a mancare una misurazione di un nodo, oppure una richiesta di connessione o una risposta dal gateway che, comunque, scaduto un certo timeout verranno rifatte da chi di dovere, ma la perdita di parte dei dati potrebbe causare comportamenti difficilmente prevedibili. Per come era strutturata inizialmente l’applicazione, infatti, per considerare valido un messaggio è sufficiente ottenere come primo byte la codifica ASCII di una qualsiasi tra le lettere ’a’ ed ’e’ (Per il formato messaggi rimando all’Appendice B) e come carattere finale il valore esadecimale del carattere ’@’, ma non viene fatto alcun controllo sulla lunghezza del messaggio ottenuto, per cui messaggi che inizino con lo stesso carattere valido, e che finiscano con ’@’, ma di lunghezza diversa, verrebbero analizzati allo stesso modo, assegnando man mano i valori letti a precisi campi, a cui poi l’applicazione farà riferimento per procedere nelle proprie elaborazioni. Ora le conseguenze sono tanto banali quanto imprevedibili. È ovvio infatti che si assisterà ad un malfunzionamento del nodo che ha analizzato il messaggio sbagliato, ma è del tutto ignota la reazione, che comunque dipende da quale parte di dati è venuta a mancare. Nel caso in cui venisse a mancare un’intera misurazione o parte di essa, si può presumere che il gateway riceverà un pacchetto con dati senza senso e che inserirà nel database misurazioni completamente errate, visto che non è presente alcun tipo di controllo. Diverso è invece il caso in cui la malformazione del messaggio avvenga per richieste di connessione o in risposte dal gateway, per le quali è veramente difficile immaginare le varie possibili conseguenze. Certo tutto questo è risolvibile prendendo in esame la lunghezza e la validità di un messaggio prima della sua elaborazione, ma questo implicherebbe ulteriori righe di codice su un dispositivo con una memoria davvero limitata. Dall’analisi iniziale fatta sui sorgenti di quello che rappresentava il programma di ogni nodo della rete si è notato che, nonostante la semplicità che il transparent mode porta con sé per l’invio dei dati, il codice viene appesantito notevolmente nella parte che riguarda l’interpretazione dei pacchetti ricevuti. In particolare si è notato che le svariate routine per l’analisi e l’elaborazione per ogni tipo di messaggio hanno contribuito ad un aumento sia delle dimensioni del codice, che della scarsa leggibilità. Capitolo 5 La nuova implementazione del protocollo CERTO L’oggetto di questa tesi è stato creare un applicativo per i nodi XBee che utilizzasse come modalità radio l’API mode. In questo capitolo verranno descritte inizialmente le possibilità offerte dalla nuova modalità API ed in seguito verranno poi spiegate le librerie create per l’utilizzo dell’API mode sui nodi e sul gateway. 5.1 La modalità API Diversamente dal transparent mode, in cui i dati vengono inviati così come arrivano sulla seriale, nella modalità API tutti i dati che entrano o lasciano il modulo radio devono essere contenuti in frames che devono necessariamente rispettare alcune regole (mostrate nell’Appendice A). Le funzionalità che la modalità API mette a disposizione rispetto a quelle che si hanno in modalità trasparente sono notevoli, è infatti possibile: • Conoscere il valore di RSSI, in quanto presente in ogni pacchetto ricevuto come tredicesimo byte. • Ottenere messaggi di avvenuta ricezione o messaggi di notifica a comandi inviati al modulo. • Impostare il destinatario del messaggio senza la necessità di entrare in command mode e cambiare manualmente, ad ogni invio, il parametro DL (Destination Low). • Inviare immediatamente il pacchetto stampandolo tutto su seriale una volta preparato, evitando di dover aspettare qualche millisecondo per ogni singolo carattere stampato o, nel caso dei caratteri per entrare in command mode, centinaia di millisecondi. • Conoscere il mittente di ogni pacchetto ricevuto. Esiste inoltre una seconda modalità API (parametro del modulo radio API=2), del tutto identica alla modalità precedente (API=1), tranne che per la particolarità 33 34CAPITOLO 5. LA NUOVA IMPLEMENTAZIONE DEL PROTOCOLLO CERTO che alla parte dati di ogni pacchetto deve essere applicato lo XOR con il valore esadecimale 0x20. Questa modalità, comunque, non verrà approfondita in quanto non utilizzata in questo progetto. 5.2 XBee: le librerie per i nodi Per la creazione dell’applicativo dei nodi è stato utilizzato l’ambiente di sviluppo di Arduino, che semplifica notevolmente sia la stesura del codice, sia i successivi passi di compilazione e upload sulla board su cui si trova il modulo radio. La creazione di una libreria per la gestione delle possibilità offerte dalla modalità API è risultata necessaria al fine di rendere più efficiente e più semplice la stesura del sorgente. Si è pensato quindi di partire da una libreria presente [12] che già implementava parte dei metodi necessari al progetto, estendendola con nuove funzioni in grado di gestire il formato messaggi introdotto nel progetto CERERE e adattando le funzioni presenti alle esigenze richieste. La libreria è stata chiamata XBee_lib e permette, in modo piuttosto semplice, di gestire qualsiasi aspetto del modulo radio: dall’inizializzazione alla velocità di trasmissione desiderata, all’invio o ricezione di pacchetti secondo gli standard precedentemente mostrati. La libreria è stata aggiornata per dare la possibilità di interpretare correttamente i messaggi nel formato introdotto dal progetto CERERE, (vedi Appendice B) da cui si è preso spunto per questa tesi: nonostante la concreta e sensata possibilità di modifica del formato messaggi, si è ritenuto opportuno mantenere lo standard precedentemente definito al fine di una più immediata fusione con gli applicativi di gestione della rete già esistenti. Verrà di seguito mostrata la semplicità con cui è possibile ottenere i dati di un messaggio ricevuto dal modulo radio di un nodo. Innanzitutto viene richiamato il metodo della classe XBeeReader poll(long time), il quale si incarica di leggere i dati dalla seriale aspettando prima un tempo tanto lungo quanto indicato nella variabile time (di default posta a 20 ms). In seguito passa tutti i dati letti alla funzione xbee_in che ha la funzione di salvare i dati che mano a mano arrivano nella struttura XBeeDataFrame, appositamente creata sulla base del tipo di pacchetto ricevuto (per eventuali chiarimenti sulle strutture delle frame fare riferimento all’Appendice A) ed infine setta la variabile booleana available al valore vero. Viene di seguito mostrato il sorgente di tale funzione: void XBeeReader :: poll ( long time ){ delay ( time ); while ( serial_ . available ()) { char c ; c = serial_ . read (); xbee_in (& xbee_ctx_ , &c , 1); } } Una volta richiamata questa funzione il programma legge il valore della variabile available, nel caso contenga il valore vero allora significa che il modulo radio ha ricevuto un pacchetto valido per cui viene richiamata la funzione della classe XBeeReader getXBeeReading(XBeeDataFrame &frame) che ha il compito di copiare i dati letti nella struttura di tipo XBeeDataFrame propria del programma in esecuzione. 5.3. SERIAL: LE LIBRERIE PER IL GATEWAY 35 Viene poi richiamato il metodo getMessageData(unsigned char *data) che ha il compito di analizzare la parte dati del pacchetto e ritorna l’identificativo del messaggio ricevuto. Tale funzione è stata così implementata: unsigned char XBeeDataFrame :: getMessageData ( unsigned char * data ){ xbee_pkt_t * pkt = ( xbee_pkt_t *) packet ; memset ( data , 0 , sizeof ( data )); if ( pkt - > type == RX16 ){ switch ((( xbee_a16_tx_pkt_t *) pkt ) - > data [0]){ case BEACON : memcpy ( data , (( xbee_a16_tx_pkt_t *) pkt ) - > data , sizeof ( beacMsg )); return BEACON ; case ASK_ASSOCIATION : case SEND_DATA : case GATEWAY_RESPONSE : memcpy ( data , (( xbee_a16_tx_pkt_t *) pkt ) - > data , sizeof ( gwMsg )); return data [0]; case ANSWER_ORPHAN : memcpy ( data , (( xbee_a16_tx_pkt_t *) pkt ) - > data , sizeof ( answMsg )); return ANSWER_ORPHAN ; default : return 0; } } else { return -1; } return 0; } Grazie a queste indicazioni risulterà semplice capire il metodo ReceiveMessage() preso direttamente dal programma di un nodo per la lettura del tipo di messaggio in arrivo: unsigned char ReceiveMessage (){ /* Se sono arrivati dati sulla seriale li salva in un pacchetto e imposta lo stato xbee . available a 1 */ xbee . poll (); /* Vero solo nel caso in cui siano arrivati pacchetti */ if ( xbee . available ()){ // Ottengo il pacchetto API xbee . getXBeeReading ( f ); /* Ritorno il tipo di messaggio CERTO ricevuto */ return f . getMessageData ( data ); } } 5.3 Serial: le librerie per il gateway Il gateway si differenzia dagli altri nodi sia a livello applicativo che a livello fisico. Per quanto riguarda il software, infatti, il gateway ha il compito di inviare i beacon di sincronizzazione per tutti gli altri nodi e scegliere gli indirizzi da assegnare ai 36CAPITOLO 5. LA NUOVA IMPLEMENTAZIONE DEL PROTOCOLLO CERTO nodi entranti. Per quanto riguarda l’hardware, invece, il gateway è costituito da un mini-pc a cui è collegato il modulo radio e non, come per gli altri nodi, da una board Arduino con modulo XBee. È stato quindi necessario dar vita ad una nuova libreria, che implementasse metodi per inviare e ricevere dati sulla seriale di un computer con una distribuzione Linux installata. Si è pensato quindi di scrivere Serial, una libreria di fatto identica nelle funzioni alla libreria XBee, in cui sono state modificate tutte le chiamate a sistema di apertura, lettura e scrittura su seriale, in modo da poter essere utilizzate su un sistema Linux e non più su una scheda Arduino. Inizialmente viene inizializzata la porta seriale /dev/ttyUSB0 impostando i vari parametri della struttura termios in modo che la funzione di lettura non blocchi l’esecuzione del programma, ma ritorni ogni singolo carattere se presente, altrimenti ritorni lo stato di errore. Viene riportato di seguito parte delle impostazioni per l’apertura corretta della porta seriale: int XBeeReader :: begin () { struct termios opciones ; // Apre la porta seriale / dev / ttyUSB0 if (( sd = open ( serialPort , O_RDWR | O_NOCTTY | O_NDELAY )) == -1) { fprintf ( stderr , " Unable ␣ to ␣ open ␣␣ ␣␣ ␣␣ ␣␣ the ␣ serial ␣ port ␣ % s !\ n " , serialPort ); exit ( -1); } // Resetta i precedenti valori memset (& opciones , 0 , sizeof ( struct termios )); tcgetattr ( sd , & opciones ); // Imposta la velocita ’ di rx e tx cfsetispeed (& opciones , B9600 ); cfsetospeed (& opciones , B9600 ); // Imposta la modalita ’ non - bloccante opciones . c_cc [ VMIN ] = 1; opciones . c_cc [ VTIME ] = 0; tcsetattr ( sd , TCSANOW , & opciones ); // Svuota i buffer di input e output fcntl ( sd , F_SETFL , FNDELAY ); tcflush ( sd , TCOFLUSH ); tcflush ( sd , TCIFLUSH ); // Inizializza il contesto del programma xbee_init (& xbee_ctx_ ); xbee_user_context ( xbee_ctx_ ) = this ; return 0; } Nella fase iniziale del programma del gateway viene quindi aperta la porta seriale e viene salvato l’identificatore associato nella variabile sd. Ogni qual volta si desideri inviare al modulo radio dei dati sarà pertanto sufficiente utilizzare il metodo write(int fd, const void *buf, size_t count), così come implementato nel metodo adibito all’invio delle frame lato gateway: int xbee_out ( xbee_pkt_t * pkt , uint8_t len , int sd ){ write ( sd , ( unsigned char *) pkt , len ); return 0; } Sono state apportate modifiche, inoltre, al metodo che si occupa della lettura da seriale, appunto perché non era più possibile utilizzare le librerie messe a disposizione dall’ambiente di sviluppo Arduino, per cui si è ricorso al metodo read(int fd, void *buf, size_t count). Viene di seguito mostrato come è stato implementato il metodo per la lettura dei dati in arrivo alla seriale lato gateway: void XBeeReader :: poll ( void ){ char c ; while ( read ( sd , &c , 1) >0) { xbee_in (& xbee_ctx_ , &c , 1); } } Grazie a queste modifiche apportate solamente all’implementazione dei metodi delle varie librerie è stato possibile utilizzare anche per il gateway routine create nell’applicativo dei nodi. Il risultato ottenuto utilizzando queste due librerie è un sorgente con poche righe di codice (circa un quinto dell’implementazione precedente) e molto leggibile. Capitolo 6 Analisi dei risultati sperimentali In questo capitolo verranno discussi i risultati ottenuti, i test effettuati e la bontà di tali sperimentazioni. La maggior parte dei test sono stati incentrati sull’affidabilità della nuova implementazione del protocollo di routing CERTO piuttosto che sulla massima distanza a cui due nodi possano essere messi per restare in comunicazione, ritenendo che questo secondo parametro non avesse alcun tipo di legame con la scelta della modalità di trasmissione, sostanziale differenza dall’implementazione precedente. Sono stati pertanto mantenuti i risultati ottenuti nella tesi da cui questo progetto ha preso ispirazione, in cui si è notato, in particolar modo, che in campo aperto e in line of sight, due nodi possono essere mantenuti ben oltre i 100 metri di distanza, risultato ragguardevole considerando che tale distanza rappresenta il limite imposto dal costruttore, con l’unico vincolo che siano sollevati entrambi da terra di almeno un metro e non ci siano ostacoli nel mezzo. Partendo da questi presupposti si è ritenuto tanto opportuno quanto comodo effettuare i test in un ambiente indoor, con i nodi poco distanziati l’uno dall’altro, in modo da poter controllare facilmente le segnalazioni di connessione e sincronizzazione indicate dallo stato dei led attivati e spenti dal programma a seconda della fase in cui il nodo si trova ad operare. 6.1 Test sulla topologia della rete Per valutare l’affidabilità del protocollo sono stati effettuati diversi test in cui di volta in volta veniva cambiata la topologia e il numero di livelli della rete. Verranno di seguito spiegate le varie tecniche adottate e i risultati a cui queste sperimentazioni hanno condotto. 6.1.1 Rete a stella Una rete viene definita a stella quando tutti i nodi che vi appartengono comunicano direttamente con il nodo centrale o gateway, così come mostrato in Figura 6.1 dove i nodi sono colorati in giallo e il gateway in blu. Si ricorda che, per come è stato sviluppato l’applicativo, ogni nodo sceglie il proprio padre dai beacon di sincronizzazione ricevuti, optando per quello con minor numero di hop a meno che 39 40 CAPITOLO 6. ANALISI DEI RISULTATI SPERIMENTALI Figura 6.1: Schema base di una rete a stella. questo non abbia già un numero di figli superiore ad una soglia, memorizzata in una costante definita come CHILD_TRESHOLD. Questo comporta due possibili alternative per permettere la creazione di una rete di questo tipo: • Accensione contemporanea dei nodi: i nodi, se accesi tutti contemporaneamente, entrano nella fase di Beacon Scan tutti nello stesso istante, ricevendo tutti come unico messaggio di sincronizzazione quello del gateway, ritenendolo quindi l’unico padre possibile. • Aumento del valore della costante CHILD_TRESHOLD e re-deploy dell’applicativo sui nodi: aumentando il valore di questa costante oltre modo, o più semplicemente impostandola grande quanto il numero massimo di figli accettabili all’interno della rete, ogni nodo sceglierà il proprio padre solamente sulla base del numero di salti dal gateway. Considerando quindi che tutti i nodi ricevono il beacon dal sink, in quanto tutti abbastanza vicini, risulta evidente che si verrà a formare la rete a stella desiderata. Tra le due soluzioni appena mostrate la prima funziona solamente con tre o massimo quattro nodi, in quanto il gateway difficilmente riesce a rispondere contemporaneamente a più di quattro risposte di Ask Association nella stessa fase di Connection, per cui i nodi ignorati ricadranno nella fase di Beacon Scan, ma questa volta riceveranno i messaggi di sincronizzazione anche dei nuovi nodi entrati, il che portare a scelte diverse in base al valore di CHILD_TRESHOLD. La seconda soluzione, invece, non presenta alcun problema sul numero di nodi, ma è piuttosto scomoda in quanto richiede una variazione nel sorgente originale e una ricompilazione con conseguente upload su ogni nodo interessato. Tuttavia, essendo la più affidabile tra le due soluzioni, è stata scelta questa seconda via, salvando il nuovo sorgente come nuovo applicativo, apposito per questo tipo di test. Dopo numerose prove si è notato che il protocollo implementato è molto robusto in questa configurazione: i nodi perdono molto raramente il beacon di sincronizzazione e il messaggio contenente i dati arriva nei primi 100 ms dello slot che il gateway assegna ad ogni nodo. 6.1. TEST SULLA TOPOLOGIA DELLA RETE 41 Va precisato che nel caso in cui un nodo perda per qualche motivo il messaggio di sincronizzazione, esso invierà comunque i dati utilizzando come riferimento il Beacon precedente e solo nel caso in cui ne perda quattro in successione, praticamente impossibile a meno di problemi sul nodo padre, procederà alla ricerca di un nuovo collegamento più affidabile con il gateway. Questo piccolo espediente, che di fatto modifica la versione originale del protocollo CERTO in cui i dati venivano inviati solamente nel caso di avvenuta ricezione del messaggio di Beacon, ha permesso di raggiungere un ottimo livello di affidabilità per quanto riguarda la raccolta dei dati. 6.1.2 Rete ad albero Con rete ad albero si è voluto intendere in realtà una rete in cui ogni nodo entrante sceglie come padre il nodo con maggior numero di hop dal gateway (Figura 6.2), così da valutare tempi di ritardo introdotti dall’inoltro dei dati e eventuali problemi nel forwarding delle richieste di connessione e delle relative risposte. Per fare questo è stato nuovamente modificato il sorgente cambiando la condizione di scelta del padre, facendo in modo che tra i possibili padri venisse scelto, appunto, quello che presentava il maggior numero di salti dal nodo centrale. Come verrà poi mostrato Figura 6.2: Schema base di una rete ad albero. nella successiva Sezione 6.2, ed in particolar modo nella Tabella 6.1, ogni hop introduce un piccolo tempo di ritardo dovuto all’elaborazione dei dati in arrivo e alla ritrasmissione degli stessi. Nonostante questo tempo di delay intrinseco alla topologia della rete e ineliminabile, ma, in caso, solamente diminuibile, la rete ha risposto in maniera ottimale, mantenendo un percentuale molto prossima al 100% di pacchetti dati ricevuti lato gateway. 6.1.3 Rete mista In questo ultimo test è stato ricaricato su ogni nodo l’applicativo in cui la routine per la scelta del padre è così impostata: 42 CAPITOLO 6. ANALISI DEI RISULTATI SPERIMENTALI 1. tra i due nodi a confronto viene scelto il nodo con minor numero di hop dal gateway a meno che questo non abbia già almeno tre figli. 2. viene scelto il nodo con minor numero di figli nel caso in cui il confronto venga fatto tra due nodi equidistanti dal gateway. Questa rappresenta una lieve rivisitazione della routine originale del protocollo, in cui non veniva fatta distinzione nel caso in cui il numero di hop del gateway fosse strettamente uguale tra i due nodi considerati. Figura 6.3: Schema di esempio di una possibile configurazione di rete. Dopo alcune prove si è notato che la topologia della rete (di cui un esempio in Figura 6.3) può subire molte variazioni a seconda del momento in cui un nodo viene acceso. La routine di scelta del padre, infatti, si basa sui messaggi di sincronizzazione che vengono ricevuti all’inizio della fase Connection, per cui prima dell’elaborazione di eventuali richieste di associazione fatte in quell’intervallo. Ciò significa che nodi accesi più o meno nello stesso istante valuteranno tutti come padre ideale lo stesso nodo, di fatto deviando l’idea iniziale in cui ogni nodo non possa essere sovraccaricato di figli. Nonostante queste considerazioni e ricordando che comunque il gateway difficilmente risponde a più di quattro richieste all’interno della stessa fase di Connection, sono state fatte diverse prove variando i tempi di attivazione di ogni nodo al fine di valutare le reazioni della rete. I risultati sono stati molto soddisfacenti: l’ordine in cui i nodi vengono accesi modifica la topologia della rete, ma non il grado di affidabilità del protocollo. 6.2 Analisi temporale dei dati in arrivo I dati ottenuti portano alla considerazione che la dimensione dello slot temporale deve tenere conto non solo del numero di nodi che può avere la rete, ma anche del numero massimo di salti che un nodo dovrebbe affrontare per poter far arrivare i propri dati al gateway. 43 6.3. PARAGONE TRA SORGENTI Per valutare correttamente la dimensione dello slot temporale per la trasmissione dei dati sono stati effettuati alcuni test da cui si sono ricavati il tempo medio e la deviazione standard sulla base del numero di hop di ogni nodo dal gateway. Come si può notare in Tabella 6.1, il gateway riceve i dati inviati dai nodi distanti solamente un hop con un ritardo medio di circa 50 ms dall’inizio dello slot temporale, e una deviazione standard di circa 9 ms, il che garantisce la ricezione di tutti i dati nei primi 100 ms dall’inizio dello slot per i nodi più prossimi al sink. Per i nodi più distanti, invece, si nota come ogni hop introduca un ritardo di circa 100 ms e contribuisca a peggiorare leggermente la sincronizzazione, evidenziata da un valore via via crescente della deviazione standard. Tabella 6.1: Tempi di arrivo dei dati sulla base del numero di hop dal gateway. 1 2 3 4 hop hop hop hop Media (ms) Deviazione standard (ms) 49.8 153.3 257.0 360.0 9.3 16.0 17.7 19.2 Ciò significa quindi, che nel caso di uno slot di 1 secondo, il numero di hop di un nodo dal gateway non potrà essere superiore a 10, altrimenti si correrebbe il rischio di invadere slot altrui o di perdere completamente il pacchetto con i dati. 6.3 Paragone tra sorgenti Al termine della creazione dell’applicazione per i nodi è stato effettuato un primo test in cui si è valutata la quantità di memoria occupata sulla flash di Arduino. Si è notata la netta differenza rispetto alla precedente implementazione in Transparent mode: solamente 8 KB rispetto ai 13,5 KB della versione originale in modalità trasparente, non pochi se considerati sulla base dei 14 KB a disposizione. Nonostante la modalità API abbia introdotto notevoli difficoltà in fase di programmazione, basti pensare che è stata introdotta una libreria apposita per la gestione dei messaggi che prima non aveva motivo di esistere, la possibilità di creare funzioni specifiche per l’invio/ricezione di frames in cui modificare solamente la parte di dati, con un ulteriore ristrutturazione del codice esistente, ha permesso di raggiungere un guadagno in termini di memoria libera, ciò ha di fatto aperto possibilità prima impossibili come protocolli di routing più complessi o gestioni più dettagliate di stand-by del microprocessore o del modulo radio. Tra le altre cose, il codice sorgente ha guadagnato molto in leggibilità, utilizzando al proprio interno chiamate a libreria come per esempio il metodo send() per inviare dati, oppure il metodo getMessageFromData() per ricavare il messaggio impacchettato all’interno della frame, che hanno contribuito diminuire ad oltre un quarto le righe di codice, rendendo quindi il tutto più comprensibile e facilmente aggiornabile. È stato poi effettuato un secondo test: è stata analizzata la quantità di memoria RAM disponibile all’avvio di entrambi i programmi, indice di quanto spazio sia ancora disponibile per salvare dati e variabile in run-time. Per questa prova è stato utilizzato il codice pubblicato sul proprio blog in data 18 Aprile 2007 da un esperto in programmazione di Arduino Rob Faludi[]. Il sorgente adoperato consiste in un’unica funzione da aggiungere subito dopo l’inizializzazione della seriale che si occupa semplicemente di allocare una quantità via via crescente di memoria fino saturarla, in modo che la funzione malloc() utilizzata per l’allocazione dia come valore di ritorno il valore NULL (zero), a questo punto si esce dal ciclo e viene mostrata quanta memoria è stato possibile allocare prima dell’evento appena descritto, nonché la quantità di memoria RAM ancora utilizzabile subito dopo l’avvio del programma stesso. I risultati sono stati quelli previsti: entrambi i programmi, se avviati con variabili delle stesse dimensioni, o più precisamente, in grado di accettare lo stesso numero di figli (di cui bisogna salvare per ognuno l’indirizzo) e con una uguale dimensione per la tabella di routing, presentano la stessa quantità di RAM ancora avviabile, pari a 78 bytes, molto pochi per una valida implementazione di nuove funzionalità. Tuttavia va detto che il modulo offre solamente 1 KB di memoria RAM avviabile, e, a titolo di esempio, la sola tabella di routing richiede 6 bytes per la memorizzazione di un singolo record, che se moltiplicato per un numero di figli pari a 20 porta ad uno spazio occupato di 120 bytes: più di un decimo della memoria disponibile per un singolo array, il cui scopo è relativamente modesto se paragonato alle variabili necessarie per la memorizzazione degli indirizzi o dei dati in transito sul modulo radio. Nonostante ciò, va comunque fatto notare che nella nuova implementazione tutta la memoria liberata dalla memoria Flash può essere utilizzata come espansione della RAM, che, sebbene ne perda in prestazioni, potrebbe tornare molto utile in caso di progetti più complessi o nuove implementazioni. Capitolo 7 Conclusioni e sviluppi futuri In questo progetto di tesi si è cercato di apportare alcune migliorie tecniche al protocollo di routing CERTO progettato e sviluppato per il progetto CERERE e, soprattutto, effettuare il porting dalla precedente implementazione in Transparent Mode alla più affidabile e veloce versione basata sulla modalità API. Si può dire che tale obiettivo sia stato completamente raggiunto, riuscendo a raggiungere i risultati sperati di un’ottima affidabilità del protocollo e una notevole diminuzione nella dimensione del sorgente, aprendo le porte per nuove implementazioni software prima trascurate a causa della mancanza di spazio in memoria. Funzionalità come sleep/wakeup del modulo radio e stand by del microcontrollore, per esempio, dovrebbero essere sicuramente aggiunte per garantire una vita alle batterie dei nodi adeguatamente lunga all’applicazione. Un altro notevole passo in avanti è stato fatto per quanto riguarda i tempi impiegati nell’elaborazione dei messaggi. Nella precedente modalità trasparente erano necessari 12 millisecondi solamente per impostare il destinatario del prossimo messaggio: era infatti indispensabile aspettare qualche millisecondo dopo ogni comando solamente per essere sicuri che il messaggio venisse ricevuto dal modulo radio. Ora invece, essendo un parametro da inserire all’interno della frame da inviare il tempo necessario è solamente quello impiegato dal microcontrollore per creare il pacchetto e calcolare il checksum da mettere come ultimo byte (di molto inferiore al millisecondo). Infine si è guadagnato in sicurezza: in particolare si è notato che con la modalità trasparente era sufficiente, utilizzando un nuovo modulo radio configurato sullo stesso canale e PAN ID, impostare come destinatario l’indirizzo di broadcast ed entrare in modalità comandi per modificare o addirittura annientare l’intera rete, inviando comandi errati che alterassero indirizzi o anche semplicemente inviando il comando di reset. Per quanto riguarda la modalità API invece, non è possibile inviare comandi AT da remoto, per cui non è possibile sabotare il funzionamento della rete; si potrebbero eventualmente inviare misurazioni fasulle ma, attraverso alcuni opportuni controlli, si potrebbe superare anche questo problema. Sono inoltre ancora irrisolti alcuni problemi presenti nel sistema e non oggetto di questa tesi tra cui, innanzitutto, la politica adottata dall’algoritmo di routing per l’inoltro dei dati. È vero infatti che associare ad ogni nodo uno slot risulta scomodo perché causa, di fatto, una limitazione del numero dei nodi: se ogni figlio deve identificare univocamente lo slot in cui è abilitato a inviare le proprie misurazioni, 45 questo comporta una limitazione del numero massimo di nodi nella rete, limitato superiormente dal numero di slot ammessi nella fase Data. Viene inoltre sprecato molto tempo che potrebbe essere invece impiegato per l’invio dei dati. Questo avviene sia a causa della soglia di guardia aggiunta all’inizio ed alla fine di ogni slot per evitare che un nodo con scarsa sincronizzazione possa invadere intervalli altrui, sia perché lo slot viene mantenuto abbastanza largo da mantenere possibile reti a diversi livelli (considerando che ogni livello introduce circa 100 millisecondi di ritardo). Il risultato di tutto ciò è un aumento dell’energia consumata: il mantenere attivo il modulo radio per tempi lunghi causa un rilevante e ingiustificato consumo energetico, con una conseguente diminuzione della vita della batteria, punto fondamentale da tenere in considerazione per un protocollo di routing utilizzato in applicazioni di questo tipo. Queste considerazioni aprono una discussione su quale algoritmo di routing sia quindi meglio implementare per uno sviluppo futuro che tenti di superare i problemi riscontrati finora. La soluzione non è affatto semplice, bisogna tenere conto infatti che escludere l’utilizzo di slot temporali in favore di una comunicazione che sfrutti gli Ack di risposta della modalità API introdurrebbe un aumento dell’utilizzo del modulo radio in trasmissione, fattore di maggior consumo energetico. Risulterebbe inoltre più complesso gestire la sincronizzazione tra i vari nodi: l’eliminazione dei vari sotto-intervalli temporali renderebbe più difficile la gestione dei tempi in cui un nodo deve accendersi per trasmettere le proprie rilevazioni con la certezza che queste non collidano con altri pacchetti in transito e quindi portino alla necessità di una ritrasmissione. Appendice A API Mode: la costruzione di una frame Quando la modalità API è abilitata (API mode = 1), ogni pacchetto che raggiunge il modulo radio deve essere così composto: Figura A.1: Struttura di una frame dati UART. Il valore di checksum Per calcolare il valore corretto di checksum da inserire nell’apposito campo per inviare un pacchetto bisogna sottrarre dal valore esadecimale 0xFF la somma di tutti i byte della frame, eccetto il frame delimiter (0x7E) e i due byte riguardanti la lunghezza, tenendo solamente gli 8 bit meno significativi. Per verificarne la correttezza, quindi, è sufficiente sommare tutti i byte della frame, esclusi frame delimiter e length, al valore di checksum; se il valore è corretto gli 8 bit meno significativi varranno 0xFF. A.1 Struttura dati API La parte dati di ogni frame deve essere strutturata secondo le specifiche che il byte di tipo API (API identifier) determina: Il valore del byte cmdID identifica univocamente la struttura dati che sarà contenuta all’interno della parte cmdData. Verranno qui di seguito mostrate le strutture dei pacchetti utilizzati nel progetto. Gli esempi sono stati presi direttamente dal manuale XBee 802.15.4 v.1 [7]. 47 48 APPENDICE A. API MODE: LA COSTRUZIONE DI UNA FRAME Figura A.2: Struttura di una frame dati con vista in dettaglio della parte dati API. A.2 Stato del modem Identificatore API: 0x8A. Messaggi di stato vengono mandati dal modulo radio in risposta a particolari eventi: Figura A.3: Struttura di una frame di tipo Stato del modem. A.3 Comandi AT Identificatore API: 0x08. Il tipo di messaggio comandi AT permette di interrogare o impostare parametri del modulo radio. Per ottenere una risposta dal modulo contenente il valore attuale di un determinato parametro è sufficiente inviare un pacchetto contenente un comando AT senza la parte Parameter value. Nel caso in cui, invece, si desideri cambiare la configurazione del modulo, la sezione Parameter value dovrà contenere il valore che si desidera impostare. Si A.3. COMANDI AT 49 noti che le modifiche vengono apportate immediatamente al modulo, il quale, come risposta, invierà un messaggio di tipo Risposta ad un comando AT contenente lo stato di uscita che il precedente comando ha generato. Figura A.4: Struttura di una frame di tipo Comando AT. Vengono di seguito riportati due esempi (uno di interrogazione e uno di impostazione) di un commando AT in API mode. La Figura A.5 mostra come sia Figura A.5: Esempio di interrogazione del modulo. Figura A.6: Esempio di impostazione del modulo. possibile ottenere il valore attuale di un parametro del modulo radio. In questo caso è stato richiesto il parametro DL, Destination Low, che veniva utilizzato in Transparent mode per definire il destinatario del pacchetto. Nella Figura A.6 viene mostrato come settare il parametro DL al valore esadecimale 0x0FFF, cioè imposta l’indirizzo a 16 bit del destinatario. A.4 Risposta ad un comando AT Identificatore API:0x88. In risposta ad un messaggio di tipo Comando AT, il modulo invierà un messaggio di tipo “Risposta ad un comando AT“. Alcuni comandi potrebbero causare l’invio di più di una frame (per esempio il comandi ND, Node Discovery, o AS, Active Scan). La struttura del messaggio “Risposta ad un comando AT“ viene riportata in Figura A.7; Figura A.7: Struttura di una frame di tipo Risposta ad un comando AT. A.5 Richiesta TX (Trasmissione) ad un indirizzo a 16 bit Identificatore API: 0x01. Una frame di tipo Richiesta TX a 16 bit causa l’invio dei dati dal modulo radio nell’etere. Figura A.8: Struttura di una frame di tipo Richiesta TX a 16 bit. A.6 Pacchetto RX (Ricezione) Identificatore API : 0x80. Quando il modulo radio riceve un pacchetto RF, invia all’uscita UART un messaggio di tipo Pacchetto RX. A.6. PACCHETTO RX (RICEZIONE) Figura A.9: Struttura di una frame di tipo Pacchetto RX. 51 Appendice B Il Formato dei messaggi utilizzato Verrà di seguito riportato uno schema del formato messaggi utilizzato. B.1 Messaggio di Ask Association Figura B.1: Struttura di un messaggio di tipo Ask Association. • byte 1: identificatore del messaggio (valore ascii esadecimale 0x61). • bytes 2-5: SerialLow del nodo entrante che ha inviato la richiesta di associazione. • bytes 6-7: MY del nodo scelto come padre. • bytes 8-9: MY del last forwader che ha inoltrato il messaggio. • byte 10: contatore di hop. B.2 Messaggio Send Data Figura B.2: Struttura di un messaggio di tipo Send Data. 53 54 APPENDICE B. IL FORMATO DEI MESSAGGI UTILIZZATO • byte 1: identificatore del messaggio (valore ascii esadecimale 0x62). • bytes 2-3: MY del nodo che invia le rilevazioni. • byte 4: numero di sequenza del messaggio dati. • bytes 5-6: valore di luminosità. • bytes 7-8: valore di umidità. • bytes 9-10: valore di temperatura. B.3 Messaggio di Gateway Response Figura B.3: Struttura di un messaggio di tipo Gateway Response. • byte 1: identificatore del messaggio (valore ascii esadecimale 0x63). • bytes 2-3: MY del nodo padre. • byte 4-7: SerialLow del nodo che ha fatto richiesta di associazione. • bytes 8-9: MY assegnato al nodo orfano. • byte 10: numero di hop tra nodo orfano e gateway. B.4 Messaggio di Answer Orphan Figura B.4: Struttura di un messaggio di tipo Answer Orphan. • byte 1: identificatore del messaggio (valore ascii esadecimale 0x64). • bytes 2-5: SerialLow del nodo entrante. • bytes 6-7: MY assegnato al nodo orfano. • byte 8: numero di hop tra nodo orfano e gateway. B.5 Messaggio di Beacon Figura B.5: Struttura di un messaggio di tipo Beacon. • byte 1: identificatore del messaggio (valore ascii esadecimale 0x65). • bytes 2-3: MY del nodo che ha inviato il messaggio. • byte 4: numero di hop dal gateway. • byte 5: numero di figli attuali. • bytes 6-9: intervallo di trasmissione. Appendice C Codice Sorgente della tesi C.1 MoteAPI.pde # include < XBeeReader .h > # include < stdlib .h > # ifndef # define # define # define # endif SENSORI sens0 0 sens1 1 sens2 2 // Sensore di l u n i m n o s i t a ’ // Sensore di umidita ’ // Sensore di t e m p e r a t u r a /* V a r i a b i l i globali ( Le v a r i a b i l i globali vengono tutte i n i z i a l i z z a t e a zero dal c o m p i l a t o r e ) */ extern v o l a t i l e u n s i g n e d long timer0_millis ; XBeeReader xbee ( Serial ); /* I n i z i a l i z z a un oggetto di tipo xbee aprendo la porta seriale con v e l o c i t a ’ 115200 */ XBeeDataFrame f ; /* I n i z i a l i z z a un oggetto di tipo X B e e D a t a F r a m e che c o n s e n t e di e l a b o r a r e i p a c c h e t t i da e l a b o r a r e dal modulo radio */ uint8_t serialLow [4] , seqNumber ; /* V a r i a b i l e che c o n t i e n e il serial Low */ uint8_t my [2] , n_hop ; /* V a r i a b i l e che c o n t i e n e il MY del padre scelto , e il My del nodo */ uint8_t data [ sizeof ( askMsg )]; /* Stringa c o n t e n e n t e di volta in volta i m e s s a g g i in i n g r e s s o ( sizeof ( askMsg ) e ’ la l u n g h e z z a massima che un m e s s a g g i o puo ’ avere ) */ ChildNode * myChildren ; /* Tabella dove vengono salvati i figli */ /* S t r u t t u r a c o n t e n e n t e i dati del proprio padre */ p o t e n t i a l P a r e n t T a b l e myParent ; routingTable * route ; /* Tabella con le regole di routing per i n o l t r a r e m e s s a g g i per o dal sink */ u n s i g n e d short int connected , wait_iteration , missedBeacon , numChild ; u n s i g n e d long mainTime , intervalB ounds [2]; u n s i g n e d long interval = I N I T I AL _ I N T E R V A L ; // P r o g r a m m a void setup (){ if ( StartUpRadio () < 0){ // ERRORE nel settare il modulo radio !!! // Reset } ReceiveBeacon (); // Una volta avviato il modulo radio } void loop (){ if ( missedBeacon > 3){ missedBeacon = 0; 57 58 APPENDICE C. CODICE SORGENTE DELLA TESI connected = 0; wait_ iteratio n =0; free ( myChildren ); /* Nel caso in cui abbia perso 4 o piu ’ beacon cerco un altro padre , ma prima azzero tutte le v a r i a b i l i */ free ( route ); ReceiveBeacon (); } if (! connected ){ S e n d A s k A s s o c i a t i o n (); } if ( connected ){ Conne ctionTim e (); } } int StartUpRadio (){ int r = xbee . begin () // Set the default 9600 baud rate for the serial port if ( r < 0){ return -1; } delay (15000); /* Aspetto il tempo n e c e s s a r i o alla c o r r e t t a i n i z i a l i z z a z i o n e del modulo radio */ xbee . se nd _A T _C om ma n d (0 , " CH " , 1 , ( const uint8_t *) " \ x0c " ); /* Setto il canale di c o m u i c a z i o n e a " C " */ delay (250); // Setto il PANID a "1111" xbee . se nd _A T _C om ma n d (0 , " ID " , 2 , ( const uint8_t *) " \ x11 \ x11 " ); delay (250); // Salvo il s e r i a l L o w nell ’ a p p o s i t a v a r i a b i l e xbee . se nd _A T _C om ma n d (1 , " SL " ); xbee . poll (500); if ( xbee . available ()){ xbee . get XBeeRead ing ( f ); f . g e t A T C o m m a n d R e s p o n s e D a t a ( serialLow , 4); } /* xbee . s e n d _ A T _ C o m m a n d (0 , " WR "); delay ( 4 0 0 0 ) ; / / Nel caso in cui si v o g l i a n o rendere d e f i n i t i v e le m o d i f i c h e */ return 0; } int ReceiveBeacon (){ u n s i g n e d int x =0 , pa rTableLe ngth =0; u n s i g n e d long timer =0; /* V a r i a b i l e che serve per a t t e n d e r e beacon s u c c e s s i v i al primo per circa 3 secondi */ u n s i g n e d short int f i r s t _ b e a c o n _ r e c e i v e d = 0; p o t e n t i a l P a r e n t T a b l e * p ot e nt ia lP ar e nt = ( p o t e n t i a l P a r e n t T a b l e *) calloc ( MAXPARENT , sizeof ( p o t e n t i a l P a r e n t T a b l e )); // Tabella dei padri route = ( routingTable *) calloc ( MAXCHILD , sizeof ( routingTable )); TurnR adioStat e (1); // Accendo il modulo radio e il led if ( millis () > 30000000){ // Se sono passate 8 h e 30 min circa resetto l ’ o r o l o g i o ResetMillis (); } do { if ( Rec eiveMess age () == BEACON ){ /* Se il p a c c h e t t o r i c e v u t o e ’ un beacon lo a g g i u n g o alla tabella dei padri nel caso in cui non ci sia gia ’ */ timer = millis (); f i r s t _ b e a c o n _ r e c e i v e d = 1; for ( x =0; x < parTa bleLengt h ; x ++){ if ( memcmp ((( beacMsg *) data ) - > my , p o te nt ia l Pa re nt [ x ]. my , 2) == 0){ break ; } } if ( x == parTab leLength ){ memcpy ( p ot en ti a lP ar en t [ x ]. my , (( beacMsg *) data ) - > my , 2); p ot en ti a lP ar en t [ x ]. n_hop_rcv = (( beacMsg *) data ) - > n_hop ; p ot en ti a lP ar en t [ x ]. n_child_rcv = (( beacMsg *) data ) - > n_children ; memcpy (& interval , (( beacMsg *) data ) - > time , 4); p ot en ti a lP ar en t [ x ]. timestamp = timer - DRIFT ; parTa bleLengt h ++; } C.1. MOTEAPI.PDE } } while (!( f i r s t _ b e a c o n _ r e c e i v e d && (( millis () - timer ) >3000)) && ( parTableLength < MAXPARENT )); /* Esci solo tre secondi dopo aver r i c e v u t o il primo beacon , in modo da r i c e v e r n e e v e n t u a l m e n t e altri */ TurnR adioStat e (0); FindMin ( parTableLength -1 , p ot e nt ia lP a re nt ); free ( po te nt i al Pa re n t ); } int S e n d A s k A s s o c i a t i o n ( void ){ WakeUpOnTime (); TurnR adioStat e (1); if (! wait_it eration ){ // Per tutta la durata della fase c o n n e c t i o n while ( millis () - mainTime < CONNECTION ){ if ( Rec eiveMess age () == BEACON && ! memcmp ( myParent . my , (( beacMsg *) data ) - > my , 2)){ break ; } } randomSeed ( analogRead (5)); delay (35* random (1 ,50)); memset ( data , 0 , sizeof ( data )); (( askMsg *) data ) - > type = AS K _A SS OC I AT IO N ; memcpy ((( askMsg *) data ) - > serialLow , serialLow , 4); memcpy ((( askMsg *) data ) - > myParent , myParent . my , 2); memcpy ((( askMsg *) data ) - > lastForward , my , 2); (( askMsg *) data ) - > n_hop =0; xbee . send (( const char *) data , sizeof ( askMsg ) , ( const uint8_t *) myParent . my ); while ( millis () - mainTime <= ACTIVETIME ){ xbee . poll (100); if ( Rec eiveMess age () == ANSWER_ORPHAN && ! memcmp ((( answMsg *) data ) - > serialLow , serialLow , 4)){ memcpy ( my , (( answMsg *) data ) - > my , 2); xbee . se nd _A T _C om ma n d (0 , " MY " , 2 , ( const uint8_t *) my ); n_hop = (*(( answMsg *) data )). n_hop ; inter valBound s [0] = (( int ) my [1] -1)* SLOTDURATION + GUARD ; inter valBound s [1] = (( int ) my [1])* SLOTDURATION - GUARD ; delay (3000); connected = 1; TurnR adioStat e (0); return 0; } } } TurnR adioStat e (0); if (++ wait_iteration >1 && ! connected ){ wait_ iteratio n = 0; ReceiveBeacon (); return -1; } return -1; } int Conne ctionTim e (){ int beaconForData =0 , dataSent =0; u n s i g n e d short int i =0; long temp ; WakeUpOnTime (); // Mi attivo al p r o s s i m o i n t e r v a l l o TurnR adioStat e (1); // Accendo la radio beaconForData = W a i t S y n c h r o B e a c o n (); /* Aspetto il beacon di s i n c r o n i z z a z i o n e per il tempo della fase c o n n e c t i o n */ if ( beaconForData ){ missedBeacon =0; } else { missedBeacon ++; } while (( temp = millis () - mainTime ) < ACTIVETIME ){ if ( IsMyTime ( temp - CONNECTION ) && ! dataSent ){ /* In questo modo invio 59 60 APPENDICE C. CODICE SORGENTE DELLA TESI i miei dati nel mio slot e una volta sola */ SendMyData (); dataSent ++; } else if ( numChild >0){ if ( Rec eiveMess age ()== SEND_DATA ){ uint8_t d [ sizeof ( sendMsg )]; memcpy (d , data , sizeof ( sendMsg )); xbee . send (( const char *) d , sizeof ( sendMsg ) , ( const uint8_t *) myParent . my ); } } } TurnR adioStat e (0); } int IsMyTime ( long time ){ // F u n z i o n e che serve per s v e g l i a r s i s o l a m e n t e nello slot d e s i d e r a t o if (( time > interv alBounds [0]) && ( time < int ervalBou nds [1])) return 1; else return 0; } int W a i t S y n c h r o B e a c o n (){ /* F u n z i o n e c h i a m a t a all ’ inizio del ciclo una volta che il nodo e ’ c o n ne s s o per a t t e n d e r e il beacon di s i n c r o n i z z a z i o n e e gestire m e s s a g g i durante la fase c o n n e c t i o n */ u n s i g n e d short int beacReceived = 0; /* V a r i a b i l e che verra ’ r i t o r n a t a e avra ’ il valore di s p e c i f i c a r e se e ’ stato r i c e v u t o il beacon di synchro o no */ while ( millis () - mainTime < CONNECTION ){ beacReceived += M a n a g e I n c o m i n g P a c k e t s (); /* b e a c r e c e i v e d viene i n c r e m e n t a t o solo con beacon p r o v e n i e n t i dal proprio padre , il metodo g e s t i s c e tutti i m e s s a g g i che p o t r e b b e r o a r r i v a r e in questa fase */ delay (20); } return beacReceived ; } u n s i g n e d char M a n a g e I n c o m i n g P a c k e t s (){ /* F u n z i o n e per la g e s t i o n e dei m e s s a g g i in arrivo durante la fase di c o n n e c t i o n */ u n s i g n e d char type = Rec eiveMess age (); if ( type == AS K _A SS OC I AT IO N ){ /* Metodo per i n o l t r a r e al padre un a s k _ a s s o c i a t i o n p r o v e n i e n t e da un orfano che vuole entrare nella rete */ if ( numChild < MAXCHILD ){ uint8_t d [ sizeof ( askMsg )]; /* Creo un vettore t e m p o r a n e o di dati per creare il m e s s a g g i o da i n o l t r a r e */ memcpy (d , data , sizeof ( askMsg )); // Mi copio tutti i dati if ( memcmp ((( askMsg *) data ) - > myParent , my , 2)){ /* Se il padre non sono io dovro ’ r i c o r d a r m i a chi i n o l t r a r e il p a c c h e t t o per cui mi salvo il l a s t f o r w a r d e il s e r i a l L o w */ memcpy ( route [ numChild ]. src , (( askMsg *) data ) - > serialLow , 4); /* Salvo il s e r i a l L o w per a s s o c i a r e il m e s s a g g i o alla regola di routing al ritorno sotto forma di gw resp */ memcpy ( route [ numChild ]. lastForw ,(( askMsg *) data ) - > lastForward , 2); /* Salvo il last forward per sapere a chi i n o l t r a r e il m e s s a g g i o al momento della gw resp */ } // Cambio il last forward con il mio i n d i r i z z o memcpy ((( askMsg *) d ) - > lastForward , my , 2); (( askMsg *) d ) - > n_hop += 1; // I n c r e m e n t o il numero di hop // Inoltro il m e s s a g g i o di ask a s s o c i a t i o n xbee . send (( const char *) d , sizeof ( askMsg ) , ( const uint8_t *) myParent . my ); } return 0; } else if ( type == G A T E W A Y _ R E S P O N S E ){ /* Se sono io il padre scelto dall ’ orfano e n t r a n t e m o d i f i c o il m e s s a g g i o in answer orphan */ if (! memcmp ((( gwMsg *) data ) - > myParent , my , 2)){ // Creo un vettore t e m p o r a n e o con la nuova r i s p o s t a C.1. MOTEAPI.PDE 61 uint8_t d [ sizeof ( answMsg )]; // Setto il tipo della r i sp o s t a ad answer orphan (( answMsg *) d ) - > type = ANSWER_ORPHAN ; /* Copio tutti i dati del m e s s a g g i o che mi servono per creare un p a c c h e t t o di tipo answer orphan */ memcpy ((( answMsg *) d ) - > serialLow , (( gwMsg *) data ) - > serialLow , 7); // Lo invio in b r o a d c a s t perche ’ l ’ orfano non ha ancora un my xbee . send (( const char *) d , sizeof ( answMsg )); // A l t r i m e n t i lo inoltro s e m p l i c e m e n t e al figlio che mi ha fatto la r i c h i e s t a } else { int x ; for ( x =0; x < MAXCHILD ; x ++){ // Se trovo nella tabella di routing da chi p r o v i e n e l ’ ask a s s o c i a t i o n lo inoltro if (! memcmp ( route [ x ]. src , (( gwMsg *) data ) - > serialLow , 4)){ uint8_t d [ sizeof ( answMsg )]; // Mi copio i dati in un array t e m p o r a n e o memcpy (d , data , sizeof ( gwMsg )); // Inoltro la gw r e s p o n s e al last f o r w a r d e r secondo le regole salvate xbee . send (( const char *) d , sizeof ( gwMsg ) , ( const uint8_t *) route [ x ]. lastForw ); /* Azzero la regola di r o u n t i n g nella tabella del figlio a cui ho appena inviato la r i s p o s t a */ memset (( void *) & route [ x ] , 0 , sizeof ( routingTable )); break ; } } } numChild ++; return 0; } // Se e ’ un beacon ed e ’ mio padre ad averlo inviato ( a l t r i m e n t i f l o o d i n g ) else if ( type == BEACON && ! memcmp ( myParent . my , (( beacMsg *) data ) - > my , 2)){ /* Per evitare di inviare dati ad un padre che si e ’ d i s c o n n e s s o e che non sa di avere figli */ if ((( beacMsg *) data ) - > n_children == 0){ missedBeacon =4; return 0; } myParent . timestamp = millis () - DRIFT ; /* A g g i o r n o il t i m e s t a m p per il p r o s s i m o r i s v e g l i o a g g i u s t a n d o l o in modo da tenere conto del tempo i m p i e g a t o dai nodi per inviare il m e s s a g g i o e per i n o l t r a r l o */ // A g g i o r n o la mia v a r i a b i l e i n t e r v a l con l ’ i n t e r v a l l o del beacon memcpy (& interval , (( beacMsg *) data ) - > time , 4); uint8_t d [ sizeof ( beacMsg )]; // Creo un vettore di dati t e m p o r a n e o (( beacMsg *) d ) - > type = BEACON ; // Setto il tipo di m e s s a g g i o // Imposto chi ha inviato il beacon con il mio i n d i r i z z o memcpy ((( beacMsg *) d ) - > my , my , 2); (( beacMsg *) d ) - > n_hop =(( beacMsg *) data ) - > n_hop +1; // I n c r e m e n t o il numero di hop // Imposto il numero di figli con la mia v a r i a b i l e (( beacMsg *) d ) - > n_children = numChild ; // Copio la durata dell ’ i n t e r v a l l o inviata dal gateway memcpy ((( beacMsg *) d ) - > time , & interval , 4); // Inoltro il beacon in b r o a d c a s t xbee . send (( const char *) d , sizeof ( beacMsg )); return 1; } return 0; } void WakeUpOnTime (){ u n s i g n e d long sleepTime =0; while (( sleepTime * interval ) < ( millis () - myParent . timestamp )){ sleepTime ++; } sleepTime = sleepTime * interval - INTERVAL SAFETY - DRIFT + myParent . timestamp ; // s l e e p T i m e c o n t i e n e l ’ istante in cui i n i z i e r a ’ il p r o s s i m o i n t e r v a l l o di a t t i v i t a ’ while ( millis () < sleepTime ){ // tieni spenta la radio delay (400); } // Accendi la radio while ( millis () - sleepTime < INT ERVALSAF ETY ){ delay (10); } mainTime = millis (); } u n s i g n e d char Recei veMessag e (){ xbee . poll (); /* Se sono a r r i v a t i dati sulla seriale li salva in un p a c c h e t t o e imposta lo stato xbee . a v a i l a b l e a 1 */ if ( xbee . available ()){ // Vero solo nel caso in cui siano a r r i v a t i p a c c h e t t i xbee . get XBeeRead ing ( f ); // Creo il p a c c h e t t o secondo lo s t a n d a r d API return f . g etMessag eData ( data ); // C o n t r o l l o il tipo di m e s s a g g i o r i c e v u t o } } int FindMin ( u n s i g n e d short int lastElemIndex , p o t e n t i a l P a r e n t T a b l e po te nt i al Pa re n t []){ int minIndex = lastElemIndex ; int n =0; while (n < lastElemIndex ){ // Scelgo il padre con meno hop dal gw a meno che questo non abbia gia ’ troppi figli if (( p ot en t ia lP ar e nt [ n ]. n_hop_rcv < p ot en t ia lP ar e nt [ n ]. n_hop_rcv ) && (( p ot en t ia lP ar e nt [ n ]. n_child_rcv - po te nt i al Pa re n t [ minIndex ]. n_child_rcv ) < CH I LD _T RE E SH OL D )){ minIndex = n ; /* Scelgo il padre con meno hop dal gw a meno che questo non abbia gia ’ troppi figli */ } else if (( p ot en t ia lP ar e nt [ n ]. n_hop_rcv == p o te nt ia l Pa re nt [ n ]. n_hop_rcv ) && ( po te n ti al Pa re n t [ n ]. n_child_rcv < p ot en t ia lP ar en t [ minIndex ]. n_child_rcv )){ minIndex = n ; } n ++; } memcpy (& myParent , & po t en ti al Pa r ent [ minIndex ] , sizeof ( myParent )); return minIndex ; } void SendMyData (){ short int val0 = analogRead ( sens0 ); // luce short int val1 = analogRead ( sens1 ); // umidita short int val2 = analogRead ( sens2 ); // temp memset ( data , 0 , sizeof ( data )); data [0] = SEND_DATA ; memcpy ((( sendMsg *) data ) - > my , my , 2); (( sendMsg *) data ) - > seqNumber = seqNumber ; memcpy ((( sendMsg *) data ) - > light , & val0 , 2); memcpy ((( sendMsg *) data ) - > humidity , & val1 , 2); memcpy ((( sendMsg *) data ) - > temp , & val2 , 2); // Invio i dati r i l e v a t i dai sensori a mio padre xbee . send (( const char *) data , sizeof ( sendMsg ) , ( const uint8_t *) myParent . my ); if ( seqNumber > 0 xfe ) // Per evitare o v e r f l o w seqNumber =0; seqNumber +=0 x01 ; } int TurnR adioStat e ( int state ){ if ( state ){ digitalWrite ( LED , HIGH ); // Codice per a c c e n d e r e la radio } else { digitalWrite ( LED , LOW ); // Codice per s p e g n e r e la radio } } void ResetMillis ( void ){ cli (); // D i s a b i l i t a gli i n t e r r u p t timer0_millis = 0; // V a r i a b i l e per r e s e t t a r e il millis () sei (); } Bibliografia [1] Airborne Warning and Control System (AWACS). http://it.wikipedia. org/wiki/Airborne_Warning_and_Control_System. [2] Alert system. http://alert.dot.pima.gov. [3] Arduino. http://www.arduino.cc. [4] Bluetooth Special Interest Group Site (includes specifications). https://www. bluetooth.org. [5] Ism band. http://en.wikipedia.org/wiki/ISM_band. [6] Koala mini pc official site. http://www.koala.it/. [7] MaxStream XBee™/XBee PRO™ OEM RF Modules. [8] Microsoft sensor map site. sensewebv3/sensormap/. http://atom.research.microsoft.com/ [9] Sensorscope official site. http://sensorscope.epfl.ch/index.php/Main_ Page. [10] Wireless sensor network applications. Wireless_sensor_network. http://en.wikipedia.org/wiki/ [11] Worldwide interoperability for microwave access. http://it.wikipedia.org/ wiki/WiMAX. [12] Xbeereader library project xbee-api-on-arduino/. site. http://code.google.com/p/ [13] G. Barrenextea, F. Ingelrest, G. Scheafer, M. Vetterli, O. Couach, and M. Parlange. SensorScope: Out-of-the-Box Environmental Monitoring. Information Processing in Sensor Networks, 2008. [14] Elena Guara and Robert Newman. Smart MEMS and Sensor Systems. Imperial College Press. [15] S. Sitharama Iyengar and Richard R. Brooks. Distributed Sensor Network. CHAPMAN & HALL/CRC. [16] Jiann-Ching Guey and Kambiz C. Zangi. Hybrid Contention-Based and Schedule-Based Access to a Communication Link. 63 64 BIBLIOGRAFIA [17] Y. Li and T. Newe. Wireless Sensor Networks– Selection Of Routing Protocol For Applications. [18] N. P. Mahalik. Agricultural Monitoring using Wireless Sensor Network and Mobile Internet Application. Ed. Germany: Springer-Verlag, 2006. [19] Jan Peirs, Dominiek Reynaerts, and Filip Verplaetsen. A Microturbine for electric power generation. page 8, 2005. [20] Seong-eun Yoo and Jae-eon Kim and Taehong Kim and Sungjin Ahn and Jongwoo Sung and Daeyoung Kim. A2S: Automated Agriculture System based on WSN. ISCE2007, 2007. [21] Filippo De Stefani. Sistema di monitoraggio ambientale tramite WSN. 2008. [22] Rodger E. Ziemer and Roger L. Peterson. Digital communications and spread spectrum systems. Macmillan, 1985.