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