IoT_watering project - supervisor
Dependencies: mbed-rtos mbed ssWi
main.cpp@1:dcfe7e79a45c, 2017-01-19 (annotated)
- Committer:
- mariob
- Date:
- Thu Jan 19 23:31:18 2017 +0000
- Revision:
- 1:dcfe7e79a45c
- Parent:
- 0:cc364516d433
- Child:
- 2:69d2d4c76f02
fix
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 | 0:cc364516d433 | 9 | int last_watering[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 10 | |
mariob | 1:dcfe7e79a45c | 11 | global_confg_t global_config; |
mariob | 1:dcfe7e79a45c | 12 | |
mariob | 0:cc364516d433 | 13 | ssWiSocket* socket_command; |
mariob | 0:cc364516d433 | 14 | ssWiSocket* socket_moisture[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 15 | ssWiSocket* socket_temperature[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 16 | ssWiSocket* socket_humidity[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 17 | ssWiSocket* socket_response[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 18 | ssWiSocket* socket_water[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 19 | |
mariob | 0:cc364516d433 | 20 | LocalFileSystem local("local"); |
mariob | 0:cc364516d433 | 21 | |
mariob | 0:cc364516d433 | 22 | bool read_counter(); |
mariob | 0:cc364516d433 | 23 | bool read_configuration(); |
mariob | 0:cc364516d433 | 24 | |
mariob | 0:cc364516d433 | 25 | bool read_from_port(ssWiSocket *socket, int *value); |
mariob | 0:cc364516d433 | 26 | |
mariob | 0:cc364516d433 | 27 | bool read_timeout(ssWiSocket *socket, int *value); |
mariob | 0:cc364516d433 | 28 | |
mariob | 0:cc364516d433 | 29 | void do_sampling(); |
mariob | 0:cc364516d433 | 30 | void do_watering(); |
mariob | 0:cc364516d433 | 31 | |
mariob | 0:cc364516d433 | 32 | int main() { |
mariob | 0:cc364516d433 | 33 | // supervisor configuration |
mariob | 1:dcfe7e79a45c | 34 | printf("6\r\n"); |
mariob | 0:cc364516d433 | 35 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 36 | printf("SUPERVISOR - config\r\n"); |
mariob | 0:cc364516d433 | 37 | #endif |
mariob | 0:cc364516d433 | 38 | if (!read_configuration()) |
mariob | 0:cc364516d433 | 39 | error("Impossible to read configuration"); |
mariob | 0:cc364516d433 | 40 | |
mariob | 0:cc364516d433 | 41 | // network configuration |
mariob | 0:cc364516d433 | 42 | XBeeModule xbee(p9, p10, 102, 14); |
mariob | 0:cc364516d433 | 43 | xbee.init(5, 10); |
mariob | 0:cc364516d433 | 44 | socket_command = ssWiSocket::createSocket(PORT_COMMANDS); |
mariob | 0:cc364516d433 | 45 | for (int i = 0; i < global_config.num_units; i++) { |
mariob | 0:cc364516d433 | 46 | socket_moisture[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 47 | global_config.nodes[i].address * 5 + PORT_MOISTURE_OFFSET); |
mariob | 0:cc364516d433 | 48 | socket_temperature[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 49 | global_config.nodes[i].address * 5 + PORT_TEMPERATURE_OFFSET); |
mariob | 0:cc364516d433 | 50 | socket_humidity[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 51 | global_config.nodes[i].address * 5 + PORT_HUMIDITY_OFFSET); |
mariob | 0:cc364516d433 | 52 | socket_response[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 53 | global_config.nodes[i].address * 5 + PORT_RESPONSE_OFFSET); |
mariob | 0:cc364516d433 | 54 | socket_water[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 55 | global_config.nodes[i].address * 5 + PORT_WATER_OFFSET); |
mariob | 0:cc364516d433 | 56 | } |
mariob | 0:cc364516d433 | 57 | |
mariob | 0:cc364516d433 | 58 | // initialize shared variables |
mariob | 0:cc364516d433 | 59 | for (int i = 0; i < MAX_NUM_NODES; i++) |
mariob | 0:cc364516d433 | 60 | last_watering[i] = 1; |
mariob | 0:cc364516d433 | 61 | |
mariob | 0:cc364516d433 | 62 | // start |
mariob | 0:cc364516d433 | 63 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 64 | printf("SUPERVISOR - start\r\n"); |
mariob | 0:cc364516d433 | 65 | #endif |
mariob | 1:dcfe7e79a45c | 66 | |
mariob | 0:cc364516d433 | 67 | while(1) { |
mariob | 0:cc364516d433 | 68 | int minute_counters = 0; |
mariob | 0:cc364516d433 | 69 | read_counter(); |
mariob | 0:cc364516d433 | 70 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 71 | printf("SUPERVISOR - wait...\r\n"); |
mariob | 0:cc364516d433 | 72 | #endif |
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 | #ifdef DEBUG |
mariob | 1:dcfe7e79a45c | 80 | printf("SUPERVISOR - active\r\n"); |
mariob | 1:dcfe7e79a45c | 81 | #endif |
mariob | 1:dcfe7e79a45c | 82 | |
mariob | 0:cc364516d433 | 83 | // mark as busy |
mariob | 0:cc364516d433 | 84 | DigitalOut led_busy(LED4); |
mariob | 0:cc364516d433 | 85 | led_busy = 1; |
mariob | 0:cc364516d433 | 86 | FILE* fp_busy = fopen(FILE_BSY, "w"); |
mariob | 0:cc364516d433 | 87 | |
mariob | 0:cc364516d433 | 88 | // sample and water |
mariob | 0:cc364516d433 | 89 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 90 | printf("SUPERVISOR - sampling\r\n"); |
mariob | 0:cc364516d433 | 91 | #endif |
mariob | 0:cc364516d433 | 92 | do_sampling(); |
mariob | 0:cc364516d433 | 93 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 94 | printf("SUPERVISOR - watering\r\n"); |
mariob | 0:cc364516d433 | 95 | #endif |
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 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 106 | printf("SUPERVISOR - shutdown\r\n"); |
mariob | 0:cc364516d433 | 107 | #endif |
mariob | 1:dcfe7e79a45c | 108 | |
mariob | 1:dcfe7e79a45c | 109 | Timer t; |
mariob | 1:dcfe7e79a45c | 110 | t.start(); |
mariob | 1:dcfe7e79a45c | 111 | while(t.read() < INTERVAL_SYNC); |
mariob | 0:cc364516d433 | 112 | socket_command->write(COMM_SHUTDOWN); |
mariob | 1:dcfe7e79a45c | 113 | |
mariob | 1:dcfe7e79a45c | 114 | t.stop(); t.reset(); t.start(); |
mariob | 1:dcfe7e79a45c | 115 | while(t.read() < INTERVAL_SYNC); |
mariob | 1:dcfe7e79a45c | 116 | |
mariob | 0:cc364516d433 | 117 | // mark as not busy |
mariob | 0:cc364516d433 | 118 | led_busy = 0; |
mariob | 0:cc364516d433 | 119 | fclose(fp_busy); |
mariob | 0:cc364516d433 | 120 | } |
mariob | 0:cc364516d433 | 121 | } |
mariob | 0:cc364516d433 | 122 | |
mariob | 0:cc364516d433 | 123 | void do_sampling () { |
mariob | 0:cc364516d433 | 124 | FILE* fp = fopen(FILE_SNS, "a"); |
mariob | 0:cc364516d433 | 125 | Timer t; |
mariob | 0:cc364516d433 | 126 | |
mariob | 0:cc364516d433 | 127 | socket_command->write(COMM_START_SAMPLING); |
mariob | 0:cc364516d433 | 128 | t.start(); |
mariob | 0:cc364516d433 | 129 | while(t.read() < INTERVAL_SAMPLING); |
mariob | 0:cc364516d433 | 130 | |
mariob | 0:cc364516d433 | 131 | socket_command->write(COMM_STOP_SAMPLING); |
mariob | 1:dcfe7e79a45c | 132 | t.stop(); |
mariob | 1:dcfe7e79a45c | 133 | t.reset(); |
mariob | 1:dcfe7e79a45c | 134 | t.start(); |
mariob | 0:cc364516d433 | 135 | while(t.read() < INTERVAL_SYNC); |
mariob | 0:cc364516d433 | 136 | |
mariob | 0:cc364516d433 | 137 | for (int i = 0; i < global_config.num_units; i++) { |
mariob | 0:cc364516d433 | 138 | int temp = 0, humi = 0, mois = 0, sampling_feedback = COMM_NO_VALUE; |
mariob | 0:cc364516d433 | 139 | int code; |
mariob | 0:cc364516d433 | 140 | if (!read_timeout(socket_response[i], &sampling_feedback)) |
mariob | 0:cc364516d433 | 141 | code = 1; |
mariob | 0:cc364516d433 | 142 | else { |
mariob | 0:cc364516d433 | 143 | switch (sampling_feedback) { |
mariob | 0:cc364516d433 | 144 | case COMM_SAMPLING_OK: |
mariob | 0:cc364516d433 | 145 | code = (read_timeout(socket_temperature[i], &temp) && |
mariob | 0:cc364516d433 | 146 | read_timeout(socket_humidity[i], &humi) && |
mariob | 0:cc364516d433 | 147 | read_timeout(socket_moisture[i], &mois)) ? 0 : 2; |
mariob | 0:cc364516d433 | 148 | break; |
mariob | 0:cc364516d433 | 149 | case COMM_SAMPLING_KO: code = 3; break; |
mariob | 0:cc364516d433 | 150 | case COMM_SAMPLING_OUT: code = 4; break; |
mariob | 0:cc364516d433 | 151 | default: code = 5; |
mariob | 0:cc364516d433 | 152 | } |
mariob | 0:cc364516d433 | 153 | } |
mariob | 0:cc364516d433 | 154 | fprintf(fp, "%d %d %d %4.2f %4.2f %4.2f\n", global_config.count, |
mariob | 0:cc364516d433 | 155 | global_config.nodes[i].address, |
mariob | 0:cc364516d433 | 156 | code, |
mariob | 0:cc364516d433 | 157 | (double)humi/10.0, |
mariob | 0:cc364516d433 | 158 | (double)temp/10.0, |
mariob | 0:cc364516d433 | 159 | (double)mois/10.0); |
mariob | 0:cc364516d433 | 160 | } |
mariob | 0:cc364516d433 | 161 | fclose(fp); |
mariob | 0:cc364516d433 | 162 | } |
mariob | 0:cc364516d433 | 163 | |
mariob | 0:cc364516d433 | 164 | void do_watering () { |
mariob | 0:cc364516d433 | 165 | for (int i = 0; i < global_config.num_units; i++) { |
mariob | 0:cc364516d433 | 166 | if (global_config.count % global_config.nodes[i].watering_wait) |
mariob | 0:cc364516d433 | 167 | continue; |
mariob | 0:cc364516d433 | 168 | FILE* fp = fopen(FILE_WTR, "a"); |
mariob | 0:cc364516d433 | 169 | |
mariob | 0:cc364516d433 | 170 | socket_water[i]->write(global_config.nodes[i].watering_seconds); |
mariob | 0:cc364516d433 | 171 | |
mariob | 0:cc364516d433 | 172 | Timer t; |
mariob | 0:cc364516d433 | 173 | t.start(); |
mariob | 1:dcfe7e79a45c | 174 | while (t.read() < (global_config.nodes[i].watering_seconds + |
mariob | 1:dcfe7e79a45c | 175 | INTERVAL_SYNC)); |
mariob | 1:dcfe7e79a45c | 176 | |
mariob | 1:dcfe7e79a45c | 177 | t.stop(); t.reset(); t.start(); |
mariob | 1:dcfe7e79a45c | 178 | while (t.read() < INTERVAL_1_SECOND); |
mariob | 0:cc364516d433 | 179 | |
mariob | 0:cc364516d433 | 180 | socket_command->write(COMM_START_WATERING_OFFSET + |
mariob | 0:cc364516d433 | 181 | global_config.nodes[i].address); |
mariob | 1:dcfe7e79a45c | 182 | |
mariob | 1:dcfe7e79a45c | 183 | t.stop(); t.reset(); t.start(); |
mariob | 0:cc364516d433 | 184 | while (t.read() < (global_config.nodes[i].watering_seconds + |
mariob | 0:cc364516d433 | 185 | INTERVAL_SYNC)); |
mariob | 0:cc364516d433 | 186 | t.stop(); |
mariob | 0:cc364516d433 | 187 | |
mariob | 0:cc364516d433 | 188 | int watering_response = 0; |
mariob | 0:cc364516d433 | 189 | int code = 4; |
mariob | 0:cc364516d433 | 190 | if (read_timeout(socket_response[i], &watering_response)) { |
mariob | 0:cc364516d433 | 191 | switch(watering_response) { |
mariob | 0:cc364516d433 | 192 | case COMM_WATERING_KO: code = 1; break; |
mariob | 0:cc364516d433 | 193 | case COMM_WATERING_OK: code = 0; break; |
mariob | 0:cc364516d433 | 194 | case COMM_LOW_WATER_LEVEL: code = 2; break; |
mariob | 0:cc364516d433 | 195 | default: code = 3; |
mariob | 0:cc364516d433 | 196 | } |
mariob | 0:cc364516d433 | 197 | } |
mariob | 0:cc364516d433 | 198 | fprintf(fp, "%d %d %d %d\n", global_config.count, |
mariob | 0:cc364516d433 | 199 | global_config.nodes[i].address, |
mariob | 0:cc364516d433 | 200 | code, |
mariob | 0:cc364516d433 | 201 | global_config.nodes[i].watering_seconds); |
mariob | 0:cc364516d433 | 202 | fclose(fp); |
mariob | 0:cc364516d433 | 203 | } |
mariob | 0:cc364516d433 | 204 | } |
mariob | 0:cc364516d433 | 205 | |
mariob | 0:cc364516d433 | 206 | bool read_from_port(ssWiSocket *socket, int *value) { |
mariob | 0:cc364516d433 | 207 | int prev = *value; |
mariob | 0:cc364516d433 | 208 | *value = socket->read(); |
mariob | 0:cc364516d433 | 209 | return (*value) != prev; |
mariob | 0:cc364516d433 | 210 | } |
mariob | 0:cc364516d433 | 211 | |
mariob | 0:cc364516d433 | 212 | bool read_timeout(ssWiSocket *socket, int *value) { |
mariob | 0:cc364516d433 | 213 | Timer t; |
mariob | 0:cc364516d433 | 214 | t.start(); |
mariob | 0:cc364516d433 | 215 | bool ret; |
mariob | 0:cc364516d433 | 216 | int v = COMM_NO_VALUE; |
mariob | 0:cc364516d433 | 217 | double start = t.read(); |
mariob | 0:cc364516d433 | 218 | do { |
mariob | 0:cc364516d433 | 219 | if ((t.read() - start) > TIMEOUT_READ) |
mariob | 0:cc364516d433 | 220 | return false; |
mariob | 0:cc364516d433 | 221 | ret = read_from_port(socket, &v); |
mariob | 0:cc364516d433 | 222 | } while(!ret); |
mariob | 0:cc364516d433 | 223 | t.stop(); |
mariob | 0:cc364516d433 | 224 | *value = v; |
mariob | 0:cc364516d433 | 225 | return true; |
mariob | 0:cc364516d433 | 226 | } |
mariob | 0:cc364516d433 | 227 | |
mariob | 0:cc364516d433 | 228 | bool read_configuration() { |
mariob | 0:cc364516d433 | 229 | int state = 0; |
mariob | 0:cc364516d433 | 230 | int n_unit = 0; |
mariob | 0:cc364516d433 | 231 | |
mariob | 0:cc364516d433 | 232 | // read configuration file |
mariob | 0:cc364516d433 | 233 | FILE *fp = fopen(FILE_CFG, "r"); |
mariob | 0:cc364516d433 | 234 | if(fp == NULL) |
mariob | 0:cc364516d433 | 235 | return false; |
mariob | 0:cc364516d433 | 236 | char line[250]; |
mariob | 0:cc364516d433 | 237 | |
mariob | 0:cc364516d433 | 238 | while(fgets(line, sizeof(line), fp)) { |
mariob | 0:cc364516d433 | 239 | if (line[0] == '#') |
mariob | 0:cc364516d433 | 240 | continue; |
mariob | 0:cc364516d433 | 241 | switch(state) { |
mariob | 0:cc364516d433 | 242 | case 0: //read interval length |
mariob | 0:cc364516d433 | 243 | sscanf(line, "%d\r", &global_config.wait_minutes); |
mariob | 0:cc364516d433 | 244 | state = 1; |
mariob | 0:cc364516d433 | 245 | break; |
mariob | 0:cc364516d433 | 246 | case 1: //read number of watering units |
mariob | 0:cc364516d433 | 247 | sscanf(line, "%d\r", &global_config.num_units); |
mariob | 0:cc364516d433 | 248 | state = 2; |
mariob | 0:cc364516d433 | 249 | break; |
mariob | 0:cc364516d433 | 250 | case 2: //read number of watering units |
mariob | 0:cc364516d433 | 251 | sscanf(line, "%d %d %d\r", |
mariob | 0:cc364516d433 | 252 | &global_config.nodes[n_unit].address, |
mariob | 0:cc364516d433 | 253 | &global_config.nodes[n_unit].watering_wait, |
mariob | 0:cc364516d433 | 254 | &global_config.nodes[n_unit].watering_seconds); |
mariob | 0:cc364516d433 | 255 | n_unit++; |
mariob | 0:cc364516d433 | 256 | if (n_unit >= global_config.num_units || n_unit >=MAX_NUM_NODES) |
mariob | 0:cc364516d433 | 257 | state = 3; |
mariob | 0:cc364516d433 | 258 | break; |
mariob | 0:cc364516d433 | 259 | } |
mariob | 0:cc364516d433 | 260 | } |
mariob | 0:cc364516d433 | 261 | fclose(fp); |
mariob | 0:cc364516d433 | 262 | |
mariob | 0:cc364516d433 | 263 | return true; |
mariob | 0:cc364516d433 | 264 | } |
mariob | 0:cc364516d433 | 265 | |
mariob | 0:cc364516d433 | 266 | bool read_counter () { |
mariob | 0:cc364516d433 | 267 | // read counter |
mariob | 0:cc364516d433 | 268 | FILE *fp = fopen(FILE_CNT, "r"); |
mariob | 0:cc364516d433 | 269 | if(fp == NULL) { |
mariob | 0:cc364516d433 | 270 | fp = fopen(FILE_CNT, "w"); |
mariob | 0:cc364516d433 | 271 | if(fp == NULL) |
mariob | 0:cc364516d433 | 272 | return false; |
mariob | 0:cc364516d433 | 273 | global_config.count = 0; |
mariob | 0:cc364516d433 | 274 | fprintf(fp, "0\n"); |
mariob | 0:cc364516d433 | 275 | } else |
mariob | 0:cc364516d433 | 276 | fscanf(fp, "%d\n", &global_config.count); |
mariob | 0:cc364516d433 | 277 | fclose(fp); |
mariob | 0:cc364516d433 | 278 | |
mariob | 0:cc364516d433 | 279 | return true; |
mariob | 0:cc364516d433 | 280 | } |