Code APP3

Dependencies:   mbed EthernetInterface WebSocketClient mbed-rtos BufferedSerial

Fork of APP3_Lab by Jean-Philippe Fournier

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 
00002 #define IS_COORDINATOR 0
00003 
00004 #include "mbed.h"
00005 
00006 #include "rtos.h"
00007 // Communication avec les Zigbee
00008 #include "xbee.h"
00009 // Lecture de fichier de config
00010 #include "parser.h"
00011     
00012 #if IS_COORDINATOR
00013     // Pour la connection ethernet du coordinateur
00014     #include "EthernetInterface.h"
00015     #include "Websocket.h"
00016 #else
00017     // Les capteurs des routeurs
00018     #include "sensors.h"
00019 #endif
00020 
00021 // Loop led qui permet de verifier l'opération correcte du module
00022 DigitalOut loop_led(LED4);
00023 
00024 // Pour les fonctionnalites de synchro
00025 Ticker ticker;
00026 
00027 // A la reception d'un message de transmission non reussie, on demarre un ticker qui ferme
00028 // la DEL3 apres une seconde, pour permettre d'indiquer la presence d'erreur
00029 Ticker error_ticker;
00030 DigitalOut error_led(LED3);
00031 void error_display();
00032 
00033 // Thread du coordinateur qui permet l'envoi au serveur distant a l'aide de websocket
00034 Thread ws_send;
00035 void send_to_ws();
00036 // Structure servant de message pour la mailbox
00037 typedef struct {
00038     char buffer[64];
00039 } ws_message_t;
00040 Mail<ws_message_t, 32> messages_box;
00041 
00042 // Envoie un remote AT command vers le noeud a l'addresse fournie
00043 void set_remote_xbee_dio4(bool set, zigbee_addr_64_t addr);
00044 
00045 // Set le pan ID du reseau pour le noeud courant a l'aide de AT Command
00046 void set_pan_id(long pan_id);
00047 
00048 // Liste de noeuds decouvert a la reception de messages
00049 zigbee_addr_64_t addr_64[255];
00050 // Index actuel dans la liste de devices
00051 volatile int last_addr_64_index = 0;
00052 // Analyse un frame de data
00053 int process_frame(frame_t* frame);
00054 // Envois a tout les devices connus dans la liste d'addresse
00055 void send_del_to_all();
00056 // Prends les valeurs des capteurs et les envois au coordinateur
00057 void get_all_sensors();
00058 
00059 #if IS_COORDINATOR   
00060 void coordinator();
00061 #else
00062 void routeur();
00063 #endif
00064 
00065 int main() {
00066 
00067     xbee_init();
00068 
00069 #if IS_COORDINATOR    
00070     coordinator();
00071 #else
00072     routeur();
00073 #endif
00074 }
00075 
00076 #if IS_COORDINATOR
00077 void coordinator()
00078 {    
00079     // Lecture de la configuration du coordinateur
00080     coordinator_config_t config = read_coordinator_config();
00081     
00082     // On set le pan ID du device adequatement dans le fichier de configuration
00083     set_pan_id(config.pan_id);
00084     
00085     // Demarrage du thread qui s'occupe d'envoyer au web server
00086     ws_send.start(callback(send_to_ws));
00087     // Ticker qui envoi a tout les noeuds une commande de clignotement
00088     ticker.attach(&send_del_to_all, 1.0); 
00089     
00090     frame_t current_frame;
00091     while(1)
00092     {
00093         // Reception
00094         bool finished_packet = receive(&current_frame);
00095         // Si un packet complet est recu, on le traite
00096         if (finished_packet)
00097         {            
00098             process_frame(&current_frame);
00099         }
00100         wait_ms(10);
00101     }
00102 }
00103 #else
00104 void routeur()
00105 {    
00106     // Lecture de la configuration du routeur
00107     router_config_t config = read_router_config();
00108     
00109     // On set le pan ID du device adequatement dans le fichier de configuration
00110     set_pan_id(config.pan_id);
00111     
00112     // Init les capteurs qui seront captures par le noeud
00113     initialize_sensors();
00114 
00115     // Appel de la fonction de mesure des donnes de capteurs a tout les 
00116     // temps donnes par config.refresh_freq
00117     ticker.attach(&get_all_sensors, config.refresh_freq);
00118     
00119     frame_t current_frame;    
00120     while(1)
00121     {        
00122         // Reception
00123         bool finished_packet = receive(&current_frame);
00124         // Si un packet complet est recu, on le traite
00125         if (finished_packet)
00126         {            
00127             process_frame(&current_frame);                       
00128         }   
00129         wait_ms(10);
00130     }
00131 }
00132 #endif
00133 
00134 // Cree un pan id a l'aide du long en parametre, et envoi la commande at de configuration du PAN ID
00135 void set_pan_id(long pan_id)
00136 {
00137     char pan_id_buffer[8] = {0};
00138     for (int i = 0; i < 8; i++)
00139     {
00140         pan_id_buffer[i] = 0xFF & (pan_id >> 8 * (7 - i));
00141     }
00142     at_command_set('I', 'D', pan_id_buffer, 8);
00143 }
00144 
00145 // Analyse du frame recu, et prise de decisions
00146 int process_frame(frame_t* frame)
00147 {
00148     Serial pc(USBTX, USBRX); // tx, rx
00149     if (frame->length <= 0)
00150     {
00151         return -1;
00152     }
00153     
00154     if (frame->buffer[0] == 0x8B)
00155     {
00156         if(frame->buffer[5] != 0x00)
00157         {
00158             error_led = 1;
00159             error_ticker.attach(&error_display, 1.0);    
00160         }
00161         return 2;
00162     }
00163     else if (frame->buffer[0] == 0x90)
00164     {
00165         // Manage source address
00166         // Detect the source address and list it dynamically
00167         zigbee_addr_64_t temp_addr_64;        
00168         bool already_exist = false;
00169         // Read 64 bit address that was in message
00170         temp_addr_64.addr_0 = frame->buffer[1];        
00171         temp_addr_64.addr_1 = frame->buffer[2];        
00172         temp_addr_64.addr_2 = frame->buffer[3];        
00173         temp_addr_64.addr_3 = frame->buffer[4];        
00174         temp_addr_64.addr_4 = frame->buffer[5];        
00175         temp_addr_64.addr_5 = frame->buffer[6];        
00176         temp_addr_64.addr_6 = frame->buffer[7];        
00177         temp_addr_64.addr_7 = frame->buffer[8];       
00178         
00179         // Verify if the received address is new
00180         for(int j = 0; j < last_addr_64_index; j++)
00181         {
00182             if(addr_64_equal(temp_addr_64,addr_64[j]))
00183             {
00184                 already_exist = true;
00185             }
00186         }
00187         
00188         // If it is New and our array isn't full of devices add it to the array
00189         if(!already_exist && last_addr_64_index < 255)
00190         {
00191             last_addr_64_index++;
00192             addr_64[last_addr_64_index] = temp_addr_64;
00193         }
00194           
00195         ws_message_t* message = messages_box.alloc();
00196           
00197         //Data starts at 12
00198         for (int i = 12; i <  frame->length; i++)
00199         {
00200             message->buffer[i - 12] = frame->buffer[i];
00201             pc.putc(frame->buffer[i]);   
00202         }     
00203         message->buffer[frame->length - 12] = '\0';
00204         messages_box.put(message);
00205         return 1;   
00206     }    
00207     return 0;
00208 }
00209 
00210 #if IS_COORDINATOR
00211 // Fonction du thread d'envoi au web server par websocket
00212 void send_to_ws()
00213 {
00214     coordinator_config_t config = read_coordinator_config();
00215     
00216     // Interface Ethernet 
00217     EthernetInterface eth;
00218     eth.init(/*"192.168.3.3", "255.255.255.0", "192.168.3.2"*/); //Use DHCP
00219     eth.connect();
00220     
00221     // Creation du WebSocket
00222     Websocket ws(config.server_url);
00223     ws.connect();
00224     osEvent evt;
00225     while(1)
00226     {
00227         if (!ws.is_connected())
00228         {
00229             ws.connect();    
00230         }
00231         
00232         evt = messages_box.get();
00233         if (evt.status == osEventMail) {
00234             ws_message_t* mail = (ws_message_t*)evt.value.p;
00235             ws.send(mail->buffer);
00236             Thread::wait(500);
00237             messages_box.free(mail);
00238         }
00239         else
00240         {
00241             Thread::wait(100);    
00242         }
00243     }
00244 }
00245 #endif
00246 
00247 // Envoi a tout les noeuds la commande at remote pour changer l'etat de la DEL
00248 void send_del_to_all()
00249 {
00250     loop_led = !loop_led;
00251     static bool flip = false;
00252     flip = !flip;
00253     for (int i = 0; i < last_addr_64_index; i++)
00254     {
00255         set_remote_xbee_dio4(flip, addr_64[i]); 
00256     }
00257 }
00258 
00259 // Envoi la commande remote at pour setter la sortie de DIO4
00260 void set_remote_xbee_dio4(bool set, zigbee_addr_64_t addr)
00261 {
00262     if (set)
00263     {
00264         remote_at_command_set(AT_COMMAND_DIO4_MSB, AT_COMMAND_DIO4_LSB,
00265             AT_COMMAND_DIO_OUT_LOW, 0x02, addr);
00266     }
00267     else
00268     {
00269         remote_at_command_set(AT_COMMAND_DIO4_MSB, AT_COMMAND_DIO4_LSB,
00270             AT_COMMAND_DIO_OUT_HIGH, 0x02, addr);
00271     }
00272 }
00273 
00274 #if !IS_COORDINATOR
00275 // Effecture une mesure sur tout les capteurs connus dans le tableau de fct puis
00276 // envoi les resultats au coordinateur
00277 void get_all_sensors()
00278 {
00279     loop_led = !loop_led;
00280     char sensor_buffer[64] = {};
00281     DECLARE_ADDR64_COORD
00282     DECLARE_ADDR16_UNKNOWN_OR_BCAST
00283     for (int i = 0; i < 2; i++)
00284     {
00285         sensor_t sensor = (*p[i])();
00286         
00287         if (sensor.sensor_type == 1)
00288         {
00289             sprintf(sensor_buffer, "button::%u\n\r", sensor.sensor_result.Bouton.etat != 0 ? 1 : 0);
00290             transmit_request(sensor_buffer, 8 + 1 + 2, 0, USE_ADDR64_COORD, USE_ADDR16_UNKNOWN_OR_BCAST);  
00291         }
00292         else if (sensor.sensor_type == 2)
00293         {
00294             sprintf(sensor_buffer, "accel::%3.2f%3.2f%3.2f\n\r", sensor.sensor_result.Accelerometre.x, 
00295                                     sensor.sensor_result.Accelerometre.y, sensor.sensor_result.Accelerometre.z);
00296             transmit_request(sensor_buffer, 7 + 15 + 2, 0, USE_ADDR64_COORD, USE_ADDR16_UNKNOWN_OR_BCAST);
00297         }
00298     }     
00299 }
00300 #endif
00301 
00302 // Ferme la DEL d'erreur et detach le ticker
00303 void error_display()
00304 {
00305     error_led = 0;
00306     error_ticker.detach();
00307 }