IoT_watering project - supervisor
Dependencies: mbed-rtos mbed ssWi
main.cpp@3:e49dd7bf7f1c, 2017-02-16 (annotated)
- Committer:
- mariob
- Date:
- Thu Feb 16 22:08:27 2017 +0000
- Revision:
- 3:e49dd7bf7f1c
- Parent:
- 2:69d2d4c76f02
release 1.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mariob | 0:cc364516d433 | 1 | #include "mbed.h" |
mariob | 0:cc364516d433 | 2 | #include "rtos.h" |
mariob | 0:cc364516d433 | 3 | |
mariob | 1:dcfe7e79a45c | 4 | #include "config.h" |
mariob | 0:cc364516d433 | 5 | |
mariob | 0:cc364516d433 | 6 | #include "xbee.hpp" |
mariob | 0:cc364516d433 | 7 | #include "ssWiSocket.hpp" |
mariob | 0:cc364516d433 | 8 | |
mariob | 2:69d2d4c76f02 | 9 | #ifndef DEBUG |
mariob | 2:69d2d4c76f02 | 10 | #define printf(fmt,...) |
mariob | 2:69d2d4c76f02 | 11 | #endif |
mariob | 2:69d2d4c76f02 | 12 | |
mariob | 3:e49dd7bf7f1c | 13 | // global configuration |
mariob | 1:dcfe7e79a45c | 14 | global_confg_t global_config; |
mariob | 1:dcfe7e79a45c | 15 | |
mariob | 3:e49dd7bf7f1c | 16 | // ssWi sockets |
mariob | 0:cc364516d433 | 17 | ssWiSocket* socket_command; |
mariob | 0:cc364516d433 | 18 | ssWiSocket* socket_moisture[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 19 | ssWiSocket* socket_temperature[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 20 | ssWiSocket* socket_humidity[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 21 | ssWiSocket* socket_response[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 22 | ssWiSocket* socket_water[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 23 | |
mariob | 0:cc364516d433 | 24 | LocalFileSystem local("local"); |
mariob | 0:cc364516d433 | 25 | |
mariob | 3:e49dd7bf7f1c | 26 | // read counter value from file |
mariob | 0:cc364516d433 | 27 | bool read_counter(); |
mariob | 3:e49dd7bf7f1c | 28 | // read board configuration from file |
mariob | 0:cc364516d433 | 29 | bool read_configuration(); |
mariob | 0:cc364516d433 | 30 | |
mariob | 3:e49dd7bf7f1c | 31 | // return true if a message has been received, false otherwise |
mariob | 0:cc364516d433 | 32 | bool read_from_port(ssWiSocket *socket, int *value); |
mariob | 3:e49dd7bf7f1c | 33 | // blocking read - timeout after 10 seconds |
mariob | 0:cc364516d433 | 34 | bool read_timeout(ssWiSocket *socket, int *value); |
mariob | 0:cc364516d433 | 35 | |
mariob | 0:cc364516d433 | 36 | void do_sampling(); |
mariob | 0:cc364516d433 | 37 | void do_watering(); |
mariob | 0:cc364516d433 | 38 | |
mariob | 0:cc364516d433 | 39 | int main() { |
mariob | 3:e49dd7bf7f1c | 40 | DigitalOut power_device(POWER_EN_PIN); |
mariob | 3:e49dd7bf7f1c | 41 | power_device = POWER_OFF; |
mariob | 3:e49dd7bf7f1c | 42 | |
mariob | 0:cc364516d433 | 43 | // supervisor configuration |
mariob | 0:cc364516d433 | 44 | printf("SUPERVISOR - config\r\n"); |
mariob | 2:69d2d4c76f02 | 45 | |
mariob | 2:69d2d4c76f02 | 46 | // read configuration |
mariob | 0:cc364516d433 | 47 | if (!read_configuration()) |
mariob | 0:cc364516d433 | 48 | error("Impossible to read configuration"); |
mariob | 0:cc364516d433 | 49 | |
mariob | 0:cc364516d433 | 50 | // network configuration |
mariob | 3:e49dd7bf7f1c | 51 | XBeeModule xbee(XBEE_PIN_TX, XBEE_PIN_RX, PAN_ID, CHANNEL_ID); |
mariob | 2:69d2d4c76f02 | 52 | xbee.init(XBEE_TX_PER_SECOND, XBEE_RX_PER_SECOND); |
mariob | 0:cc364516d433 | 53 | socket_command = ssWiSocket::createSocket(PORT_COMMANDS); |
mariob | 0:cc364516d433 | 54 | for (int i = 0; i < global_config.num_units; i++) { |
mariob | 0:cc364516d433 | 55 | socket_moisture[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 56 | global_config.nodes[i].address * 5 + PORT_MOISTURE_OFFSET); |
mariob | 0:cc364516d433 | 57 | socket_temperature[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 58 | global_config.nodes[i].address * 5 + PORT_TEMPERATURE_OFFSET); |
mariob | 0:cc364516d433 | 59 | socket_humidity[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 60 | global_config.nodes[i].address * 5 + PORT_HUMIDITY_OFFSET); |
mariob | 0:cc364516d433 | 61 | socket_response[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 62 | global_config.nodes[i].address * 5 + PORT_RESPONSE_OFFSET); |
mariob | 0:cc364516d433 | 63 | socket_water[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 64 | global_config.nodes[i].address * 5 + PORT_WATER_OFFSET); |
mariob | 0:cc364516d433 | 65 | } |
mariob | 0:cc364516d433 | 66 | |
mariob | 0:cc364516d433 | 67 | // start |
mariob | 0:cc364516d433 | 68 | printf("SUPERVISOR - start\r\n"); |
mariob | 1:dcfe7e79a45c | 69 | |
mariob | 0:cc364516d433 | 70 | while(1) { |
mariob | 0:cc364516d433 | 71 | int minute_counters = 0; |
mariob | 2:69d2d4c76f02 | 72 | printf("SUPERVISOR - waiting\r\n"); |
mariob | 0:cc364516d433 | 73 | do { |
mariob | 0:cc364516d433 | 74 | // wait 1 minute |
mariob | 0:cc364516d433 | 75 | Thread::wait(INTERVAL_60_SECONDS * 1000); |
mariob | 0:cc364516d433 | 76 | minute_counters++; |
mariob | 0:cc364516d433 | 77 | } while (minute_counters < global_config.wait_minutes); |
mariob | 0:cc364516d433 | 78 | |
mariob | 1:dcfe7e79a45c | 79 | printf("SUPERVISOR - active\r\n"); |
mariob | 1:dcfe7e79a45c | 80 | |
mariob | 0:cc364516d433 | 81 | // mark as busy |
mariob | 0:cc364516d433 | 82 | DigitalOut led_busy(LED4); |
mariob | 0:cc364516d433 | 83 | led_busy = 1; |
mariob | 0:cc364516d433 | 84 | FILE* fp_busy = fopen(FILE_BSY, "w"); |
mariob | 0:cc364516d433 | 85 | |
mariob | 3:e49dd7bf7f1c | 86 | // power watering units |
mariob | 3:e49dd7bf7f1c | 87 | power_device = POWER_ON; |
mariob | 3:e49dd7bf7f1c | 88 | wait(INTERVAL_POWER_START); |
mariob | 3:e49dd7bf7f1c | 89 | |
mariob | 3:e49dd7bf7f1c | 90 | read_counter(); |
mariob | 3:e49dd7bf7f1c | 91 | |
mariob | 0:cc364516d433 | 92 | // sample and water |
mariob | 0:cc364516d433 | 93 | printf("SUPERVISOR - sampling\r\n"); |
mariob | 0:cc364516d433 | 94 | do_sampling(); |
mariob | 0:cc364516d433 | 95 | printf("SUPERVISOR - watering\r\n"); |
mariob | 0:cc364516d433 | 96 | do_watering(); |
mariob | 1:dcfe7e79a45c | 97 | |
mariob | 0:cc364516d433 | 98 | // increment counter |
mariob | 0:cc364516d433 | 99 | global_config.count++; |
mariob | 0:cc364516d433 | 100 | FILE* fp = fopen(FILE_CNT, "w"); |
mariob | 0:cc364516d433 | 101 | fprintf(fp, "%d\n", global_config.count); |
mariob | 0:cc364516d433 | 102 | fclose(fp); |
mariob | 0:cc364516d433 | 103 | |
mariob | 0:cc364516d433 | 104 | // send shutdown |
mariob | 0:cc364516d433 | 105 | printf("SUPERVISOR - shutdown\r\n"); |
mariob | 1:dcfe7e79a45c | 106 | |
mariob | 2:69d2d4c76f02 | 107 | wait(INTERVAL_SYNC); |
mariob | 0:cc364516d433 | 108 | socket_command->write(COMM_SHUTDOWN); |
mariob | 3:e49dd7bf7f1c | 109 | wait(INTERVAL_SYNC * 2); |
mariob | 1:dcfe7e79a45c | 110 | |
mariob | 3:e49dd7bf7f1c | 111 | // power off devices |
mariob | 3:e49dd7bf7f1c | 112 | power_device = POWER_OFF; |
mariob | 3:e49dd7bf7f1c | 113 | |
mariob | 0:cc364516d433 | 114 | // mark as not busy |
mariob | 0:cc364516d433 | 115 | led_busy = 0; |
mariob | 0:cc364516d433 | 116 | fclose(fp_busy); |
mariob | 0:cc364516d433 | 117 | } |
mariob | 0:cc364516d433 | 118 | } |
mariob | 0:cc364516d433 | 119 | |
mariob | 0:cc364516d433 | 120 | void do_sampling () { |
mariob | 0:cc364516d433 | 121 | FILE* fp = fopen(FILE_SNS, "a"); |
mariob | 0:cc364516d433 | 122 | |
mariob | 0:cc364516d433 | 123 | socket_command->write(COMM_START_SAMPLING); |
mariob | 2:69d2d4c76f02 | 124 | wait(INTERVAL_SAMPLING); |
mariob | 0:cc364516d433 | 125 | |
mariob | 0:cc364516d433 | 126 | socket_command->write(COMM_STOP_SAMPLING); |
mariob | 2:69d2d4c76f02 | 127 | wait(INTERVAL_SYNC); |
mariob | 0:cc364516d433 | 128 | |
mariob | 0:cc364516d433 | 129 | for (int i = 0; i < global_config.num_units; i++) { |
mariob | 0:cc364516d433 | 130 | int temp = 0, humi = 0, mois = 0, sampling_feedback = COMM_NO_VALUE; |
mariob | 0:cc364516d433 | 131 | int code; |
mariob | 0:cc364516d433 | 132 | if (!read_timeout(socket_response[i], &sampling_feedback)) |
mariob | 0:cc364516d433 | 133 | code = 1; |
mariob | 0:cc364516d433 | 134 | else { |
mariob | 0:cc364516d433 | 135 | switch (sampling_feedback) { |
mariob | 0:cc364516d433 | 136 | case COMM_SAMPLING_OK: |
mariob | 0:cc364516d433 | 137 | code = (read_timeout(socket_temperature[i], &temp) && |
mariob | 0:cc364516d433 | 138 | read_timeout(socket_humidity[i], &humi) && |
mariob | 0:cc364516d433 | 139 | read_timeout(socket_moisture[i], &mois)) ? 0 : 2; |
mariob | 0:cc364516d433 | 140 | break; |
mariob | 0:cc364516d433 | 141 | case COMM_SAMPLING_KO: code = 3; break; |
mariob | 0:cc364516d433 | 142 | case COMM_SAMPLING_OUT: code = 4; break; |
mariob | 0:cc364516d433 | 143 | default: code = 5; |
mariob | 0:cc364516d433 | 144 | } |
mariob | 0:cc364516d433 | 145 | } |
mariob | 0:cc364516d433 | 146 | fprintf(fp, "%d %d %d %4.2f %4.2f %4.2f\n", global_config.count, |
mariob | 0:cc364516d433 | 147 | global_config.nodes[i].address, |
mariob | 0:cc364516d433 | 148 | code, |
mariob | 0:cc364516d433 | 149 | (double)humi/10.0, |
mariob | 0:cc364516d433 | 150 | (double)temp/10.0, |
mariob | 0:cc364516d433 | 151 | (double)mois/10.0); |
mariob | 0:cc364516d433 | 152 | } |
mariob | 0:cc364516d433 | 153 | fclose(fp); |
mariob | 0:cc364516d433 | 154 | } |
mariob | 0:cc364516d433 | 155 | |
mariob | 0:cc364516d433 | 156 | void do_watering () { |
mariob | 2:69d2d4c76f02 | 157 | FILE* fp = fopen(FILE_WTR, "a"); |
mariob | 0:cc364516d433 | 158 | for (int i = 0; i < global_config.num_units; i++) { |
mariob | 0:cc364516d433 | 159 | if (global_config.count % global_config.nodes[i].watering_wait) |
mariob | 0:cc364516d433 | 160 | continue; |
mariob | 2:69d2d4c76f02 | 161 | // write watering time in seconds |
mariob | 0:cc364516d433 | 162 | socket_water[i]->write(global_config.nodes[i].watering_seconds); |
mariob | 2:69d2d4c76f02 | 163 | wait(INTERVAL_SYNC); |
mariob | 2:69d2d4c76f02 | 164 | // send watering command |
mariob | 0:cc364516d433 | 165 | socket_command->write(COMM_START_WATERING_OFFSET + |
mariob | 0:cc364516d433 | 166 | global_config.nodes[i].address); |
mariob | 2:69d2d4c76f02 | 167 | wait(global_config.nodes[i].watering_seconds + INTERVAL_SYNC + |
mariob | 2:69d2d4c76f02 | 168 | INTERVAL_SYNC); |
mariob | 0:cc364516d433 | 169 | |
mariob | 0:cc364516d433 | 170 | int watering_response = 0; |
mariob | 0:cc364516d433 | 171 | int code = 4; |
mariob | 0:cc364516d433 | 172 | if (read_timeout(socket_response[i], &watering_response)) { |
mariob | 0:cc364516d433 | 173 | switch(watering_response) { |
mariob | 0:cc364516d433 | 174 | case COMM_WATERING_KO: code = 1; break; |
mariob | 0:cc364516d433 | 175 | case COMM_WATERING_OK: code = 0; break; |
mariob | 0:cc364516d433 | 176 | case COMM_LOW_WATER_LEVEL: code = 2; break; |
mariob | 0:cc364516d433 | 177 | default: code = 3; |
mariob | 0:cc364516d433 | 178 | } |
mariob | 0:cc364516d433 | 179 | } |
mariob | 0:cc364516d433 | 180 | fprintf(fp, "%d %d %d %d\n", global_config.count, |
mariob | 0:cc364516d433 | 181 | global_config.nodes[i].address, |
mariob | 0:cc364516d433 | 182 | code, |
mariob | 0:cc364516d433 | 183 | global_config.nodes[i].watering_seconds); |
mariob | 0:cc364516d433 | 184 | } |
mariob | 3:e49dd7bf7f1c | 185 | fclose(fp); |
mariob | 0:cc364516d433 | 186 | } |
mariob | 0:cc364516d433 | 187 | |
mariob | 0:cc364516d433 | 188 | bool read_from_port(ssWiSocket *socket, int *value) { |
mariob | 0:cc364516d433 | 189 | int prev = *value; |
mariob | 0:cc364516d433 | 190 | *value = socket->read(); |
mariob | 0:cc364516d433 | 191 | return (*value) != prev; |
mariob | 0:cc364516d433 | 192 | } |
mariob | 0:cc364516d433 | 193 | |
mariob | 0:cc364516d433 | 194 | bool read_timeout(ssWiSocket *socket, int *value) { |
mariob | 0:cc364516d433 | 195 | Timer t; |
mariob | 0:cc364516d433 | 196 | t.start(); |
mariob | 0:cc364516d433 | 197 | bool ret; |
mariob | 0:cc364516d433 | 198 | int v = COMM_NO_VALUE; |
mariob | 0:cc364516d433 | 199 | double start = t.read(); |
mariob | 0:cc364516d433 | 200 | do { |
mariob | 0:cc364516d433 | 201 | if ((t.read() - start) > TIMEOUT_READ) |
mariob | 0:cc364516d433 | 202 | return false; |
mariob | 0:cc364516d433 | 203 | ret = read_from_port(socket, &v); |
mariob | 0:cc364516d433 | 204 | } while(!ret); |
mariob | 0:cc364516d433 | 205 | t.stop(); |
mariob | 0:cc364516d433 | 206 | *value = v; |
mariob | 0:cc364516d433 | 207 | return true; |
mariob | 0:cc364516d433 | 208 | } |
mariob | 0:cc364516d433 | 209 | |
mariob | 0:cc364516d433 | 210 | bool read_configuration() { |
mariob | 0:cc364516d433 | 211 | int state = 0; |
mariob | 0:cc364516d433 | 212 | int n_unit = 0; |
mariob | 0:cc364516d433 | 213 | |
mariob | 0:cc364516d433 | 214 | FILE *fp = fopen(FILE_CFG, "r"); |
mariob | 0:cc364516d433 | 215 | if(fp == NULL) |
mariob | 0:cc364516d433 | 216 | return false; |
mariob | 0:cc364516d433 | 217 | char line[250]; |
mariob | 0:cc364516d433 | 218 | |
mariob | 0:cc364516d433 | 219 | while(fgets(line, sizeof(line), fp)) { |
mariob | 0:cc364516d433 | 220 | if (line[0] == '#') |
mariob | 0:cc364516d433 | 221 | continue; |
mariob | 0:cc364516d433 | 222 | switch(state) { |
mariob | 0:cc364516d433 | 223 | case 0: //read interval length |
mariob | 0:cc364516d433 | 224 | sscanf(line, "%d\r", &global_config.wait_minutes); |
mariob | 0:cc364516d433 | 225 | state = 1; |
mariob | 0:cc364516d433 | 226 | break; |
mariob | 0:cc364516d433 | 227 | case 1: //read number of watering units |
mariob | 0:cc364516d433 | 228 | sscanf(line, "%d\r", &global_config.num_units); |
mariob | 0:cc364516d433 | 229 | state = 2; |
mariob | 0:cc364516d433 | 230 | break; |
mariob | 0:cc364516d433 | 231 | case 2: //read number of watering units |
mariob | 0:cc364516d433 | 232 | sscanf(line, "%d %d %d\r", |
mariob | 0:cc364516d433 | 233 | &global_config.nodes[n_unit].address, |
mariob | 0:cc364516d433 | 234 | &global_config.nodes[n_unit].watering_wait, |
mariob | 0:cc364516d433 | 235 | &global_config.nodes[n_unit].watering_seconds); |
mariob | 0:cc364516d433 | 236 | n_unit++; |
mariob | 0:cc364516d433 | 237 | if (n_unit >= global_config.num_units || n_unit >=MAX_NUM_NODES) |
mariob | 0:cc364516d433 | 238 | state = 3; |
mariob | 0:cc364516d433 | 239 | break; |
mariob | 0:cc364516d433 | 240 | } |
mariob | 0:cc364516d433 | 241 | } |
mariob | 0:cc364516d433 | 242 | fclose(fp); |
mariob | 2:69d2d4c76f02 | 243 | |
mariob | 0:cc364516d433 | 244 | return true; |
mariob | 0:cc364516d433 | 245 | } |
mariob | 0:cc364516d433 | 246 | |
mariob | 0:cc364516d433 | 247 | bool read_counter () { |
mariob | 0:cc364516d433 | 248 | FILE *fp = fopen(FILE_CNT, "r"); |
mariob | 0:cc364516d433 | 249 | if(fp == NULL) { |
mariob | 0:cc364516d433 | 250 | fp = fopen(FILE_CNT, "w"); |
mariob | 0:cc364516d433 | 251 | if(fp == NULL) |
mariob | 0:cc364516d433 | 252 | return false; |
mariob | 0:cc364516d433 | 253 | global_config.count = 0; |
mariob | 0:cc364516d433 | 254 | fprintf(fp, "0\n"); |
mariob | 0:cc364516d433 | 255 | } else |
mariob | 0:cc364516d433 | 256 | fscanf(fp, "%d\n", &global_config.count); |
mariob | 0:cc364516d433 | 257 | fclose(fp); |
mariob | 0:cc364516d433 | 258 | |
mariob | 0:cc364516d433 | 259 | return true; |
mariob | 0:cc364516d433 | 260 | } |