IoT_watering project - supervisor

Dependencies:   mbed-rtos mbed ssWi

main.cpp

Committer:
mariob
Date:
2017-01-19
Revision:
1:dcfe7e79a45c
Parent:
0:cc364516d433
Child:
2:69d2d4c76f02

File content as of revision 1:dcfe7e79a45c:

#include "mbed.h"
#include "rtos.h"

#include "config.h"

#include "xbee.hpp"
#include "ssWiSocket.hpp"

int last_watering[MAX_NUM_NODES];

global_confg_t global_config;

ssWiSocket* socket_command;
ssWiSocket* socket_moisture[MAX_NUM_NODES];
ssWiSocket* socket_temperature[MAX_NUM_NODES];
ssWiSocket* socket_humidity[MAX_NUM_NODES];
ssWiSocket* socket_response[MAX_NUM_NODES];
ssWiSocket* socket_water[MAX_NUM_NODES];

LocalFileSystem local("local");

bool read_counter();
bool read_configuration();

bool read_from_port(ssWiSocket *socket, int *value);

bool read_timeout(ssWiSocket *socket, int *value);

void do_sampling();
void do_watering();

int main() {
    // supervisor configuration
    printf("6\r\n");
#ifdef DEBUG
    printf("SUPERVISOR - config\r\n");
#endif
    if (!read_configuration())
        error("Impossible to read configuration");

    // network configuration
    XBeeModule xbee(p9, p10, 102, 14);
    xbee.init(5, 10);
    socket_command = ssWiSocket::createSocket(PORT_COMMANDS);
    for (int i = 0; i < global_config.num_units; i++) {
        socket_moisture[i] = ssWiSocket::createSocket(
                     global_config.nodes[i].address * 5 + PORT_MOISTURE_OFFSET);
        socket_temperature[i] = ssWiSocket::createSocket(
                  global_config.nodes[i].address * 5 + PORT_TEMPERATURE_OFFSET);
        socket_humidity[i] = ssWiSocket::createSocket(
                     global_config.nodes[i].address * 5 + PORT_HUMIDITY_OFFSET);
        socket_response[i] = ssWiSocket::createSocket(
                     global_config.nodes[i].address * 5 + PORT_RESPONSE_OFFSET);
        socket_water[i] = ssWiSocket::createSocket(
                        global_config.nodes[i].address * 5 + PORT_WATER_OFFSET);
    }

    // initialize shared variables
    for (int i = 0; i < MAX_NUM_NODES; i++)
        last_watering[i] = 1;

    // start
#ifdef DEBUG
    printf("SUPERVISOR - start\r\n");
#endif

    while(1) {
        int minute_counters = 0;
        read_counter();
#ifdef DEBUG
        printf("SUPERVISOR - wait...\r\n");
#endif
        do {
            // wait 1 minute
            Thread::wait(INTERVAL_60_SECONDS * 1000);
            minute_counters++;
        } while (minute_counters < global_config.wait_minutes);

#ifdef DEBUG
        printf("SUPERVISOR - active\r\n");
#endif

        // mark as busy
        DigitalOut led_busy(LED4);
        led_busy = 1;
        FILE* fp_busy = fopen(FILE_BSY, "w");

        // sample and water
#ifdef DEBUG
        printf("SUPERVISOR - sampling\r\n");
#endif
        do_sampling();
#ifdef DEBUG
        printf("SUPERVISOR - watering\r\n");
#endif
        do_watering();
        
        // increment counter
        global_config.count++;
        FILE* fp = fopen(FILE_CNT, "w");
        fprintf(fp, "%d\n", global_config.count);
        fclose(fp);

        // send shutdown
#ifdef DEBUG
        printf("SUPERVISOR - shutdown\r\n");
#endif

        Timer t;
        t.start();
        while(t.read() < INTERVAL_SYNC);
        socket_command->write(COMM_SHUTDOWN);

        t.stop(); t.reset(); t.start();
        while(t.read() < INTERVAL_SYNC);

        // mark as not busy
        led_busy = 0;
        fclose(fp_busy);
    }
}

void do_sampling () {
    FILE* fp = fopen(FILE_SNS, "a");
    Timer t;

    socket_command->write(COMM_START_SAMPLING);
    t.start();
    while(t.read() < INTERVAL_SAMPLING);
    
    socket_command->write(COMM_STOP_SAMPLING);
        t.stop();
        t.reset();
        t.start();
    while(t.read() < INTERVAL_SYNC);

    for (int i = 0; i < global_config.num_units; i++) {
        int temp = 0, humi = 0, mois = 0, sampling_feedback = COMM_NO_VALUE;
        int code;
        if (!read_timeout(socket_response[i], &sampling_feedback))
            code = 1;
        else {
            switch (sampling_feedback) {
                case COMM_SAMPLING_OK:
                    code = (read_timeout(socket_temperature[i], &temp) &&
                            read_timeout(socket_humidity[i], &humi) &&
                            read_timeout(socket_moisture[i], &mois)) ? 0 : 2;
                    break;
                case COMM_SAMPLING_KO: code = 3; break;
                case COMM_SAMPLING_OUT: code = 4; break;
                default: code = 5;
            }
        }
        fprintf(fp, "%d %d %d %4.2f %4.2f %4.2f\n", global_config.count,
                                                 global_config.nodes[i].address,
                                                 code,
                                                 (double)humi/10.0,
                                                 (double)temp/10.0,
                                                 (double)mois/10.0);
    }
    fclose(fp);
}

void do_watering () {
    for (int i = 0; i < global_config.num_units; i++) {
        if (global_config.count % global_config.nodes[i].watering_wait)
            continue;
        FILE* fp = fopen(FILE_WTR, "a");

        socket_water[i]->write(global_config.nodes[i].watering_seconds);
        
        Timer t;
        t.start();
        while (t.read() < (global_config.nodes[i].watering_seconds +
                                                                INTERVAL_SYNC));

        t.stop(); t.reset(); t.start();
        while (t.read() < INTERVAL_1_SECOND);
        
        socket_command->write(COMM_START_WATERING_OFFSET + 
                                                global_config.nodes[i].address);

        t.stop(); t.reset(); t.start();
        while (t.read() < (global_config.nodes[i].watering_seconds +
                                                                INTERVAL_SYNC));
        t.stop();
        
        int watering_response = 0;
        int code = 4;
        if (read_timeout(socket_response[i], &watering_response)) {
            switch(watering_response) {
                case COMM_WATERING_KO: code = 1; break;
                case COMM_WATERING_OK: code = 0; break;
                case COMM_LOW_WATER_LEVEL: code = 2; break;
                default: code = 3;
            }
        }
        fprintf(fp, "%d %d %d %d\n", global_config.count,
                                     global_config.nodes[i].address,
                                     code,
                                     global_config.nodes[i].watering_seconds);
        fclose(fp);
    }
}

bool read_from_port(ssWiSocket *socket, int *value) {
    int prev = *value;
    *value = socket->read();
    return (*value) != prev;
}

bool read_timeout(ssWiSocket *socket, int *value) {
    Timer t;
    t.start();
    bool ret;
    int v = COMM_NO_VALUE;
    double start = t.read();
    do {
        if ((t.read() - start) > TIMEOUT_READ)
            return false;
        ret = read_from_port(socket, &v);
    } while(!ret);
    t.stop();
    *value = v;
    return true;
}

bool read_configuration() {
    int state = 0;
    int n_unit = 0;
    
    // read configuration file
    FILE *fp = fopen(FILE_CFG, "r");
    if(fp == NULL)
        return false;
    char line[250];
    
    while(fgets(line, sizeof(line), fp)) {
        if (line[0] == '#')
            continue;
        switch(state) {
            case 0: //read interval length
                sscanf(line, "%d\r", &global_config.wait_minutes);
                state = 1;
                break;
            case 1: //read number of watering units
                sscanf(line, "%d\r", &global_config.num_units);
                state = 2;
                break;
            case 2: //read number of watering units
                sscanf(line, "%d %d %d\r",
                                &global_config.nodes[n_unit].address,
                                &global_config.nodes[n_unit].watering_wait,
                                &global_config.nodes[n_unit].watering_seconds);
                n_unit++;
                if (n_unit >= global_config.num_units || n_unit >=MAX_NUM_NODES)
                    state = 3;
                break;
        }
    }
    fclose(fp);
       
    return true;
}

bool read_counter () {
    // read counter
    FILE *fp = fopen(FILE_CNT, "r");
    if(fp == NULL) {
        fp = fopen(FILE_CNT, "w");
        if(fp == NULL)
            return false;
        global_config.count = 0;
        fprintf(fp, "0\n");
    } else
        fscanf(fp, "%d\n", &global_config.count);
    fclose(fp);
    
    return true;
}