IoT_watering project - supervisor

Dependencies:   mbed-rtos mbed ssWi

Files at this revision

API Documentation at this revision

Comitter:
mariob
Date:
Wed Jan 18 21:01:38 2017 +0000
Child:
1:dcfe7e79a45c
Commit message:
alpha release

Changed in this revision

config.hpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
ssWi.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.hpp	Wed Jan 18 21:01:38 2017 +0000
@@ -0,0 +1,55 @@
+#ifndef __SUPERVISOR_CONFIG__
+#define __SUPERVISOR_CONFIG__
+
+// TIME
+#define TIMEOUT_READ                10.0
+#define INTERVAL_SAMPLING           40.0
+#define INTERVAL_SYNC               5.0
+#define INTERVAL_1_SECOND           1.0
+#define INTERVAL_60_SECONDS         60
+
+// COMM VALUES
+#define COMM_NO_VALUE               0x0000
+#define COMM_START_SAMPLING         0xAAAA
+#define COMM_STOP_SAMPLING          0x1111
+#define COMM_START_WATERING_OFFSET  0xFF00
+#define COMM_SHUTDOWN               0x00FF
+#define COMM_EXIT                   0x2244
+#define COMM_SAMPLING_KO            0x2222
+#define COMM_SAMPLING_OUT           0x5555
+#define COMM_SAMPLING_OK            0xBBBB
+#define COMM_WATERING_KO            0x3333
+#define COMM_WATERING_OK            0xCCCC
+#define COMM_LOW_WATER_LEVEL        0x7777
+
+// PORTS
+#define PORT_COMMANDS               0x00
+#define PORT_HUMIDITY_OFFSET        0x01
+#define PORT_TEMPERATURE_OFFSET     0x02
+#define PORT_MOISTURE_OFFSET        0x03
+#define PORT_WATER_OFFSET           0x04
+#define PORT_RESPONSE_OFFSET        0x05
+
+#define MAX_NUM_NODES               10
+
+// FILES
+#define FILE_CNT                    "/local/CNT.txt"
+#define FILE_CFG                    "/local/cfg.txt"
+#define FILE_SNS                    "/local/SNS.txt"
+#define FILE_WTR                    "/local/WTR.txt"
+#define FILE_BSY                    "/local/BSY.txt"
+
+struct watering_unit_node_t {
+    int address;
+    int watering_wait;
+    int watering_seconds;
+};
+
+struct global_confg_t {
+    int count;
+    int wait_minutes;
+    int num_units;
+    watering_unit_node_t nodes[MAX_NUM_NODES];
+} global_config;
+
+#endif //__SUPERVISOR_CONFIG__
--- /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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Wed Jan 18 21:01:38 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#58563e6cba1e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Jan 18 21:01:38 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/99b5ccf27215
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ssWi.lib	Wed Jan 18 21:01:38 2017 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mariob/code/ssWi/#8ba1b278b407