Code APP3

Dependencies:   mbed EthernetInterface WebSocketClient mbed-rtos BufferedSerial

Fork of APP3_Lab by Jean-Philippe Fournier

main.cpp

Committer:
JayMcGee
Date:
2017-10-02
Revision:
29:56b6c15904e6
Parent:
27:3baf4701a047

File content as of revision 29:56b6c15904e6:


#define IS_COORDINATOR 0

#include "mbed.h"

#include "rtos.h"
// Communication avec les Zigbee
#include "xbee.h"
// Lecture de fichier de config
#include "parser.h"
    
#if IS_COORDINATOR
    // Pour la connection ethernet du coordinateur
    #include "EthernetInterface.h"
    #include "Websocket.h"
#else
    // Les capteurs des routeurs
    #include "sensors.h"
#endif

// Loop led qui permet de verifier l'opération correcte du module
DigitalOut loop_led(LED4);

// Pour les fonctionnalites de synchro
Ticker ticker;

// A la reception d'un message de transmission non reussie, on demarre un ticker qui ferme
// la DEL3 apres une seconde, pour permettre d'indiquer la presence d'erreur
Ticker error_ticker;
DigitalOut error_led(LED3);
void error_display();

// Thread du coordinateur qui permet l'envoi au serveur distant a l'aide de websocket
Thread ws_send;
void send_to_ws();
// Structure servant de message pour la mailbox
typedef struct {
    char buffer[64];
} ws_message_t;
Mail<ws_message_t, 32> messages_box;

// Envoie un remote AT command vers le noeud a l'addresse fournie
void set_remote_xbee_dio4(bool set, zigbee_addr_64_t addr);

// Set le pan ID du reseau pour le noeud courant a l'aide de AT Command
void set_pan_id(long pan_id);

// Liste de noeuds decouvert a la reception de messages
zigbee_addr_64_t addr_64[255];
// Index actuel dans la liste de devices
volatile int last_addr_64_index = 0;
// Analyse un frame de data
int process_frame(frame_t* frame);
// Envois a tout les devices connus dans la liste d'addresse
void send_del_to_all();
// Prends les valeurs des capteurs et les envois au coordinateur
void get_all_sensors();

#if IS_COORDINATOR   
void coordinator();
#else
void routeur();
#endif

int main() {

    xbee_init();

#if IS_COORDINATOR    
    coordinator();
#else
    routeur();
#endif
}

#if IS_COORDINATOR
void coordinator()
{    
    // Lecture de la configuration du coordinateur
    coordinator_config_t config = read_coordinator_config();
    
    // On set le pan ID du device adequatement dans le fichier de configuration
    set_pan_id(config.pan_id);
    
    // Demarrage du thread qui s'occupe d'envoyer au web server
    ws_send.start(callback(send_to_ws));
    // Ticker qui envoi a tout les noeuds une commande de clignotement
    ticker.attach(&send_del_to_all, 1.0); 
    
    frame_t current_frame;
    while(1)
    {
        // Reception
        bool finished_packet = receive(&current_frame);
        // Si un packet complet est recu, on le traite
        if (finished_packet)
        {            
            process_frame(&current_frame);
        }
        wait_ms(10);
    }
}
#else
void routeur()
{    
    // Lecture de la configuration du routeur
    router_config_t config = read_router_config();
    
    // On set le pan ID du device adequatement dans le fichier de configuration
    set_pan_id(config.pan_id);
    
    // Init les capteurs qui seront captures par le noeud
    initialize_sensors();

    // Appel de la fonction de mesure des donnes de capteurs a tout les 
    // temps donnes par config.refresh_freq
    ticker.attach(&get_all_sensors, config.refresh_freq);
    
    frame_t current_frame;    
    while(1)
    {        
        // Reception
        bool finished_packet = receive(&current_frame);
        // Si un packet complet est recu, on le traite
        if (finished_packet)
        {            
            process_frame(&current_frame);                       
        }   
        wait_ms(10);
    }
}
#endif

// Cree un pan id a l'aide du long en parametre, et envoi la commande at de configuration du PAN ID
void set_pan_id(long pan_id)
{
    char pan_id_buffer[8] = {0};
    for (int i = 0; i < 8; i++)
    {
        pan_id_buffer[i] = 0xFF & (pan_id >> 8 * (7 - i));
    }
    at_command_set('I', 'D', pan_id_buffer, 8);
}

// Analyse du frame recu, et prise de decisions
int process_frame(frame_t* frame)
{
    Serial pc(USBTX, USBRX); // tx, rx
    if (frame->length <= 0)
    {
        return -1;
    }
    
    if (frame->buffer[0] == 0x8B)
    {
        if(frame->buffer[5] != 0x00)
        {
            error_led = 1;
            error_ticker.attach(&error_display, 1.0);    
        }
        return 2;
    }
    else if (frame->buffer[0] == 0x90)
    {
        // Manage source address
        // Detect the source address and list it dynamically
        zigbee_addr_64_t temp_addr_64;        
        bool already_exist = false;
        // Read 64 bit address that was in message
        temp_addr_64.addr_0 = frame->buffer[1];        
        temp_addr_64.addr_1 = frame->buffer[2];        
        temp_addr_64.addr_2 = frame->buffer[3];        
        temp_addr_64.addr_3 = frame->buffer[4];        
        temp_addr_64.addr_4 = frame->buffer[5];        
        temp_addr_64.addr_5 = frame->buffer[6];        
        temp_addr_64.addr_6 = frame->buffer[7];        
        temp_addr_64.addr_7 = frame->buffer[8];       
        
        // Verify if the received address is new
        for(int j = 0; j < last_addr_64_index; j++)
        {
            if(addr_64_equal(temp_addr_64,addr_64[j]))
            {
                already_exist = true;
            }
        }
        
        // If it is New and our array isn't full of devices add it to the array
        if(!already_exist && last_addr_64_index < 255)
        {
            last_addr_64_index++;
            addr_64[last_addr_64_index] = temp_addr_64;
        }
          
        ws_message_t* message = messages_box.alloc();
          
        //Data starts at 12
        for (int i = 12; i <  frame->length; i++)
        {
            message->buffer[i - 12] = frame->buffer[i];
            pc.putc(frame->buffer[i]);   
        }     
        message->buffer[frame->length - 12] = '\0';
        messages_box.put(message);
        return 1;   
    }    
    return 0;
}

#if IS_COORDINATOR
// Fonction du thread d'envoi au web server par websocket
void send_to_ws()
{
    coordinator_config_t config = read_coordinator_config();
    
    // Interface Ethernet 
    EthernetInterface eth;
    eth.init(/*"192.168.3.3", "255.255.255.0", "192.168.3.2"*/); //Use DHCP
    eth.connect();
    
    // Creation du WebSocket
    Websocket ws(config.server_url);
    ws.connect();
    osEvent evt;
    while(1)
    {
        if (!ws.is_connected())
        {
            ws.connect();    
        }
        
        evt = messages_box.get();
        if (evt.status == osEventMail) {
            ws_message_t* mail = (ws_message_t*)evt.value.p;
            ws.send(mail->buffer);
            Thread::wait(500);
            messages_box.free(mail);
        }
        else
        {
            Thread::wait(100);    
        }
    }
}
#endif

// Envoi a tout les noeuds la commande at remote pour changer l'etat de la DEL
void send_del_to_all()
{
    loop_led = !loop_led;
    static bool flip = false;
    flip = !flip;
    for (int i = 0; i < last_addr_64_index; i++)
    {
        set_remote_xbee_dio4(flip, addr_64[i]); 
    }
}

// Envoi la commande remote at pour setter la sortie de DIO4
void set_remote_xbee_dio4(bool set, zigbee_addr_64_t addr)
{
    if (set)
    {
        remote_at_command_set(AT_COMMAND_DIO4_MSB, AT_COMMAND_DIO4_LSB,
            AT_COMMAND_DIO_OUT_LOW, 0x02, addr);
    }
    else
    {
        remote_at_command_set(AT_COMMAND_DIO4_MSB, AT_COMMAND_DIO4_LSB,
            AT_COMMAND_DIO_OUT_HIGH, 0x02, addr);
    }
}

#if !IS_COORDINATOR
// Effecture une mesure sur tout les capteurs connus dans le tableau de fct puis
// envoi les resultats au coordinateur
void get_all_sensors()
{
    loop_led = !loop_led;
    char sensor_buffer[64] = {};
    DECLARE_ADDR64_COORD
    DECLARE_ADDR16_UNKNOWN_OR_BCAST
    for (int i = 0; i < 2; i++)
    {
        sensor_t sensor = (*p[i])();
        
        if (sensor.sensor_type == 1)
        {
            sprintf(sensor_buffer, "button::%u\n\r", sensor.sensor_result.Bouton.etat != 0 ? 1 : 0);
            transmit_request(sensor_buffer, 8 + 1 + 2, 0, USE_ADDR64_COORD, USE_ADDR16_UNKNOWN_OR_BCAST);  
        }
        else if (sensor.sensor_type == 2)
        {
            sprintf(sensor_buffer, "accel::%3.2f%3.2f%3.2f\n\r", sensor.sensor_result.Accelerometre.x, 
                                    sensor.sensor_result.Accelerometre.y, sensor.sensor_result.Accelerometre.z);
            transmit_request(sensor_buffer, 7 + 15 + 2, 0, USE_ADDR64_COORD, USE_ADDR16_UNKNOWN_OR_BCAST);
        }
    }     
}
#endif

// Ferme la DEL d'erreur et detach le ticker
void error_display()
{
    error_led = 0;
    error_ticker.detach();
}