2. Apio Mesh - Giachelli/Apio-RSSI1 GitHub Wiki

Come programmare il tutto?

Una volta raccolto tutto il materiale, si entra nel vivo del progetto. La domanda che sorge spontanea è: come comunicano tra di loro i miei Apio General e come comunicano con Apio Dongle, coordinatore di tutta la mia rete? Fanno tutti parte di una rete Mesh di cui il coordinatore è il Dongle stesso.

Ma cosa è una rete Mesh?

Una rete mesh (detta "a maglie") è una rete di telecomunicazione cooperativa costituita da un gran numero di nodi che fungono da ricevitori, trasmettitori e ripetitori. Una rete mesh è costituita da un dispositivo coordinatore, che ha il compito di crearla, controllarla e mantenerla, insieme a uno o più nodi dislocati. Nel caso in cui un nodo dovesse riportare un qualsiasi tipo di guasto, i nodi vicino ad esso trovano altri percorsi per rimanere collegati alla rete, ignorando il nodo guasto. E’ una rete, quindi, estremamente affidabile.

La rete Mesh sul controllore ATmega256RFR2

Il controllore ATmega256RFR2, caratteristico dei Dongle e dei General, supporta la tecnologia Lightweight Mesh. Lo stack software Atmel  Lightweight Mesh è un protocollo di rete wireless a bassa potenza, di facile utilizzo. E’ sviluppato per lavorare con tutti i ricetrasmettitori dell’Atmel costruiti sull’IEEE 802.15.4.

Architettura Lightweight Mesh

  • Hardware Abstraction Layer (HAL) fornisce funzionalità di base dipendenti dall’ hardware, come l’hardware timer, sleep control ecc. ;

  • Radio Physical Layer (PHY) fornisce funzioni per l’accesso ai ricetrasmettitori. Alcune di esse sono accessibili solo dal livello network(richiesta di invio dati ecc); altre di esse possono essere utilizzate dall’applicazione (selezione del canale, generazione random dei numeri, ecc.);

  • Network Layer (NWK) è quello principale e ne discuteremo più in dettaglio;

  • System Services (SYS) fornisce funzioni di base comuni a tutti i livelli;

  • Application Services include moduli che non vengono richiesti dallo stack, ma sono comuni per molte applicazioni.

Specifiche del Network Layer

Il network header e l’application payload del Lightweight Mesh sono incapsulati all’interno del data payload dello standard IEEE 802.15.4. La figura seguente ci mostra un generale frame dello standard 802.15.4 dove troviamo il MAC header, il network header, l’application payload e il message integrity code (opzionale) (MIC) e il check sum (CRC).

Analizziamo il network header:

  • Frame control: contiene le informazioni di controllo per il frame. E’a sua volta formattato in:
  1. Ack Request: specifica se un ack è richiesto dal nodo di destinazione. Se è settato ad 1 il nodo di destinazione deve inviare un ack se è stato ricevuto ed elaborato il frame. Se è 0, non invia nulla;

  2. Security Enabled: mi indica se il payload è criptato o meno;

  3. Link Local: può essere impostato su 1 per impedire ai nodi vicini di ritrasmettere un frame (valido solo nel caso broadcast);

  4. Multicast: è impostato ad 1 se l’indirizzo di destinazione è un indirizzo di gruppo sennò a 0;

  • Sequence Number: specifica l’identificatore di sequenza per il frame. Viene incrementato di 1 per ogni frame in uscita dal nodo e non deve cambiare per i frame instradati;

  • Source address: identifica l’indirizzo di rete del nodo che origina il frame;

  • Destination address: specifica l’indirizzo di rete del nodo di destinazione. Può essere impostato su 0xffff per i frame broadcast;

  • Source endpoint: specifica l’identificatore dell’endpoint sorgente;

  • Destination endpoint: specifica l’identificatore dell’endpoint di destinazione;

  • Multicast header: contiene informazioni di controllo per i frame multicast.

Routing

Lightweight Mesh supporta due algoritmi di routing:

  • Native Routing: questo è l'algoritmo originale del Lightweight Mesh; è semplice, compatto e non utilizza ulteriori comandi per eseguire la route discovery;

  • AODV Routing: questo è un algoritmo più standard; utilizza ulteriori comandi per eseguire la route discovery e il processo di route discovery potrebbe richiedere un tempo più lungo.

Entrambi gli algoritmi utilizzano la Routing Table per le loro operazioni.

Routing Table

  • Fixed: indica un elemento fisso che non può essere rimosso anche se il nodo di destinazione non è più raggiungibile;

  • Multicast: indica una elemento di multicast;

  • Reserved: riservato e deve essere impostato su 0;

  • Score: indica la salute dell'elemento. Se il valore di questo campo raggiunge 0, l’ elemento viene rimosso dalla tabella di routing;

  • DstAddr: indirizzo di rete di destinazione o un ID di gruppo come indicato dal campo multicast;

  • NextHopAddr: indirizzo di rete del nodo successivo sull'itinerario verso il nodo di destinazione;

  • Rank: indica quanto spesso un elemento è stato utilizzato;

  • Lqi: indica la qualita del routing;

Native Routing

L’algoritmo di routing utilizzato da Apio è il Native Routing. Con l'algoritmo Native Routing non esiste una speciale procedura di route discovery; la Routing Table si forma nel momento in cui invii o ricevi un messaggio da un nodo.

Esempio di utilizzo

I nodi marcati con “1”, “2” e “3” sono nodi di routing. Facciamo le seguenti assunzioni:

  • il nodo 1 vuole inviare dati al nodo 3;
  • le Routing Table di ogni nodo sono vuote;
  • non c’è un percorso diretto tra 1 e 3;

Configurazione iniziale di rete

Primo step di trasferimento dati che richede una Route Discovery (

  1. Il nodo 1 invia un frame con il Network Destination Address settato a 3, e il MAC Destination Address settato a 0xffff.
  2. Il nodo 2 riceve questo frame e aggiunge la voce per il nodo 1 alla sua Routing Table.

Secondo step di trasferimento dati che richede una Route Discovery (

  1. Il nodo 2 trasmette in broadcast il frame (poiché il Mac Destination Address è settato a 0xffff);
  2. Il nodo 3 riceve questo frame e aggiunge la voce per il nodo 2 sulla sua Routing Table;
  3. Il nodo 3 aggiunge una voce per il nodo 1 sulla sua Routing Table (dal Network Source Address);

Terzo step di trasferimento dati che richiede una Route Discovery (

  1. Il nodo 3 tratta il frame e invia un Ack, anche se non è stato richiesto. Questo viene fatto per stabilire un percorso inverso. Il nodo 3 adesso conosce il percorso verso il nodo 1, quindi viene inviato un frame unicast

Step finale di trasferimento dati che richiede una Route Discovery (

  1. il nodo 2 riceve il frame e aggiunge il percorso al nodo 3 sulla sua Routing Table;
  2. il nodo 2 ha una voce con il percorso del nodo 1, così instrada il frame ricevuto( dal nodo 3) verso la sua destinazione finale (nodo 1);
  3. il nodo 1 riceve il frame e aggiunge il percorso al nodo 3 sulla sua Routing Table;

Configurazione finale (

Così il percorso tra nodo 1 e nodo 3 è stato stabilito e può essere utilizzato per tutti gli altri frame che come questo richiedono questa comunicazione.

Nota bene: durante il route discovery, tutti i nodi lungo il percorso imparano come instradare i dati verso il nodo di destinazione. Questi “instradamenti” verrano utilizzati per altri scopi di routing senza necessita di altre route discovery.

In conclusione, questo algoritmo esegue ottimizzazioni locali per stabilire e gestire percorsi con la miglior qualità di collegamento, ma questo non garantisce i percorsi più brevi.

Trasmissione, Ricezione ed Ack

Ogni frame ricevuto viene sottoposto ad uno screening di eliminazione duplicati che elimina quei frame che risultano essere duplicati. Questo screening viene eseguito utilizzando la Tabella di Rifiuto Duplicato - una tabella che contiene per ciascun nodo il Network Sequence Number dell'ultimo frame ricevuto.

Tipologie di messaggi

  • unicast: è caratterizzato dall’ invio ad un solo determinato host. Si verifica quando il campo Multicast è settato ad 0 e il destination address non è settato a 0xffff;

  • broadcast: è caratterizzato dall’ invio a tutti gli host di una rete. Si verifica quando il campo Multicast è settato a 0 e il destination address è settato a 0xffff;

  • multicast: è caratterizzato dall’ invio ad un gruppo di destinatari. Si verifica quando il campo Multicast è settato ad 1 e il Destination Address è settato all’indirizzo del gruppo di destinatari.

  • broadcast PAN ID: un frame inviato al PAN ID broadcast (0xffff) viene ricevuto dai nodi con l’indirizzo di destinazione richiesto in tutti i PAN immediatamente accessibili. Questi frame non possono essere instradati o riconosciuti;

Lista di parametri da settare

  • Network Address: il network address del nodo è settato tramite la funzione NWK_SetAddr(). Il parametro addr non può essere 0xffff poiché è un indirizzo riservato per i frame broadcast. Ex: NWK_SetAddr(0x0001);

  • Network Identifier: l’identificatore di network (PAN ID) del nodo è settato tramite la funzione NWK_SetPanId(). Non può assumere il valore 0xffff poiché è riservato. Ex: NWK_SetPanId(0x1234);

  • Frequency Channel: il canale di frequenza del nodo è settato tramite la funzione PHY_SetChannel(). Il range di parametri valido per segnali radio di banda 2.4GHz va da 11-26 (0x0b – 0x1a). Ex: PHY_SetChanell(0x0f);

  • Receiver State: lo stato di ricezione del nodo viene settato tramite la funzione PHY_SetRxState(). Ex: PHY_SetRxState(true);

  • Security Key: la security key di un nodo viene settata tramite la funzione NWK_SetSecurityKey(). La lunghezza è di 16 bytes. Ex: NWK_SetSecurityKey((uint8_t *)"Security12345678");

  • Application Endpoint: per ricevere dati, l’applicazione deve registrare una callback di indicazione dei dati associata all’identificatore dell’ endpoint. Per registrare un endpoint è utilizzata la funzione NWK_OpenEndpoint(). Il valore va da 1 a 16. Possono essere implementati più di un endpoint allo stesso tempo. Ex: static bool appDataInd(NWK_DataInd_t *ind) { // process the frame return true; }

NWK_OpenEndpoint(1, appDataInd);

L’invio del dato

Per l’invio del dato, l’applicazione prima ha bisogno di creare una richiesta di trasmissione dati di tipo NWK_DataReq_t che specifica il data payload, la dimensione del data payload , setta vari parametri di trasmissione e definisce la funzione di callback che deve essere eseguita per informare l’applicazione riguardo la trasmissione del dato. La funzione NWK_DataReq() è utilizzata per inviare i dati. Si noti che NWK_DataReq () deve essere chiamata una sola volta per la stessa struttura NWK_DataReq_t fino a quando non viene richiamata la callback di conferma. I campi di NWK_DataReq_t, accessibili all’utente, sono:

  1. data: puntatore al payload data;
  2. dstAddr: network address per il nodo di destinazione;
  3. dstEndpoint: numero di endpoint del dispositivo di destinazione;
  4. option: opzioni di richiesta dati;
  5. size: dimensione del payload data;
  6. srcAddr: network address per il nodo di inizio;
  7. srcEndpoint: numero di endpoint del dispositivo di inizio;
  8. confirm: puntatore alla callback di conferma;
  9. status: si divide in:
  • NWK_SUCCESS_STATUS: operazione completata con successo;
  • NWK_ERROR_STATUS : errore;
  • NWK_OUT_OF_MEMORY_STATUS: allocazione nel buffer fallita;
  • NWK_NO_ACK_STATUS: l’ack a livello network non è stato ricevuto;
  • NWK_NO_ROUTE_STATUS: la rotta per l’indirizzo di destinazione non è stata trovata;
  • NWK_PHY_CHANNEL_ACCESS_FAILURE_STATUS: la trasmissione radio non è riuscita ad accedere al canale
  • NWK_PHY_NO_ACK_STATUS: l’ack a livello fisico non è stato ricevuto.

Ex:

  1. static uint8_t message;
  2. static NWK_DataReq_t nwkDataReq;
  3. static void appDataConf(NWK_DataReq_t *req)
  4. {
  5. if (NWK_SUCCESS_STATUS == req->status)
  6. // frame was sent successfully
  7. else // some error happened
  8. }
  9. static void sendFrame(void)
  10. {
  11. nwkDataReq.dstAddr = 0;
  12. nwkDataReq.dstEndpoint = 1;
  13. nwkDataReq.srcEndpoint = 5;
  14. nwkDataReq.options = NWK_OPT_ACK_REQUEST | NWK_OPT_ENABLE_SECURITY; nwkDataReq.data = &message;
  15. nwkDataReq.size = sizeof(message);
  16. nwkDataReq.confirm = appDataConf;
  17. NWK_DataReq(&nwkDataReq);
  18. }

Ricezione del dato

Se l’applicazione ha registrato la callback di indicazione dei dati (come dicevamo per l’Application Endpoint) allora è capace di ricevere dati. Quando un frame è ricevuto e processato dallo stack, viene indicato all’applicazione tramite una callback di registrazione. Questa funzione ha il seguente prototipo: “bool appDataInd(NWK_DataInd_t *ind)”. La struttura NWK_DataInd_t contiene i seguenti campi:

  • srcAddr: network address per il nodo di inizio;
  • dstEndpoint: numero di endpoint del dispositivo di destinazione;
  • srcEndpoint: numero di endpoint del dispositivo di inizio;
  • option: opzioni di richiesta dati;
  • data: puntatore al payload data;
  • size: dimensione del payload data;
  • rssi: Received Signal Strenght Indication del frame ricevuto;

L'applicazione può impostare 1 byte di dati da inviare nel ack frame. Questo viene fatto usando la funzione NWK_SetAckControl (). Questo byte può essere utilizzato per inviare informazioni aggiuntive al dispositivo che invia (oltre all’ack). (Metterci l’esempio concreto dell rssi)

Gestione della Routing Table Le funzioni che caratterizzano la Routing Table sono le seguenti:

  • NWK_RouteFindEntry() – cerca una voce nella Routing Table;
  • NWK_RouteNewEntry() – alloca una nuova voce nella Routing Table;
  • NWK_RouteFreeEntry() – libera le voci precedentemente allocate;
  • NWK_RouteNextHop() – ottiene l’indirizzo di rete del nextHop node nel percorso verso la destinazione richiesta;
  • NWK_RouteTable() – ottiene un puntatore all’ intera Routing Table;