IoT_watering project - supervisor
Dependencies: mbed-rtos mbed ssWi
main.cpp@0:cc364516d433, 2017-01-18 (annotated)
- Committer:
- mariob
- Date:
- Wed Jan 18 21:01:38 2017 +0000
- Revision:
- 0:cc364516d433
- Child:
- 1:dcfe7e79a45c
alpha release
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 | 0:cc364516d433 | 4 | #include "config.hpp" |
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 | 0:cc364516d433 | 11 | ssWiSocket* socket_command; |
mariob | 0:cc364516d433 | 12 | ssWiSocket* socket_moisture[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 13 | ssWiSocket* socket_temperature[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 14 | ssWiSocket* socket_humidity[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 15 | ssWiSocket* socket_response[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 16 | ssWiSocket* socket_water[MAX_NUM_NODES]; |
mariob | 0:cc364516d433 | 17 | |
mariob | 0:cc364516d433 | 18 | LocalFileSystem local("local"); |
mariob | 0:cc364516d433 | 19 | |
mariob | 0:cc364516d433 | 20 | bool read_counter(); |
mariob | 0:cc364516d433 | 21 | bool read_configuration(); |
mariob | 0:cc364516d433 | 22 | |
mariob | 0:cc364516d433 | 23 | bool read_from_port(ssWiSocket *socket, int *value); |
mariob | 0:cc364516d433 | 24 | |
mariob | 0:cc364516d433 | 25 | bool read_timeout(ssWiSocket *socket, int *value); |
mariob | 0:cc364516d433 | 26 | |
mariob | 0:cc364516d433 | 27 | void do_sampling(); |
mariob | 0:cc364516d433 | 28 | void do_watering(); |
mariob | 0:cc364516d433 | 29 | |
mariob | 0:cc364516d433 | 30 | int main() { |
mariob | 0:cc364516d433 | 31 | // supervisor configuration |
mariob | 0:cc364516d433 | 32 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 33 | printf("SUPERVISOR - config\r\n"); |
mariob | 0:cc364516d433 | 34 | #endif |
mariob | 0:cc364516d433 | 35 | if (!read_configuration()) |
mariob | 0:cc364516d433 | 36 | error("Impossible to read configuration"); |
mariob | 0:cc364516d433 | 37 | |
mariob | 0:cc364516d433 | 38 | // network configuration |
mariob | 0:cc364516d433 | 39 | XBeeModule xbee(p9, p10, 102, 14); |
mariob | 0:cc364516d433 | 40 | xbee.init(5, 10); |
mariob | 0:cc364516d433 | 41 | socket_command = ssWiSocket::createSocket(PORT_COMMANDS); |
mariob | 0:cc364516d433 | 42 | for (int i = 0; i < global_config.num_units; i++) { |
mariob | 0:cc364516d433 | 43 | socket_moisture[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 44 | global_config.nodes[i].address * 5 + PORT_MOISTURE_OFFSET); |
mariob | 0:cc364516d433 | 45 | socket_temperature[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 46 | global_config.nodes[i].address * 5 + PORT_TEMPERATURE_OFFSET); |
mariob | 0:cc364516d433 | 47 | socket_humidity[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 48 | global_config.nodes[i].address * 5 + PORT_HUMIDITY_OFFSET); |
mariob | 0:cc364516d433 | 49 | socket_response[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 50 | global_config.nodes[i].address * 5 + PORT_RESPONSE_OFFSET); |
mariob | 0:cc364516d433 | 51 | socket_water[i] = ssWiSocket::createSocket( |
mariob | 0:cc364516d433 | 52 | global_config.nodes[i].address * 5 + PORT_WATER_OFFSET); |
mariob | 0:cc364516d433 | 53 | } |
mariob | 0:cc364516d433 | 54 | |
mariob | 0:cc364516d433 | 55 | // initialize shared variables |
mariob | 0:cc364516d433 | 56 | for (int i = 0; i < MAX_NUM_NODES; i++) |
mariob | 0:cc364516d433 | 57 | last_watering[i] = 1; |
mariob | 0:cc364516d433 | 58 | |
mariob | 0:cc364516d433 | 59 | // start |
mariob | 0:cc364516d433 | 60 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 61 | printf("SUPERVISOR - start\r\n"); |
mariob | 0:cc364516d433 | 62 | #endif |
mariob | 0:cc364516d433 | 63 | while(1) { |
mariob | 0:cc364516d433 | 64 | int minute_counters = 0; |
mariob | 0:cc364516d433 | 65 | read_counter(); |
mariob | 0:cc364516d433 | 66 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 67 | printf("SUPERVISOR - wait...\r\n"); |
mariob | 0:cc364516d433 | 68 | #endif |
mariob | 0:cc364516d433 | 69 | do { |
mariob | 0:cc364516d433 | 70 | // wait 1 minute |
mariob | 0:cc364516d433 | 71 | Thread::wait(INTERVAL_60_SECONDS * 1000); |
mariob | 0:cc364516d433 | 72 | minute_counters++; |
mariob | 0:cc364516d433 | 73 | } while (minute_counters < global_config.wait_minutes); |
mariob | 0:cc364516d433 | 74 | |
mariob | 0:cc364516d433 | 75 | // mark as busy |
mariob | 0:cc364516d433 | 76 | DigitalOut led_busy(LED4); |
mariob | 0:cc364516d433 | 77 | led_busy = 1; |
mariob | 0:cc364516d433 | 78 | FILE* fp_busy = fopen(FILE_BSY, "w"); |
mariob | 0:cc364516d433 | 79 | |
mariob | 0:cc364516d433 | 80 | // sample and water |
mariob | 0:cc364516d433 | 81 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 82 | printf("SUPERVISOR - sampling\r\n"); |
mariob | 0:cc364516d433 | 83 | #endif |
mariob | 0:cc364516d433 | 84 | do_sampling(); |
mariob | 0:cc364516d433 | 85 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 86 | printf("SUPERVISOR - watering\r\n"); |
mariob | 0:cc364516d433 | 87 | #endif |
mariob | 0:cc364516d433 | 88 | do_watering(); |
mariob | 0:cc364516d433 | 89 | |
mariob | 0:cc364516d433 | 90 | // increment counter |
mariob | 0:cc364516d433 | 91 | global_config.count++; |
mariob | 0:cc364516d433 | 92 | FILE* fp = fopen(FILE_CNT, "w"); |
mariob | 0:cc364516d433 | 93 | fprintf(fp, "%d\n", global_config.count); |
mariob | 0:cc364516d433 | 94 | fclose(fp); |
mariob | 0:cc364516d433 | 95 | |
mariob | 0:cc364516d433 | 96 | // send shutdown |
mariob | 0:cc364516d433 | 97 | #ifdef DEBUG |
mariob | 0:cc364516d433 | 98 | printf("SUPERVISOR - shutdown\r\n"); |
mariob | 0:cc364516d433 | 99 | #endif |
mariob | 0:cc364516d433 | 100 | wait(INTERVAL_SYNC); |
mariob | 0:cc364516d433 | 101 | socket_command->write(COMM_SHUTDOWN); |
mariob | 0:cc364516d433 | 102 | wait(INTERVAL_SYNC); |
mariob | 0:cc364516d433 | 103 | socket_command->write(COMM_NO_VALUE); |
mariob | 0:cc364516d433 | 104 | wait(INTERVAL_SYNC); |
mariob | 0:cc364516d433 | 105 | |
mariob | 0:cc364516d433 | 106 | // mark as not busy |
mariob | 0:cc364516d433 | 107 | led_busy = 0; |
mariob | 0:cc364516d433 | 108 | fclose(fp_busy); |
mariob | 0:cc364516d433 | 109 | } |
mariob | 0:cc364516d433 | 110 | } |
mariob | 0:cc364516d433 | 111 | |
mariob | 0:cc364516d433 | 112 | void do_sampling () { |
mariob | 0:cc364516d433 | 113 | FILE* fp = fopen(FILE_SNS, "a"); |
mariob | 0:cc364516d433 | 114 | Timer t; |
mariob | 0:cc364516d433 | 115 | |
mariob | 0:cc364516d433 | 116 | socket_command->write(COMM_START_SAMPLING); |
mariob | 0:cc364516d433 | 117 | t.start(); |
mariob | 0:cc364516d433 | 118 | while(t.read() < INTERVAL_SAMPLING); |
mariob | 0:cc364516d433 | 119 | |
mariob | 0:cc364516d433 | 120 | socket_command->write(COMM_STOP_SAMPLING); |
mariob | 0:cc364516d433 | 121 | t.reset(); |
mariob | 0:cc364516d433 | 122 | while(t.read() < INTERVAL_SYNC); |
mariob | 0:cc364516d433 | 123 | |
mariob | 0:cc364516d433 | 124 | for (int i = 0; i < global_config.num_units; i++) { |
mariob | 0:cc364516d433 | 125 | int temp = 0, humi = 0, mois = 0, sampling_feedback = COMM_NO_VALUE; |
mariob | 0:cc364516d433 | 126 | int code; |
mariob | 0:cc364516d433 | 127 | if (!read_timeout(socket_response[i], &sampling_feedback)) |
mariob | 0:cc364516d433 | 128 | code = 1; |
mariob | 0:cc364516d433 | 129 | else { |
mariob | 0:cc364516d433 | 130 | switch (sampling_feedback) { |
mariob | 0:cc364516d433 | 131 | case COMM_SAMPLING_OK: |
mariob | 0:cc364516d433 | 132 | code = (read_timeout(socket_temperature[i], &temp) && |
mariob | 0:cc364516d433 | 133 | read_timeout(socket_humidity[i], &humi) && |
mariob | 0:cc364516d433 | 134 | read_timeout(socket_moisture[i], &mois)) ? 0 : 2; |
mariob | 0:cc364516d433 | 135 | break; |
mariob | 0:cc364516d433 | 136 | case COMM_SAMPLING_KO: code = 3; break; |
mariob | 0:cc364516d433 | 137 | case COMM_SAMPLING_OUT: code = 4; break; |
mariob | 0:cc364516d433 | 138 | default: code = 5; |
mariob | 0:cc364516d433 | 139 | } |
mariob | 0:cc364516d433 | 140 | } |
mariob | 0:cc364516d433 | 141 | fprintf(fp, "%d %d %d %4.2f %4.2f %4.2f\n", global_config.count, |
mariob | 0:cc364516d433 | 142 | global_config.nodes[i].address, |
mariob | 0:cc364516d433 | 143 | code, |
mariob | 0:cc364516d433 | 144 | (double)humi/10.0, |
mariob | 0:cc364516d433 | 145 | (double)temp/10.0, |
mariob | 0:cc364516d433 | 146 | (double)mois/10.0); |
mariob | 0:cc364516d433 | 147 | } |
mariob | 0:cc364516d433 | 148 | fclose(fp); |
mariob | 0:cc364516d433 | 149 | } |
mariob | 0:cc364516d433 | 150 | |
mariob | 0:cc364516d433 | 151 | void do_watering () { |
mariob | 0:cc364516d433 | 152 | for (int i = 0; i < global_config.num_units; i++) { |
mariob | 0:cc364516d433 | 153 | if (global_config.count % global_config.nodes[i].watering_wait) |
mariob | 0:cc364516d433 | 154 | continue; |
mariob | 0:cc364516d433 | 155 | FILE* fp = fopen(FILE_WTR, "a"); |
mariob | 0:cc364516d433 | 156 | |
mariob | 0:cc364516d433 | 157 | socket_water[i]->write(global_config.nodes[i].watering_seconds); |
mariob | 0:cc364516d433 | 158 | |
mariob | 0:cc364516d433 | 159 | Timer t; |
mariob | 0:cc364516d433 | 160 | t.start(); |
mariob | 0:cc364516d433 | 161 | wait(t.read() < INTERVAL_1_SECOND); |
mariob | 0:cc364516d433 | 162 | |
mariob | 0:cc364516d433 | 163 | socket_command->write(COMM_START_WATERING_OFFSET + |
mariob | 0:cc364516d433 | 164 | global_config.nodes[i].address); |
mariob | 0:cc364516d433 | 165 | t.reset(); |
mariob | 0:cc364516d433 | 166 | while (t.read() < (global_config.nodes[i].watering_seconds + |
mariob | 0:cc364516d433 | 167 | INTERVAL_SYNC)); |
mariob | 0:cc364516d433 | 168 | t.stop(); |
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 | fclose(fp); |
mariob | 0:cc364516d433 | 185 | } |
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 | // read configuration file |
mariob | 0:cc364516d433 | 215 | FILE *fp = fopen(FILE_CFG, "r"); |
mariob | 0:cc364516d433 | 216 | if(fp == NULL) |
mariob | 0:cc364516d433 | 217 | return false; |
mariob | 0:cc364516d433 | 218 | char line[250]; |
mariob | 0:cc364516d433 | 219 | |
mariob | 0:cc364516d433 | 220 | while(fgets(line, sizeof(line), fp)) { |
mariob | 0:cc364516d433 | 221 | if (line[0] == '#') |
mariob | 0:cc364516d433 | 222 | continue; |
mariob | 0:cc364516d433 | 223 | switch(state) { |
mariob | 0:cc364516d433 | 224 | case 0: //read interval length |
mariob | 0:cc364516d433 | 225 | sscanf(line, "%d\r", &global_config.wait_minutes); |
mariob | 0:cc364516d433 | 226 | state = 1; |
mariob | 0:cc364516d433 | 227 | break; |
mariob | 0:cc364516d433 | 228 | case 1: //read number of watering units |
mariob | 0:cc364516d433 | 229 | sscanf(line, "%d\r", &global_config.num_units); |
mariob | 0:cc364516d433 | 230 | state = 2; |
mariob | 0:cc364516d433 | 231 | break; |
mariob | 0:cc364516d433 | 232 | case 2: //read number of watering units |
mariob | 0:cc364516d433 | 233 | sscanf(line, "%d %d %d\r", |
mariob | 0:cc364516d433 | 234 | &global_config.nodes[n_unit].address, |
mariob | 0:cc364516d433 | 235 | &global_config.nodes[n_unit].watering_wait, |
mariob | 0:cc364516d433 | 236 | &global_config.nodes[n_unit].watering_seconds); |
mariob | 0:cc364516d433 | 237 | n_unit++; |
mariob | 0:cc364516d433 | 238 | if (n_unit >= global_config.num_units || n_unit >=MAX_NUM_NODES) |
mariob | 0:cc364516d433 | 239 | state = 3; |
mariob | 0:cc364516d433 | 240 | break; |
mariob | 0:cc364516d433 | 241 | } |
mariob | 0:cc364516d433 | 242 | } |
mariob | 0:cc364516d433 | 243 | fclose(fp); |
mariob | 0:cc364516d433 | 244 | |
mariob | 0:cc364516d433 | 245 | return true; |
mariob | 0:cc364516d433 | 246 | } |
mariob | 0:cc364516d433 | 247 | |
mariob | 0:cc364516d433 | 248 | bool read_counter () { |
mariob | 0:cc364516d433 | 249 | // read counter |
mariob | 0:cc364516d433 | 250 | FILE *fp = fopen(FILE_CNT, "r"); |
mariob | 0:cc364516d433 | 251 | if(fp == NULL) { |
mariob | 0:cc364516d433 | 252 | fp = fopen(FILE_CNT, "w"); |
mariob | 0:cc364516d433 | 253 | if(fp == NULL) |
mariob | 0:cc364516d433 | 254 | return false; |
mariob | 0:cc364516d433 | 255 | global_config.count = 0; |
mariob | 0:cc364516d433 | 256 | fprintf(fp, "0\n"); |
mariob | 0:cc364516d433 | 257 | } else |
mariob | 0:cc364516d433 | 258 | fscanf(fp, "%d\n", &global_config.count); |
mariob | 0:cc364516d433 | 259 | fclose(fp); |
mariob | 0:cc364516d433 | 260 | |
mariob | 0:cc364516d433 | 261 | return true; |
mariob | 0:cc364516d433 | 262 | } |