iot_water_monitor_v2

Dependencies:   easy-connect-v16 Watchdog FP MQTTPacket RecordType-v-16 watersenor_and_temp_code

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /**
00002   * Revision
00003   * version 1.0
00004   * ....
00005   * version 2.5     02-14-2018: 3rd relay and remote time setting are added
00006   * version 2.6     02-14-2018: DO Sensor added, calibration is still on the way
00007   * version 2.6.3   02-19-2018: developing calibration. the average voltage is ok
00008   * version 2.6.5   02-21-2018: developing calibration. Sensor read is completely ok
00009   * version 2.6.8   02-27-2018: developing DO calibration. DS18B20 temperature sensor is added
00010   * version 2.7     03-04-2018: DO calibration complete. IWDG is added
00011   * version 2.7.5   03-08-2018: DS18B20 & IWDG is being developed
00012   * version 2.7.5a  03-08-2018: DS18B20 problem discovered at line 42th ReadSensor.cpp
00013                                 Upload RTC time converted to epoch
00014   * version 2.8     03-18-2018: DS18B20 problem solved
00015   * version 2.8.5   03-19-2018: Set time to turn on/off the relay
00016   * version 2.9     03-22-2018: Watchdog worked. Some hardware bugs found
00017   * version 2.9.7   03-29-2018: Try to upload 1 more time if upload fail
00018   * version 2.9.7   03-30-2018
00019   * version 2.9.8   03-04-2018  Minor changes. Time frame updated to IBM Watson every 60s
00020   */
00021 
00022 /***************************************************************
00023  * Includes
00024  ***************************************************************/
00025 #include "mbed.h"
00026 
00027 #include "ReadSensor.h"
00028 #include "SimpleMQTT.h"
00029 #include "CommandExecution.h"
00030 #include "flash_programming.h"
00031 
00032 #include "Watchdog.h"
00033 
00034 /***************************************************************
00035  * Definitions
00036  ***************************************************************/
00037 //#define READ_ANALOG_SOFTTIMER 
00038  
00039 #define READ_SECOND                         1    /* Read timer every 1 second(s) */
00040 #define INTERVAL_BETWEEN_EACH_UPLOAD_TYPE   10   /* The interval between each upload type in second */
00041 #define RECONNECT_WIFI                      60   /* Try to reconnect to wifi */
00042 #ifdef READ_ANALOG_SOFTTIMER
00043     #define READ_ANALOG_MS                  30
00044 #endif
00045 #define PROCESS_SENSOR_VALUE_S              2
00046 #define CALIB_STATE_CHANGE_PERIOD_S         5
00047 #define ALARM_TIME_ODD                      20
00048 
00049 #define SEND_TIME_INTERVAL                  60  /* Send Time frame every 60s */
00050 /***************************************************************
00051  * Variables
00052  ***************************************************************/
00053 bool        isUploading         = false;
00054 bool        isSendingData       = false;
00055 bool        isUploadImmediately = false;
00056 bool        isFirstUpload       = true;
00057 uint8_t     uploadType          = SENSOR_VALUE;
00058 uint8_t     currentCalibMode    = 1;
00059 uint8_t     calibStateCounter   = 0;
00060 
00061 uint32_t    lastRead                = 0;
00062 uint32_t    noWiFilastRead          = 0;
00063 uint16_t    intervalSecondCounter   = 0;  
00064 uint32_t    uploadPeriodCounter     = 0;
00065 
00066 #ifdef READ_ANALOG_SOFTTIMER
00067     uint32_t    lastReadAnalog          = 0;
00068 #endif
00069 
00070 struct UploadValue DataStruct;
00071 Watchdog           wd;
00072 
00073 extern float doValue;
00074 extern float temperature;
00075 extern bool  isCalibrating;
00076 
00077 /***************************************************************
00078  * Structs/Classess
00079  ***************************************************************/
00080 static Serial pc(SERIAL_TX, SERIAL_RX); 
00081 
00082 //DigitalOut    myled(LED1);
00083 DigitalOut  myled(A6);
00084 DigitalOut  espEn(D2);
00085 DigitalOut  espRs(D7);
00086 
00087 Timer       UploadTimer;
00088 #ifdef READ_ANALOG_SOFTTIMER
00089     Timer       ReadAnalogTimer;
00090 #endif
00091 Ticker      DisplayDO;
00092 
00093 /***************************************************************
00094  * Unity function definitions
00095  ***************************************************************/
00096 void ReadAllFlashValues();
00097 void SensorRun(); 
00098 void enableESP();
00099 
00100 void BinkLEDStart();
00101 
00102 void AutomaticHandle();
00103 void TimeAlarmHandle();
00104 
00105 /***************************************************************
00106  * Unity function declarations
00107  ***************************************************************/ 
00108 void ReadAllFlashValues() {
00109     DataStruct.ADC_TEMPVal                  = 0;
00110     DataStruct.ADC_DOVal                    = 0;
00111     DataStruct.SENSOR_TEMPVal               = 0;
00112     DataStruct.SENSOR_DOVal                 = 0;
00113     DataStruct.RELAY_State_1                = FP_ReadValue(RELAY1_ADDRESS);
00114     DataStruct.RELAY_State_2                = FP_ReadValue(RELAY2_ADDRESS);
00115     DataStruct.RELAY_State_3                = FP_ReadValue(RELAY3_ADDRESS);
00116     DataStruct.CONFIG_Mode                  = FP_ReadValue(MODE_ADDRESS);
00117     DataStruct.CONFIG_OxyThreshold          = FP_ReadValue(OXY_THRES_ADDRESS);
00118     DataStruct.CONFIG_TemperatureThreshold  = FP_ReadValue(TEMP_THRES_ADDRESS);
00119     DataStruct.CONFIG_UploadInterval        = FP_ReadValue(UPLOAD_PERIOD_ADDRESS);
00120     DataStruct.CONFIG_AlarmTime             = FP_ReadValue(ALARM_TIME_ADDRESS);
00121     DataStruct.CONFIG_SetRelayState_1       = FP_ReadValue(SET_RELAY_1_ADDRESS);
00122     DataStruct.CONFIG_SetRelayState_2       = FP_ReadValue(SET_RELAY_2_ADDRESS);
00123     printf("All values: %d %d %d %d %d %d %d %d %d\r\n", DataStruct.RELAY_State_1, DataStruct.RELAY_State_2,
00124                                                 DataStruct.CONFIG_Mode,   DataStruct.CONFIG_OxyThreshold,   
00125                                                 DataStruct.CONFIG_TemperatureThreshold, DataStruct.CONFIG_UploadInterval,
00126                                                 DataStruct.CONFIG_AlarmTime, 
00127                                                 DataStruct.CONFIG_SetRelayState_1, DataStruct.CONFIG_SetRelayState_2);
00128     if (DataStruct.CONFIG_Mode == 0xFFFFFFFF) {
00129         DataStruct.CONFIG_Mode = 0;
00130     }
00131     if (DataStruct.CONFIG_OxyThreshold == 0xFFFFFFFF) {
00132         DataStruct.CONFIG_OxyThreshold = 50;
00133     }
00134     if (DataStruct.CONFIG_TemperatureThreshold == 0xFFFFFFFF) {
00135         DataStruct.CONFIG_TemperatureThreshold = 25;
00136     }
00137     if (DataStruct.CONFIG_UploadInterval == 0xFFFFFFFF) {
00138         DataStruct.CONFIG_UploadInterval = 300;
00139     }
00140     CE_HandleRelays(DataStruct.RELAY_State_1, DataStruct.RELAY_State_2, DataStruct.RELAY_State_3);
00141 }
00142 
00143 void SensorRun() {
00144     if (!isSendingData) {
00145         wd.Service();
00146         for (uint8_t j = 0; j < SCOUNT; j++) {
00147             SENSOR_AnalogRead();
00148         }
00149         SENSOR_GetDOValue();
00150         DataStruct.SENSOR_DOVal = doValue;
00151         DataStruct.SENSOR_TEMPVal = temperature;
00152         if (isCalibrating) {
00153             SENSOR_DoCalibration(currentCalibMode);
00154             if (currentCalibMode == 3) {
00155                 currentCalibMode = 1;
00156                 isCalibrating    = false;
00157             }
00158             calibStateCounter++;
00159             
00160             /* Change calibration mode every PROCESS_SENSOR_VALUE_S*CALIB_STATE_CHANGE_PERIOD_S second(s) */
00161             if ((calibStateCounter % CALIB_STATE_CHANGE_PERIOD_S) == 0) {      
00162                 currentCalibMode++;
00163             }
00164         }           
00165     }
00166     else {
00167         printf("No sensor reading because uploading data\r\n"); 
00168     }
00169 }
00170 
00171 void enableESP() {
00172     espRs = 0;  
00173     espEn = 0;
00174     wait(2);
00175     espEn = 1;
00176     espRs = 1;  
00177     printf("ESP enabled\r\n");
00178 }
00179 
00180 void BinkLEDStart() {
00181     myled = 1;
00182     for (uint8_t j = 0; j < 8; j++) {
00183         myled = !myled; 
00184         wait(0.2);
00185     }
00186     myled = 0;  
00187 }
00188 
00189 void AutomaticHandle() {
00190     if (DataStruct.CONFIG_Mode == 1) {            /* Automatic mode */
00191 //      printf("DataStruct.SENSOR_DOVal*100 %d\r\n",(uint32_t)(DataStruct.SENSOR_DOVal*100));
00192         if ((uint32_t)(DataStruct.SENSOR_DOVal*10) >= DataStruct.CONFIG_OxyThreshold) {
00193             /* Turn on the pumps */
00194             DataStruct.RELAY_State_1 = 1;      
00195             DataStruct.RELAY_State_2 = 1;  
00196             DataStruct.RELAY_State_3 = 1;   
00197              
00198         }
00199         else {
00200             /* Turn off the pumps */
00201             DataStruct.RELAY_State_1 = 0;      
00202             DataStruct.RELAY_State_2 = 0;
00203             DataStruct.RELAY_State_3 = 0;               
00204         }
00205         CE_HandleRelays(DataStruct.RELAY_State_1, DataStruct.RELAY_State_2, DataStruct.RELAY_State_3);   
00206         FP_WriteRelayStates(DataStruct.RELAY_State_1, DataStruct.RELAY_State_2, DataStruct.RELAY_State_3);
00207     }   
00208 }
00209 
00210 void TimeAlarmHandle(time_t CurrentTime) {
00211     if (CurrentTime == (DataStruct.CONFIG_AlarmTime)) {
00212         DataStruct.RELAY_State_1 = DataStruct.CONFIG_SetRelayState_1; 
00213         DataStruct.RELAY_State_2 = DataStruct.CONFIG_SetRelayState_2;
00214         CE_HandleRelays(DataStruct.RELAY_State_1, DataStruct.RELAY_State_2, DataStruct.RELAY_State_3);   
00215         FP_WriteRelayStates(DataStruct.RELAY_State_1, DataStruct.RELAY_State_2, DataStruct.RELAY_State_3);      
00216     }
00217 }
00218 /***************************************************************
00219  * Main
00220  ***************************************************************/ 
00221 int main() {   
00222     pc.baud(115200);
00223     printf("PROGRAM STARTS\r\n");
00224     set_time(1514768400);                //01-01-2018 8:30AM
00225     enableESP();
00226     UploadTimer.start();
00227     
00228     #ifdef READ_ANALOG_SOFTTIMER
00229         ReadAnalogTimer.start();
00230     #endif
00231     
00232     BinkLEDStart();
00233     
00234     lastRead = 0;
00235     pc.printf("\r\nViKa IoT Water Monitor mbed Application\r\n");     
00236     pc.printf("\r\nconnecting to AP\r\n");   
00237              
00238     wd.Configure(24.8);
00239     wd.Service();
00240     
00241     NetworkInterface* network = easy_connect(true);
00242     if (!network) {
00243         printf ("Error easy_connect\n\r");
00244         wifiConnected = false;
00245     } 
00246     wd.Service();
00247     printf ("ATTEMPT CONNECT\n\r");
00248     MQTTNetwork mqttNetwork(network);   
00249     MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> client(mqttNetwork); 
00250     wd.Service();
00251     MQTT_AttemptConnect(&client, &mqttNetwork, network, DataStruct);
00252     wd.Service();
00253     if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
00254         printf ("---ERROR line : %d, error type %d\n\r", __LINE__, connack_rc);
00255         wifiConnected = false;
00256 //      while (true)
00257 //          wait(1.0); // Permanent failures - don't retry
00258     }
00259     if (wd.WatchdogCausedReset()) {
00260         printf("Watchdog caused reset.\r\n");
00261     }
00262     wd.Service();
00263     DisplayDO.attach(&SensorRun, PROCESS_SENSOR_VALUE_S);
00264     ReadAllFlashValues();
00265     SENSOR_ReadDoCharacteristicValues();
00266     BinkLEDStart();
00267     wd.Service();
00268     lastRead = UploadTimer.read();  
00269     
00270     myled = 1;   
00271     while (true) {
00272         time_t seconds = time(NULL);    
00273         AutomaticHandle();
00274         TimeAlarmHandle(seconds);
00275         #ifdef READ_ANALOG_SOFTTIMER
00276             if ((uint32_t)(ReadAnalogTimer.read_ms() - lastReadAnalog) > READ_ANALOG_MS) {
00277                 SENSOR_AnalogRead();
00278                 lastReadAnalog = ReadAnalogTimer.read_ms();
00279             }
00280         #endif
00281         if (wifiConnected) {
00282             if(connected == true) {
00283                 /* Upload for the first time */
00284                 if (isFirstUpload) {
00285                     if (MQTT_PublishAll(&client, seconds, SENSOR_VALUE, DataStruct) != MQTT::SUCCESS) {
00286                         wait(2);
00287                         MQTT_PublishAll(&client, seconds, SENSOR_VALUE, DataStruct);
00288                         wait(2);
00289                         uint32_t uploadTimeFramePeriod = SEND_TIME_INTERVAL;
00290                         if (MQTT_PublishDeviceManage(&client, seconds, DataStruct.CONFIG_UploadInterval, uploadTimeFramePeriod) ==  MQTT::SUCCESS) {
00291                         }
00292                         else {
00293                             MQTT_PublishDeviceManage(&client, seconds, DataStruct.CONFIG_UploadInterval, uploadTimeFramePeriod);
00294                         }
00295                     }
00296                     else {
00297                         wait(2);
00298                         uint32_t uploadTimeFramePeriod = SEND_TIME_INTERVAL;
00299                         if (MQTT_PublishDeviceManage(&client, seconds, DataStruct.CONFIG_UploadInterval, uploadTimeFramePeriod) ==  MQTT::SUCCESS) {
00300                         }
00301                         else {
00302                             MQTT_PublishDeviceManage(&client, seconds, DataStruct.CONFIG_UploadInterval, uploadTimeFramePeriod);
00303                         }                       
00304                     }
00305                     wait(2);
00306                     isFirstUpload = false;
00307                 }
00308                     /* Periodic upload */
00309                     if ((uint32_t)(UploadTimer.read() - lastRead) >= READ_SECOND) {               // Read timer every readSecond(s)                             
00310                         /* Start uploading data */  
00311                         if (!isUploading) {
00312                             wd.Service();
00313                             uploadPeriodCounter++;
00314                             if (uploadPeriodCounter == DataStruct.CONFIG_UploadInterval) {  
00315                                 uploadPeriodCounter     = 0;
00316                                 isUploading             = true;
00317                                 intervalSecondCounter   = INTERVAL_BETWEEN_EACH_UPLOAD_TYPE;
00318                             }
00319                             else if ((uploadPeriodCounter % SEND_TIME_INTERVAL) == 0) {
00320                                 uint32_t uploadTimeFramePeriod = SEND_TIME_INTERVAL;
00321                                 if (MQTT_PublishDeviceManage(&client, seconds, DataStruct.CONFIG_UploadInterval, uploadTimeFramePeriod) ==  MQTT::SUCCESS) {
00322                                     myled = 1;
00323                                 }
00324                                 else {
00325                                     if (MQTT_PublishDeviceManage(&client, seconds, DataStruct.CONFIG_UploadInterval, uploadTimeFramePeriod) ==  MQTT::SUCCESS) {
00326                                         myled = 1;
00327                                     }
00328                                     else {
00329                                         myled = 0;  
00330                                     }
00331                                 }
00332                             }                   
00333                         }
00334                         else {
00335                             wd.Service();
00336                             if (intervalSecondCounter == INTERVAL_BETWEEN_EACH_UPLOAD_TYPE) {
00337                                 isSendingData = true;
00338                                 if (MQTT_PublishAll(&client, seconds, uploadType, DataStruct) ==  MQTT::SUCCESS) {
00339                                     myled = 1;
00340                                     uploadType++;
00341                                     if (uploadType > CONFIG_VALUE) {
00342                                         isUploading = false;
00343                                         uploadType  = SENSOR_VALUE;
00344                                         commandID++;
00345                                         UploadTimer.reset();
00346                                     }
00347                                 }
00348                                 else {
00349                                     /* Try to reupload */
00350                                     if (MQTT_PublishAll(&client, seconds, uploadType, DataStruct) ==  MQTT::SUCCESS) {
00351                                         myled = 1;
00352                                         uploadType++;
00353                                         if (uploadType > RELAY_STATE) {
00354                                             isUploading = false;
00355                                             uploadType  = SENSOR_VALUE;
00356                                             commandID++;
00357                                             UploadTimer.reset();
00358                                         }                                       
00359                                     }
00360                                     else {
00361                                         myled = 0;
00362                                         client.disconnect();
00363                                         mqttNetwork.disconnect();
00364                                         /* if we have lost the connection */ 
00365                                         MQTT_AttemptConnect(&client, &mqttNetwork, network, DataStruct);                                        
00366                                     }
00367                                 }
00368                                 isSendingData = false;                      
00369                                 intervalSecondCounter = 0;      
00370                             }
00371                             else {
00372                                 intervalSecondCounter++;
00373                             }
00374                         }
00375                         lastRead = UploadTimer.read();
00376                     }                          
00377                 /* allow the MQTT client to receive subscribe messages and manage keep alive */
00378                 wd.Service();
00379                 client.yield(500);                                                        
00380             } 
00381             else if (connected == false) {
00382                 connected = true;
00383             }           
00384         }
00385         else {
00386             wd.Service();
00387             if ((uint32_t)(UploadTimer.read() - noWiFilastRead) >= RECONNECT_WIFI) {
00388                 wifiConnected = true;
00389                 network = easy_connect(true);
00390                 MQTT_AttemptConnect(&client, &mqttNetwork, network, DataStruct);
00391                 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
00392                     printf ("---ERROR line : %d, error type %d\n\r", __LINE__, connack_rc);
00393                     wifiConnected = false;
00394             //          while (true)
00395             //              wait(1.0); // Permanent failures - don't retry
00396                 }               
00397                 noWiFilastRead = UploadTimer.read();
00398             }
00399         }
00400     }
00401 }
00402