Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed-rtos mbed ssWi
main.cpp
00001 #include "mbed.h" 00002 #include "rtos.h" 00003 00004 #include "config.h" 00005 00006 #include "xbee.hpp" 00007 #include "ssWiSocket.hpp" 00008 00009 #ifndef DEBUG 00010 #define printf(fmt,...) 00011 #endif 00012 00013 // global configuration 00014 global_confg_t global_config; 00015 00016 // ssWi sockets 00017 ssWiSocket* socket_command; 00018 ssWiSocket* socket_moisture[MAX_NUM_NODES]; 00019 ssWiSocket* socket_temperature[MAX_NUM_NODES]; 00020 ssWiSocket* socket_humidity[MAX_NUM_NODES]; 00021 ssWiSocket* socket_response[MAX_NUM_NODES]; 00022 ssWiSocket* socket_water[MAX_NUM_NODES]; 00023 00024 LocalFileSystem local("local"); 00025 00026 // read counter value from file 00027 bool read_counter(); 00028 // read board configuration from file 00029 bool read_configuration(); 00030 00031 // return true if a message has been received, false otherwise 00032 bool read_from_port(ssWiSocket *socket, int *value); 00033 // blocking read - timeout after 10 seconds 00034 bool read_timeout(ssWiSocket *socket, int *value); 00035 00036 void do_sampling(); 00037 void do_watering(); 00038 00039 int main() { 00040 DigitalOut power_device(POWER_EN_PIN); 00041 power_device = POWER_OFF; 00042 00043 // supervisor configuration 00044 printf("SUPERVISOR - config\r\n"); 00045 00046 // read configuration 00047 if (!read_configuration()) 00048 error("Impossible to read configuration"); 00049 00050 // network configuration 00051 XBeeModule xbee(XBEE_PIN_TX, XBEE_PIN_RX, PAN_ID, CHANNEL_ID); 00052 xbee.init(XBEE_TX_PER_SECOND, XBEE_RX_PER_SECOND); 00053 socket_command = ssWiSocket::createSocket(PORT_COMMANDS); 00054 for (int i = 0; i < global_config.num_units; i++) { 00055 socket_moisture[i] = ssWiSocket::createSocket( 00056 global_config.nodes[i].address * 5 + PORT_MOISTURE_OFFSET); 00057 socket_temperature[i] = ssWiSocket::createSocket( 00058 global_config.nodes[i].address * 5 + PORT_TEMPERATURE_OFFSET); 00059 socket_humidity[i] = ssWiSocket::createSocket( 00060 global_config.nodes[i].address * 5 + PORT_HUMIDITY_OFFSET); 00061 socket_response[i] = ssWiSocket::createSocket( 00062 global_config.nodes[i].address * 5 + PORT_RESPONSE_OFFSET); 00063 socket_water[i] = ssWiSocket::createSocket( 00064 global_config.nodes[i].address * 5 + PORT_WATER_OFFSET); 00065 } 00066 00067 // start 00068 printf("SUPERVISOR - start\r\n"); 00069 00070 while(1) { 00071 int minute_counters = 0; 00072 printf("SUPERVISOR - waiting\r\n"); 00073 do { 00074 // wait 1 minute 00075 Thread::wait(INTERVAL_60_SECONDS * 1000); 00076 minute_counters++; 00077 } while (minute_counters < global_config.wait_minutes); 00078 00079 printf("SUPERVISOR - active\r\n"); 00080 00081 // mark as busy 00082 DigitalOut led_busy(LED4); 00083 led_busy = 1; 00084 FILE* fp_busy = fopen(FILE_BSY, "w"); 00085 00086 // power watering units 00087 power_device = POWER_ON; 00088 wait(INTERVAL_POWER_START); 00089 00090 read_counter(); 00091 00092 // sample and water 00093 printf("SUPERVISOR - sampling\r\n"); 00094 do_sampling(); 00095 printf("SUPERVISOR - watering\r\n"); 00096 do_watering(); 00097 00098 // increment counter 00099 global_config.count++; 00100 FILE* fp = fopen(FILE_CNT, "w"); 00101 fprintf(fp, "%d\n", global_config.count); 00102 fclose(fp); 00103 00104 // send shutdown 00105 printf("SUPERVISOR - shutdown\r\n"); 00106 00107 wait(INTERVAL_SYNC); 00108 socket_command->write(COMM_SHUTDOWN); 00109 wait(INTERVAL_SYNC * 2); 00110 00111 // power off devices 00112 power_device = POWER_OFF; 00113 00114 // mark as not busy 00115 led_busy = 0; 00116 fclose(fp_busy); 00117 } 00118 } 00119 00120 void do_sampling () { 00121 FILE* fp = fopen(FILE_SNS, "a"); 00122 00123 socket_command->write(COMM_START_SAMPLING); 00124 wait(INTERVAL_SAMPLING); 00125 00126 socket_command->write(COMM_STOP_SAMPLING); 00127 wait(INTERVAL_SYNC); 00128 00129 for (int i = 0; i < global_config.num_units; i++) { 00130 int temp = 0, humi = 0, mois = 0, sampling_feedback = COMM_NO_VALUE; 00131 int code; 00132 if (!read_timeout(socket_response[i], &sampling_feedback)) 00133 code = 1; 00134 else { 00135 switch (sampling_feedback) { 00136 case COMM_SAMPLING_OK: 00137 code = (read_timeout(socket_temperature[i], &temp) && 00138 read_timeout(socket_humidity[i], &humi) && 00139 read_timeout(socket_moisture[i], &mois)) ? 0 : 2; 00140 break; 00141 case COMM_SAMPLING_KO: code = 3; break; 00142 case COMM_SAMPLING_OUT: code = 4; break; 00143 default: code = 5; 00144 } 00145 } 00146 fprintf(fp, "%d %d %d %4.2f %4.2f %4.2f\n", global_config.count, 00147 global_config.nodes[i].address, 00148 code, 00149 (double)humi/10.0, 00150 (double)temp/10.0, 00151 (double)mois/10.0); 00152 } 00153 fclose(fp); 00154 } 00155 00156 void do_watering () { 00157 FILE* fp = fopen(FILE_WTR, "a"); 00158 for (int i = 0; i < global_config.num_units; i++) { 00159 if (global_config.count % global_config.nodes[i].watering_wait) 00160 continue; 00161 // write watering time in seconds 00162 socket_water[i]->write(global_config.nodes[i].watering_seconds); 00163 wait(INTERVAL_SYNC); 00164 // send watering command 00165 socket_command->write(COMM_START_WATERING_OFFSET + 00166 global_config.nodes[i].address); 00167 wait(global_config.nodes[i].watering_seconds + INTERVAL_SYNC + 00168 INTERVAL_SYNC); 00169 00170 int watering_response = 0; 00171 int code = 4; 00172 if (read_timeout(socket_response[i], &watering_response)) { 00173 switch(watering_response) { 00174 case COMM_WATERING_KO: code = 1; break; 00175 case COMM_WATERING_OK: code = 0; break; 00176 case COMM_LOW_WATER_LEVEL: code = 2; break; 00177 default: code = 3; 00178 } 00179 } 00180 fprintf(fp, "%d %d %d %d\n", global_config.count, 00181 global_config.nodes[i].address, 00182 code, 00183 global_config.nodes[i].watering_seconds); 00184 } 00185 fclose(fp); 00186 } 00187 00188 bool read_from_port(ssWiSocket *socket, int *value) { 00189 int prev = *value; 00190 *value = socket->read(); 00191 return (*value) != prev; 00192 } 00193 00194 bool read_timeout(ssWiSocket *socket, int *value) { 00195 Timer t; 00196 t.start(); 00197 bool ret; 00198 int v = COMM_NO_VALUE; 00199 double start = t.read(); 00200 do { 00201 if ((t.read() - start) > TIMEOUT_READ) 00202 return false; 00203 ret = read_from_port(socket, &v); 00204 } while(!ret); 00205 t.stop(); 00206 *value = v; 00207 return true; 00208 } 00209 00210 bool read_configuration() { 00211 int state = 0; 00212 int n_unit = 0; 00213 00214 FILE *fp = fopen(FILE_CFG, "r"); 00215 if(fp == NULL) 00216 return false; 00217 char line[250]; 00218 00219 while(fgets(line, sizeof(line), fp)) { 00220 if (line[0] == '#') 00221 continue; 00222 switch(state) { 00223 case 0: //read interval length 00224 sscanf(line, "%d\r", &global_config.wait_minutes); 00225 state = 1; 00226 break; 00227 case 1: //read number of watering units 00228 sscanf(line, "%d\r", &global_config.num_units); 00229 state = 2; 00230 break; 00231 case 2: //read number of watering units 00232 sscanf(line, "%d %d %d\r", 00233 &global_config.nodes[n_unit].address, 00234 &global_config.nodes[n_unit].watering_wait, 00235 &global_config.nodes[n_unit].watering_seconds); 00236 n_unit++; 00237 if (n_unit >= global_config.num_units || n_unit >=MAX_NUM_NODES) 00238 state = 3; 00239 break; 00240 } 00241 } 00242 fclose(fp); 00243 00244 return true; 00245 } 00246 00247 bool read_counter () { 00248 FILE *fp = fopen(FILE_CNT, "r"); 00249 if(fp == NULL) { 00250 fp = fopen(FILE_CNT, "w"); 00251 if(fp == NULL) 00252 return false; 00253 global_config.count = 0; 00254 fprintf(fp, "0\n"); 00255 } else 00256 fscanf(fp, "%d\n", &global_config.count); 00257 fclose(fp); 00258 00259 return true; 00260 }
Generated on Sun Jul 17 2022 12:07:48 by
1.7.2