IoT_watering project - supervisor

Dependencies:   mbed-rtos mbed ssWi

Revision:
0:cc364516d433
Child:
1:dcfe7e79a45c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jan 18 21:01:38 2017 +0000
@@ -0,0 +1,262 @@
+#include "mbed.h"
+#include "rtos.h"
+
+#include "config.hpp"
+
+#include "xbee.hpp"
+#include "ssWiSocket.hpp"
+
+int last_watering[MAX_NUM_NODES];
+
+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
+#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);
+
+        // 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
+        wait(INTERVAL_SYNC);
+        socket_command->write(COMM_SHUTDOWN);
+        wait(INTERVAL_SYNC);
+        socket_command->write(COMM_NO_VALUE);
+        wait(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.reset();
+    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();
+        wait(t.read() < INTERVAL_1_SECOND);
+        
+        socket_command->write(COMM_START_WATERING_OFFSET + 
+                                                global_config.nodes[i].address);
+        t.reset();
+        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;
+}