Lovkesh Chauhan / Mbed OS SmartKitchen_MiniProject_RTES

Dependencies:   C12832 LM75B MQ2 MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*******************************************************************************
00002  * Copyright (c) 2014, 2015 IBM Corp.
00003  *
00004  * All rights reserved. This program and the accompanying materials
00005  * are made available under the terms of the Eclipse Public License v1.0
00006  * and Eclipse Distribution License v1.0 which accompany this distribution.
00007  *
00008  * The Eclipse Public License is available at
00009  *    http://www.eclipse.org/legal/epl-v10.html
00010  * and the Eclipse Distribution License is available at
00011  *   http://www.eclipse.org/org/documents/edl-v10.php.
00012  *
00013  * Contributors:
00014  *    Ian Craggs - initial API and implementation and/or initial documentation
00015  *    Ian Craggs - make sure QoS2 processing works, and add device headers
00016  *******************************************************************************/
00017 
00018  /**
00019   This is a sample program to illustrate the use of the MQTT Client library
00020   on the mbed platform.  The Client class requires two classes which mediate
00021   access to system interfaces for networking and timing.  As long as these two
00022   classes provide the required public programming interfaces, it does not matter
00023   what facilities they use underneath. In this program, they use the mbed
00024   system libraries.
00025 
00026  */
00027 
00028  // change this to 1 to output messages to LCD instead of serial
00029 #define USE_LCD 1
00030 
00031 #if USE_LCD
00032 #include "C12832.h"
00033 
00034 // the actual pins are defined in mbed_app.json and can be overridden per target
00035 C12832 lcd(LCD_MOSI, LCD_SCK, LCD_MISO, LCD_A0, LCD_NCS);
00036 
00037 #define logMessage lcd.cls();lcd.locate(0,0);lcd.printf
00038 
00039 #else
00040 
00041 #define logMessage printf
00042 
00043 #endif
00044 
00045 #define MQTTCLIENT_QOS2 0
00046 
00047 #include "easy-connect.h" //Ethernet Connection library
00048 #include "MQTTNetwork.h" //MQTT Connection
00049 #include "MQTTmbed.h"  //MQTT Connection
00050 #include "MQTTClient.h" //MQTT Connection
00051 #include "string.h";
00052 
00053 #include "mbed.h" 
00054 //#include "platform/mbed_thread.h"
00055 #include "FP.h" //For function pointer usage
00056 #include "MQ2.h" //Smoke and Gas detector library
00057 #include "LM75B.h" //Temperature sensor
00058 
00059 #define ON 1 
00060 #define OFF 0
00061 
00062 #define PUMP PTC1 //Relay Signal for controlling pump
00063 #define TRIGGER PTB18 //Trigger pin for ultrasonic sensor
00064 #define ECHO PTB19 //Echo pin for ultrasonic sensor
00065 #define MQ2_SIG PTC10 //Smoke and Gas sensor output pin
00066 #define ALARM_SIG PTC8 //Alarm Signal Pin
00067 #define FAN_SIG PTC9 //Fan signal pin
00068 
00069 //Global variables to update the ThingSpeak channel fields.
00070 int WATER_LEVEL = 0; 
00071 float CO_level = 0;
00072 float SMOKE_level = 0;
00073 float GAS_level = 0;
00074 float TEMPERATURE = 0;
00075 int FAN_STATE = 0;
00076 int ALARM_STATE = 0;
00077 int PUMP_STATE = 0;
00078 
00079 class indicator{ //class to allow easy usage of RGB LED 
00080     private:
00081         DigitalOut RED; //LED1
00082         DigitalOut BLUE; //LED2
00083         DigitalOut GREEN; //LED3
00084         Ticker blink; //Ticker to start blinking
00085         bool red_set; //bool to check if RED is ON
00086         bool green_set; //bool to check if GREEN is ON
00087         bool blue_set; //bool to check if BLUE is ON
00088         
00089         void blink_effect(){ //function to flip LEDs to generate blink effect
00090             if(red_set)
00091                 RED = !RED;
00092             if(green_set)
00093                 GREEN = !GREEN;
00094             if(blue_set)
00095                 BLUE = !BLUE;
00096         }
00097  
00098     public:
00099          indicator(PinName _LED1, PinName _LED2, PinName _LED3):RED(_LED1, 1), GREEN(_LED2, 1), BLUE(_LED3, 1){ //Initialize RGB LEDs with requried PINS.
00100              red_set = false; green_set = false; blue_set = false; //All LED intially OFF.
00101         }
00102         
00103         void red_led(){ //Set Only RED LED
00104             RED = 0; red_set = true; 
00105             GREEN = 1; green_set = false;
00106             BLUE = 1; blue_set = false;
00107         }
00108         
00109         void green_led(){ //Set Only GREEN LED
00110             RED = 1; red_set = false;
00111             GREEN = 0; green_set = true;
00112             BLUE = 1; blue_set = false;
00113         }
00114         void blue_led(){//Set Only BLUE LED
00115             RED = 1; red_set = false;
00116             GREEN = 1; green_set = false;
00117             BLUE = 0; blue_set = true;
00118         }
00119         void amber_led(){//Set Only AMBER LED
00120             RED = 0; red_set = true;
00121             GREEN = 0; green_set = true;
00122             BLUE = 1; blue_set = false;
00123         }
00124         void pink_led(){//Set Only PINK LED
00125             RED = 0; red_set = true;
00126             GREEN = 1; green_set = false;
00127             BLUE = 0; blue_set = true;
00128         }
00129         void cyan_led(){//Set Only CYAN LED
00130             RED = 1; red_set = false;
00131             GREEN = 0; green_set = true;
00132             BLUE = 0; blue_set = true;
00133         }
00134         void white_led(){//Set Only WHITE LED
00135             RED = 0; red_set = true;
00136             GREEN = 0; green_set = true;
00137             BLUE = 0; blue_set = true;
00138         }
00139         void all_led_off(){//Set All LED OFF
00140             RED = 1; red_set = false;
00141             GREEN = 1; green_set = false;
00142             BLUE = 1; blue_set = false;
00143         }
00144         void start_blink(float blink_interval){ //Start blinking on current LED using tikcer to avoid code blocking
00145             blink.attach(callback(this, &indicator::blink_effect), blink_interval);
00146         }
00147         void stop_blink(){ //Stop blinkink. Detach Ticker function call
00148             blink.detach();
00149             if(red_set) //Set last LED being used as ON.
00150                 RED = 0;
00151             if(green_set)
00152                 GREEN = 0;
00153             if(blue_set)
00154                 BLUE = 0;        
00155         }
00156 };
00157 
00158 indicator led_indicator(LED1, LED2, LED3); //Use K64f RGB LED for water pump
00159 indicator shield_led_indicator(D5, D9, D8); //Use Application Shield's RGB LED for MQ2 sensor
00160 
00161 class ultrasonic{ //Ultrasonic sensot for measuring depth of water in tank
00162     private:
00163         DigitalOut trigger;//DigitalOut trigger; //trigger pin for UltarSonic sensor
00164         InterruptIn echo; //Echo pin for water_level measurement. Uses as Interrupt to avoid code execution blocking.
00165         Ticker measure; //Ticker to trigger water_level measurement periodically.
00166         Timeout trigger_low; //Timeout interrupt to set trigger pin low after 10us of HIGH.
00167         Timer echoTimer; //Timer to get the time elapsed between echo sent and echo received back
00168         int echo_time_us; //Timer taken by echo to resturn abck to module.
00169         float interval; //Interval after which periodic measurement should start
00170         volatile bool measuring;
00171         FP<void,int> fp;
00172          
00173         void set_trigger_high(){ //Function to set Trigger Pin HIGH for 10us and set measuring = true
00174             measuring = true;
00175             trigger = ON;
00176             trigger_low.attach_us(callback(this, &ultrasonic::set_trigger_low), 10); //set trigger pin OFF after 10us   
00177         }
00178         
00179         void set_trigger_low(void){ //Function to set trigger pin LOW to fiish trigger after 10us. This will be called by low timer object.
00180             trigger = OFF;
00181         }
00182         
00183         void start_echo(void){//Function to start listening for echo back. This will start timer echoTimer. Will be based on Echo Pin RISE(or HIGH)
00184             if(!measuring) return; //avoid fluctuations on echo pin if any. Continue echo calculation only if measuring is TRUE.
00185             echoTimer.reset();
00186             echoTimer.start(); //Timer start since Echo pin is HIGH
00187         }
00188         void stop_echo(void){//Function to stop echoTimer after echo received back. Will be based on Echo Pin FALL(or LOW).
00189             if (!measuring)return; //avoid fluctuations on echo pin if any
00190             echoTimer.stop(); //stop timer since echo pin back to LOW
00191             echo_time_us = echoTimer.read_us(); //Calculate time for ultrasonic wave RTT.
00192             if(echo_time_us > 2000 || echo_time_us < 125)return; //ignore reading in case abnormally high or low RTT time
00193             measuring = false; //Marke measurement completed
00194             fp(echo_time_us / (29 * 2));
00195         }
00196 public: 
00197         ultrasonic(PinName _trigger, PinName _echo,float _interval):trigger(_trigger), echo(_echo){ //Constructor: initialize trigger(default value OFF) & echo pin
00198             interval = _interval;
00199             echo.rise(callback(this, &ultrasonic::start_echo)); //Attach function to Interrupt on Echo pin Rise
00200             echo.fall(callback(this, &ultrasonic::stop_echo)); //Attach function to Interrupt on Echo pin Fall
00201             measuring = false;
00202         }
00203 
00204         void start_measure(){ //function to Set Trigger Pin high repeatedly every 'time' seconds
00205             measure.attach(callback(this, &ultrasonic::set_trigger_high),interval);//ticker to trigger measurement with callback function
00206         }
00207         void stop_measure(void){ //Dettach from Ticker and stop measurements
00208             measuring = false;
00209             measure.detach();
00210         }
00211         void req_callBack(FP<void, int> _fp){
00212             fp = _fp;
00213         }
00214 };
00215 
00216 class pump{
00217     private:
00218         DigitalOut signal; //Signal for relay to set PUMP ON and OFF
00219         ultrasonic sensor; //Ultrasonic module objet for measuring depth of water
00220         volatile bool pump_on_request; //Bool to inform whether ita PUMP on request or only water depth meas.
00221         const int LEVEL_LOW = 4; //Low Water level defined as 4CM. Signifies Tank FULL.
00222         const int LEVEL_HIGH = 9; //High Water level defined as 11CM. Signifies Tank EMPTY.
00223         FP<void, int> fp; //Function pointer to receive call back with depth of water level in tank.
00224         
00225     public:        
00226         //Initialize Ultrasonic module with TRIG and ECHO pin along with measurement interval.
00227         pump(PinName _signal, PinName _trigger, PinName _echo, float _interval):signal(_signal), sensor(_trigger, _echo, _interval){ 
00228             pump_on_request = false;
00229             fp.attach(this, &pump::update_depth); //update_depth function will be called bu ultrasonic module when depth meas is completed.
00230             sensor.req_callBack(fp); //set call back.
00231         }
00232         void start_measurement(int interval){
00233             sensor.start_measure(); //Start depth measurements to calculate the water level.
00234         }
00235         void stop_measurement(){
00236             sensor.stop_measure(); //Start depth measurements to calculate the water level.
00237         }
00238     
00239         void pump_on(){ //Pump On request by User.
00240             pump_on_request = true; //bool to confirm that Pump On request is raised
00241             //sensor.start_measure(); //Start depth measurements to calculate the water level.
00242         }
00243         void pump_off(){ //Switch OFF the pump
00244             pump_on_request = false; //Set User request to flase.
00245             //sensor.stop_measure(); //Stop the ultrasonic measurements
00246             signal = OFF; //Relay Signal for pump OFF.
00247             PUMP_STATE = OFF;
00248         }
00249         
00250         void get_depth(){ //Only depth of water requried. no need to switch ON pump.
00251             if(signal == OFF) //If Already PUMP ONdont start measurement again. 
00252                 sensor.start_measure(); //Start Ultrasonic Measurements
00253         }
00254         
00255         void update_depth(int depth){ //Depth from ultrasonic is available
00256             WATER_LEVEL = depth;
00257             if(depth <= LEVEL_LOW) // set GREEN LED to inidicate the tank is FULL
00258                 led_indicator.green_led();
00259             else if(depth <= LEVEL_HIGH)// set Amber LED to inidicate the tank is more than HALF
00260                 led_indicator.amber_led();
00261             else 
00262                 led_indicator.red_led();// set RED LED to inidicate the tank is less than HALF
00263             
00264             if(depth <= LEVEL_LOW && signal == ON)//Tank FULL and PUMP ON. Switch OFF PUMP.
00265                 pump_off();
00266             else if(signal == OFF && pump_on_request && depth > LEVEL_HIGH ) //Pump is OFF and User have requested to on PUMP
00267                 signal = ON;  //Pump ON 
00268             else if(signal == ON && !pump_on_request) //If PUMP is ON but not requster by User.
00269                 pump_off(); //Pump OFF
00270             else if(signal == OFF && !pump_on_request) // Only for depth measurement. Pump on is not requested by user.
00271                 pump_off();
00272             PUMP_STATE = signal;
00273         }
00274 };
00275 
00276 class control{ //Control object for fan and alarm. Only Switch ON and OFF requried.
00277     private:
00278         DigitalOut signal; //Signal pin for object
00279     public:
00280         control(PinName _signal, int state):signal(_signal,state){ //Initialize Signal PIN with default state(ON or OFF)
00281         }
00282         
00283         void set_state(int state){ //Set the state of control
00284             if (state >= 1){ //Switch ON
00285                 signal = ON;
00286                 led_indicator.pink_led(); //Blink RED LED
00287             }
00288             else //Switch OFF
00289                 signal = OFF; //Set Control OFF
00290             //publish data
00291         }
00292         int get_state(){ //Get the state of the control
00293             return signal.read(); 
00294         }
00295 };
00296 
00297 class _temperature{ //Object for measuring current temperature and taking action accordingly
00298     private:
00299         LM75B temp_sensor; //LM75B temperature library used.
00300         float temperature_threshold_fan; // Threshold value for switching ON the FAN
00301         float temperature_threshold_alarm; // Threshold value for switching ON the ALARM
00302         Ticker periodic_meas; //Ticker for periodic measurement of the temperature
00303         control* alarm; //Poniter to control the alarm
00304         control* fan; //Poniter to control the fan
00305         void read_data(){ //Read the temperature from sensor
00306             TEMPERATURE = temp_sensor.temp(); //Use global variable TEMPERATURE which will be sent to ThingSpeak.
00307             if(TEMPERATURE >= temperature_threshold_alarm){ //Check if alarm threshold met.
00308                 alarm->set_state(ON); //Set Alarm ON
00309                 shield_led_indicator.red_led(); //Start RED LED Blinking
00310             }
00311             else if(TEMPERATURE >= temperature_threshold_fan){//Check if fan threshold met.
00312                 shield_led_indicator.amber_led();//Set Amber LED Blinking
00313                 fan->set_state(ON);//Set Alarm ON
00314                 FAN_STATE = ON;
00315             }
00316             else
00317                 shield_led_indicator.green_led();
00318         }
00319     public:
00320         _temperature(control* _alarm, control* _fan):temp_sensor(D14,D15){ //Initialize temp sensor with shield PINs D14, D15
00321             alarm = _alarm; //received object for alarm from Main function
00322             fan = _fan;//received object for fan from Main function
00323             temperature_threshold_fan = 30; //Fan threshold
00324             temperature_threshold_alarm = 40; //Alarm threshold
00325         }
00326         void start_measurement(int interval){ 
00327             periodic_meas.attach(callback(this, &_temperature::read_data), interval); //Start ticker based periodic temperature measurement
00328         }
00329         void stop_measurement(int interval){
00330             periodic_meas.detach();  //Stop ticker.
00331         }         
00332 };
00333 
00334 class _smoke_detector{ //Class to control the MQ2 Gas and Smoke detector
00335     private:
00336         MQ2 mq2; //Existing MQ2 library is used
00337         MQ2_data_t data; //data field to read the CO, SMOKE & GAS levels
00338         float CO_threshold_fan; //FAN Threshold for Carbon Monoxide
00339         float CO_threshold_alarm;//ALARM Threshold for Carbon Monoxide
00340         float GAS_threshold_fan; //FAN Threshold for combustible GASES
00341         float GAS_threshold_alarm; //ALARM Threshold for combustible GASES
00342         float SMOKE_threshold_fan; //FAN Threshold for SMOKE
00343         float SMOKE_threshold_alarm;//ALARM Threshold for SMOKE
00344         control* fan; //Poniter to control the fan
00345         control* alarm; //Poniter to control the alarm
00346         Ticker periodic_meas; //Ticker to complete periodic measurements
00347         
00348         void read_data(){ //Read the GAS/CO/SMOKE level from sensor
00349             mq2.read(&data);
00350             CO_level = mq2.readCO(); //CO Level
00351             GAS_level = mq2.readLPG(); //GAS Level
00352             SMOKE_level = mq2.readSmoke(); //SMOKE Level
00353             //Check if alarm threhold is crossed for any measurements
00354             if(data.co >= CO_threshold_alarm || data.lpg >= GAS_threshold_alarm || data.smoke >= SMOKE_threshold_alarm){ 
00355                 shield_led_indicator.red_led(); //Set RED Blinker
00356                 alarm->set_state(ON); //Set alarm ON
00357             }
00358             //Check if fan threhold is crossed for any measurements
00359             else if(data.co >= CO_threshold_fan || data.lpg >= GAS_threshold_fan || data.smoke >= SMOKE_threshold_fan){ 
00360                 shield_led_indicator.amber_led(); //Set AMBER LED
00361                 fan->set_state(ON); //Set FAN ON
00362             }
00363         }
00364         
00365     public:
00366         //Initialize MQ2 sensor using Analog pin.
00367         _smoke_detector(PinName _analog, control* _alarm, control* _fan):mq2(_analog){ 
00368             mq2.begin(); //mq2 begin method to Calibrate sensor
00369             fan = _fan; //Fan control object from Main function
00370             alarm = _alarm;//Alarm control object from Main function
00371             CO_threshold_alarm = 3;
00372             CO_threshold_fan = 2;
00373             GAS_threshold_fan = 2;
00374             GAS_threshold_alarm = 3;
00375             SMOKE_threshold_alarm = 3;
00376             SMOKE_threshold_fan = 2;
00377         }
00378                
00379         void start_measurement(int interval){ //Start Ticker based periodic measurements
00380             periodic_meas.attach(callback(this, &_smoke_detector::read_data), interval);
00381         }
00382         void stop_measurement(){//Stop Ticker based periodic measurements
00383             periodic_meas.detach();
00384         }  
00385 };
00386 
00387 int arrivedcount = 0;
00388 
00389 pump water_pump(PUMP,TRIGGER, ECHO, 1); //Water Pump object
00390 control alarm(ALARM_SIG, ON); //Alarm Pump object
00391 control fan(FAN_SIG, OFF); //Fan object
00392 _smoke_detector smoke_detector(MQ2_SIG, &alarm, &fan); //Smoke Detector object
00393 _temperature temperature(&alarm, &fan);//Uses fixed PIN on shiled- D14, D15. So no need to pass from main
00394 NetworkInterface* network = easy_connect(true); //Network object. Creates ethernt conncetion
00395 MQTTNetwork mqttNetwork(network); //MQTTNetwork object. Takes Network object as input for connection over ethernet
00396 MQTT::Client<MQTTNetwork, Countdown> client(mqttNetwork); //MQTT Client for Connction with broker, Subscribe and Publsih service.
00397 
00398  
00399 void field1_pump_state(MQTT::MessageData& md) //Callback functionf for Field1 from thingspeak.
00400 {
00401     MQTT::Message &message = md.message; //Message recived using MQTT
00402     logMessage("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
00403     logMessage("Message Field1 %s\r\n", message.payload); //Message Payload
00404     if(strtol((char *)message.payload, '\0', 10) == 1){  //convert to int and check if power ON command
00405         logMessage("Water Pump ON\r\n"); 
00406         water_pump.stop_measurement();
00407         water_pump.start_measurement(2); //Start Water Pump measurements. At intervals of 2s. This is small value because for test purpose very small tank is being used. In real life this could be in mins.
00408         water_pump.pump_on(); //Start the pump for 1st time
00409     }
00410     else{
00411         logMessage("Water Pump OFF\r\n"); 
00412         water_pump.pump_off(); //Power off pump otherwise
00413     }
00414 }
00415 
00416 void field2_fan_state(MQTT::MessageData& md)//Callback functionf for Field2 from thingspeak.
00417 {
00418     MQTT::Message &message = md.message; //Message recived using MQTT
00419     logMessage("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
00420     logMessage("Message Field2 %s\r\n", message.payload);//Message Payload
00421     if(strtol((char *)message.payload, '\0', 10) == 1){//convert to int and check if power ON command
00422         logMessage("FAN ON\r\n");
00423         fan.set_state(OFF);//Power On FAN
00424     }
00425     else{
00426         logMessage("FAN OFF\r\n");
00427         fan.set_state(ON);//Power off fan otherwise
00428     }
00429 }
00430 
00431 void field3_alarm_state(MQTT::MessageData& md)
00432 {
00433     MQTT::Message &message = md.message;
00434     logMessage("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
00435     logMessage("Message Field3 %s\r\n", message.payload);
00436 //    RED = strtol((char *)message.payload, '\0', 10);
00437     if(strtol((char *)message.payload, '\0', 10) == 1){//convert to int and check if power ON command
00438         logMessage("Alarm ON\r\n");;//Power On Alarm. This scenario should never occur,
00439         alarm.set_state(ON);
00440     }
00441     else{
00442         logMessage("Alarm OFF\r\n");
00443         alarm.set_state(OFF); //Power off Alarm otherwise
00444     }
00445     ++arrivedcount;
00446 }
00447 
00448 void publish_field1(){ //Function to publish the values to ThingSpeak fields
00449     static int last_update = -1;
00450     if(PUMP_STATE == last_update)
00451         return; //Ignore unncessary update in case no chnage in value.
00452     last_update = PUMP_STATE;
00453     logMessage("Publish Routine\r\n");
00454     int rc = 0;
00455     MQTT::Message message; 
00456     char* topic = "channels/1608275/publish";//Topic contaning Channel ID
00457     char buf[100]; //Buffer for storing data
00458     sprintf(buf, "field1=%d&status=MQTTPUBLISH",PUMP_STATE);
00459     message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
00460     message.retained = false;
00461     message.dup = false;
00462     message.payload = (void*)buf; //Copy buffer to Message Payload
00463     message.payloadlen = strlen(buf)+1;
00464     rc = client.publish(topic, message); //Publsih data using MQTT client
00465     logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
00466 }
00467 
00468 void publish_field2(){ //Function to publish the values to ThingSpeak fields
00469     static int last_update = -1;
00470     if(FAN_STATE == last_update)
00471         return; //Ignore unncessary update in case no chnage in value.
00472     last_update = FAN_STATE;
00473     logMessage("Publish Routine\r\n");
00474     int rc = 0;
00475     MQTT::Message message; 
00476     char* topic = "channels/1608275/publish";//Topic contaning Channel ID
00477     char buf[100]; //Buffer for storing data
00478     sprintf(buf, "field2=%d&status=MQTTPUBLISH",FAN_STATE);
00479     message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
00480     message.retained = false;
00481     message.dup = false;
00482     message.payload = (void*)buf; //Copy buffer to Message Payload
00483     message.payloadlen = strlen(buf)+1;
00484     rc = client.publish(topic, message); //Publsih data using MQTT client
00485     logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
00486 }
00487 
00488 void publish_field3(){ //Function to publish the values to ThingSpeak fields
00489     static int last_update = -1;
00490     if(ALARM_STATE == last_update)
00491         return; //Ignore unncessary update in case no chnage in value.
00492     last_update = ALARM_STATE;
00493     logMessage("Publish Routine\r\n");
00494     int rc = 0;
00495     MQTT::Message message; 
00496     char* topic = "channels/1608275/publish";//Topic contaning Channel ID
00497     char buf[100]; //Buffer for storing data
00498     sprintf(buf, "field3=%d&status=MQTTPUBLISH",ALARM_STATE);
00499     message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
00500     message.retained = false;
00501     message.dup = false;
00502     message.payload = (void*)buf; //Copy buffer to Message Payload
00503     message.payloadlen = strlen(buf)+1;
00504     rc = client.publish(topic, message); //Publsih data using MQTT client
00505     logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
00506 }
00507 
00508 void publish_field4(){ //Function to publish the values to ThingSpeak fields
00509     static int last_update = -1;
00510     last_update = WATER_LEVEL;
00511     //logMessage("Publish Routine\r\n");
00512     int rc = 0;
00513     MQTT::Message message; 
00514     char* topic = "channels/1608275/publish";//Topic contaning Channel ID
00515     char buf[100]; //Buffer for storing data
00516     //field5=%0.1f&field6=%0.1f&field7=%0.1f&field8=%0.1f&
00517     sprintf(buf, "field4=%d&field1=%d&field2=%d&field3=%d&status=MQTTPUBLISH",WATER_LEVEL, PUMP_STATE,FAN_STATE,ALARM_STATE);
00518     message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
00519     message.retained = false;
00520     message.dup = false;
00521     message.payload = (void*)buf; //Copy buffer to Message Payload
00522     message.payloadlen = strlen(buf)+1;
00523     rc = client.publish(topic, message); //Publsih data using MQTT client
00524     //logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
00525 }
00526 
00527 void publish_field5(){ //Function to publish the values to ThingSpeak fields
00528     static int last_update = -1;
00529     last_update = GAS_level;
00530     //logMessage("Publish Routine\r\n");
00531     int rc = 0;
00532     MQTT::Message message; 
00533     char* topic = "channels/1608275/publish";//Topic contaning Channel ID
00534     char buf[100]; //Buffer for storing data
00535     sprintf(buf, "field5=%d&field6=%d&field7=%d&field8=%d&status=MQTTPUBLISH",GAS_level, CO_level, SMOKE_level, TEMPERATURE);
00536     message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
00537     message.retained = false;
00538     message.dup = false;
00539     message.payload = (void*)buf; //Copy buffer to Message Payload
00540     message.payloadlen = strlen(buf)+1;
00541     rc = client.publish(topic, message); //Publsih data using MQTT client
00542     //logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
00543 }
00544 
00545 void publish_field6(){ //Function to publish the values to ThingSpeak fields
00546     static int last_update = -1;
00547     if(CO_level == last_update)
00548         return; //Ignore unncessary update in case no chnage in value.
00549     last_update = CO_level;
00550     logMessage("Publish Routine\r\n");
00551     int rc = 0;
00552     MQTT::Message message; 
00553     char* topic = "channels/1608275/publish";//Topic contaning Channel ID
00554     char buf[100]; //Buffer for storing data
00555     sprintf(buf, "field6=%d&status=MQTTPUBLISH",CO_level);
00556     message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
00557     message.retained = false;
00558     message.dup = false;
00559     message.payload = (void*)buf; //Copy buffer to Message Payload
00560     message.payloadlen = strlen(buf)+1;
00561     rc = client.publish(topic, message); //Publsih data using MQTT client
00562     logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
00563 }
00564 
00565 void publish_field8(){ //Function to publish the values to ThingSpeak fields
00566     static int last_update = -1;
00567     if(TEMPERATURE == last_update)
00568         return; //Ignore unncessary update in case no chnage in value.
00569     last_update = TEMPERATURE;
00570     logMessage("Publish Routine\r\n");
00571     int rc = 0;
00572     MQTT::Message message; 
00573     char* topic = "channels/1608275/publish";//Topic contaning Channel ID
00574     char buf[100]; //Buffer for storing data
00575     sprintf(buf, "field8=%d&status=MQTTPUBLISH",TEMPERATURE);
00576     message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
00577     message.retained = false;
00578     message.dup = false;
00579     message.payload = (void*)buf; //Copy buffer to Message Payload
00580     message.payloadlen = strlen(buf)+1;
00581     rc = client.publish(topic, message); //Publsih data using MQTT client
00582     logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
00583 }
00584 
00585 void publish_field7(){ //Function to publish the values to ThingSpeak fields
00586     static int last_update = -1;
00587     if(SMOKE_level == last_update)
00588         return; //Ignore unncessary update in case no chnage in value.
00589     last_update = SMOKE_level;
00590     logMessage("Publish Routine\r\n");
00591     int rc = 0;
00592     MQTT::Message message; 
00593     char* topic = "channels/1608275/publish";//Topic contaning Channel ID
00594     char buf[100]; //Buffer for storing data
00595     sprintf(buf, "field7=%d&status=MQTTPUBLISH",SMOKE_level);
00596     message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
00597     message.retained = false;
00598     message.dup = false;
00599     message.payload = (void*)buf; //Copy buffer to Message Payload
00600     message.payloadlen = strlen(buf)+1;
00601     rc = client.publish(topic, message); //Publsih data using MQTT client
00602     logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
00603 }
00604 
00605 int main(int argc, char* argv[])
00606 {
00607     smoke_detector.start_measurement(2); //Start periodic Smoke detector measurements at intervals of 10s
00608    temperature.start_measurement(20); //Start periodic Temperaturre readings. At interval of 20s
00609    water_pump.start_measurement(2); //Start Water Pump measurements. At intervals of 2s. This is small value because for test purpose very small tank is being used. In real life this could be in mins.
00610    water_pump.pump_on(); //Start the pump for 1st time
00611     float version = 0.6;
00612     logMessage("HelloMQTT: version is %.2f\r\n", version);
00613     int ret = 0;
00614     
00615     if (!network) { //Check if ethernet connection successful
00616         return -1;
00617     }
00618 
00619     const char* hostname = "mqtt3.thingspeak.com"; //Thingspeak host name
00620     int port = 1883; //MQTT default port number
00621     logMessage("Connecting to %s:%d\r\n", hostname, port);
00622     int rc = mqttNetwork.connect(hostname, port); //Attempt to connect to MQTT host
00623     if (rc != 0)
00624         logMessage("rc- TCP connect: %d\r\n", rc);
00625 
00626     MQTTPacket_connectData data = MQTTPacket_connectData_initializer; //Build MQTT Client connection data
00627     data.MQTTVersion = 3; //MQTT Version
00628     data.clientID.cstring = "FA8KKzQ1CDY6EjENATYTESc"; //Thingspeak MQTT Client ID
00629     data.username.cstring = "FA8KKzQ1CDY6EjENATYTESc";//Thingspeak MQTT Username
00630     data.password.cstring = "vVdiiGscVIGLEgQIZ250Unxc";//Thingspeak MQTT Password
00631     
00632     
00633     if ((rc = client.connect(data)) != 0) //Connect Client
00634         logMessage("rc- connect: %d\r\n", rc);
00635         
00636     char* topic = "channels/1608275/subscribe/fields/field1"; //Subscribe for field1
00637     if ((rc = client.subscribe(topic, MQTT::QOS0, field1_pump_state)) != 0)//Use field1_pump_state function pointer as call back function
00638         logMessage("rc1: %d\r\n", rc);
00639     
00640     topic = "channels/1608275/subscribe/fields/field2";
00641     if ((rc = client.subscribe(topic, MQTT::QOS0, field2_fan_state)) != 0)//Use field2_fan_state function pointer as call back function
00642         logMessage("rc2: %d\r\n", rc);
00643 
00644     topic = "channels/1608275/subscribe/fields/field3";
00645     if ((rc = client.subscribe(topic, MQTT::QOS0, field3_alarm_state)) != 0)//Use field3_alarm_state function pointer as call back function
00646         logMessage("rc: %d\r\n", rc);
00647     
00648     while (1){
00649         logMessage("GAS: %d, CO: %d, Smoke: %d, TEMP = %0.1f, Water = %d", GAS_level, CO_level, SMOKE_level, TEMPERATURE, WATER_LEVEL);
00650         publish_field4();
00651         wait(5);
00652         publish_field5();
00653         wait(5);
00654         client.yield(50);
00655 
00656     }
00657     if ((rc = client.unsubscribe(topic)) != 0)
00658         logMessage("rc from unsubscribe was %d\r\n", rc);
00659     if ((rc = client.disconnect()) != 0)
00660         logMessage("rc from disconnect was %d\r\n", rc);
00661     mqttNetwork.disconnect();
00662     logMessage("Version %.2f: finish %d msgs\r\n", version, arrivedcount);
00663     return 0;
00664 }