Lovkesh Chauhan / Mbed OS SmartKitchen_MiniProject

Dependencies:   C12832 LM75B MQ2 MQTT

Files at this revision

API Documentation at this revision

Comitter:
lovkesh_chauhan
Date:
Tue Jan 04 11:10:00 2022 +0000
Parent:
23:e38aaf532823
Commit message:
Project Code

Changed in this revision

LM75B.lib Show annotated file Show diff for this revision Revisions of this file
MQ2.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LM75B.lib	Tue Jan 04 11:10:00 2022 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/neilt6/code/LM75B/#7ac462ba84ac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQ2.lib	Tue Jan 04 11:10:00 2022 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/lovkesh_chauhan/code/MQ2/#54c2e1d69508
--- a/main.cpp	Tue Jan 16 13:41:29 2018 +0000
+++ b/main.cpp	Tue Jan 04 11:10:00 2022 +0000
@@ -26,7 +26,7 @@
  */
 
  // change this to 1 to output messages to LCD instead of serial
-#define USE_LCD 0
+#define USE_LCD 1
 
 #if USE_LCD
 #include "C12832.h"
@@ -34,7 +34,7 @@
 // the actual pins are defined in mbed_app.json and can be overridden per target
 C12832 lcd(LCD_MOSI, LCD_SCK, LCD_MISO, LCD_A0, LCD_NCS);
 
-#define logMessage lcd.cls();lcd.printf
+#define logMessage lcd.cls();lcd.locate(0,0);lcd.printf
 
 #else
 
@@ -42,98 +42,636 @@
 
 #endif
 
-#define MQTTCLIENT_QOS2 1
+#define MQTTCLIENT_QOS2 0
+
+#include "easy-connect.h" //Ethernet Connection library
+#include "MQTTNetwork.h" //MQTT Connection
+#include "MQTTmbed.h"  //MQTT Connection
+#include "MQTTClient.h" //MQTT Connection
+#include "string.h";
+
+#include "mbed.h" 
+//#include "platform/mbed_thread.h"
+#include "FP.h" //For function pointer usage
+#include "MQ2.h" //Smoke and Gas detector library
+#include "LM75B.h" //Temperature sensor
+
+#define ON 1 
+#define OFF 0
+
+#define PUMP PTC1 //Relay Signal for controlling pump
+#define TRIGGER PTB18 //Trigger pin for ultrasonic sensor
+#define ECHO PTB19 //Echo pin for ultrasonic sensor
+#define MQ2_SIG PTC10 //Smoke and Gas sensor output pin
+#define ALARM_SIG PTC8 //Alarm Signal Pin
+#define FAN_SIG PTC9 //Fan signal pin
+
+//Global variables to update the ThingSpeak channel fields.
+int WATER_LEVEL = 0; 
+float CO_level = 0;
+float SMOKE_level = 0;
+float GAS_level = 0;
+float TEMPERATURE = 0;
+int FAN_STATE = 0;
+int ALARM_STATE = 0;
+int PUMP_STATE = 0;
+
+class indicator{ //class to allow easy usage of RGB LED 
+    private:
+        DigitalOut RED; //LED1
+        DigitalOut BLUE; //LED2
+        DigitalOut GREEN; //LED3
+        Ticker blink; //Ticker to start blinking
+        bool red_set; //bool to check if RED is ON
+        bool green_set; //bool to check if GREEN is ON
+        bool blue_set; //bool to check if BLUE is ON
+        
+        void blink_effect(){ //function to flip LEDs to generate blink effect
+            if(red_set)
+                RED = !RED;
+            if(green_set)
+                GREEN = !GREEN;
+            if(blue_set)
+                BLUE = !BLUE;
+        }
+ 
+    public:
+         indicator(PinName _LED1, PinName _LED2, PinName _LED3):RED(_LED1, 1), GREEN(_LED2, 1), BLUE(_LED3, 1){ //Initialize RGB LEDs with requried PINS.
+             red_set = false; green_set = false; blue_set = false; //All LED intially OFF.
+        }
+        
+        void red_led(){ //Set Only RED LED
+            RED = 0; red_set = true; 
+            GREEN = 1; green_set = false;
+            BLUE = 1; blue_set = false;
+        }
+        
+        void green_led(){ //Set Only GREEN LED
+            RED = 1; red_set = false;
+            GREEN = 0; green_set = true;
+            BLUE = 1; blue_set = false;
+        }
+        void blue_led(){//Set Only BLUE LED
+            RED = 1; red_set = false;
+            GREEN = 1; green_set = false;
+            BLUE = 0; blue_set = true;
+        }
+        void amber_led(){//Set Only AMBER LED
+            RED = 0; red_set = true;
+            GREEN = 0; green_set = true;
+            BLUE = 1; blue_set = false;
+        }
+        void pink_led(){//Set Only PINK LED
+            RED = 0; red_set = true;
+            GREEN = 1; green_set = false;
+            BLUE = 0; blue_set = true;
+        }
+        void cyan_led(){//Set Only CYAN LED
+            RED = 1; red_set = false;
+            GREEN = 0; green_set = true;
+            BLUE = 0; blue_set = true;
+        }
+        void white_led(){//Set Only WHITE LED
+            RED = 0; red_set = true;
+            GREEN = 0; green_set = true;
+            BLUE = 0; blue_set = true;
+        }
+        void all_led_off(){//Set All LED OFF
+            RED = 1; red_set = false;
+            GREEN = 1; green_set = false;
+            BLUE = 1; blue_set = false;
+        }
+        void start_blink(float blink_interval){ //Start blinking on current LED using tikcer to avoid code blocking
+            blink.attach(callback(this, &indicator::blink_effect), blink_interval);
+        }
+        void stop_blink(){ //Stop blinkink. Detach Ticker function call
+            blink.detach();
+            if(red_set) //Set last LED being used as ON.
+                RED = 0;
+            if(green_set)
+                GREEN = 0;
+            if(blue_set)
+                BLUE = 0;        
+        }
+};
+
+indicator led_indicator(LED1, LED2, LED3); //Use K64f RGB LED for water pump
+indicator shield_led_indicator(D5, D9, D8); //Use Application Shield's RGB LED for MQ2 sensor
+
+class ultrasonic{ //Ultrasonic sensot for measuring depth of water in tank
+    private:
+        DigitalOut trigger;//DigitalOut trigger; //trigger pin for UltarSonic sensor
+        InterruptIn echo; //Echo pin for water_level measurement. Uses as Interrupt to avoid code execution blocking.
+        Ticker measure; //Ticker to trigger water_level measurement periodically.
+        Timeout trigger_low; //Timeout interrupt to set trigger pin low after 10us of HIGH.
+        Timer echoTimer; //Timer to get the time elapsed between echo sent and echo received back
+        int echo_time_us; //Timer taken by echo to resturn abck to module.
+        float interval; //Interval after which periodic measurement should start
+        volatile bool measuring;
+        FP<void,int> fp;
+         
+        void set_trigger_high(){ //Function to set Trigger Pin HIGH for 10us and set measuring = true
+            measuring = true;
+            trigger = ON;
+            trigger_low.attach_us(callback(this, &ultrasonic::set_trigger_low), 10); //set trigger pin OFF after 10us   
+        }
+        
+        void set_trigger_low(void){ //Function to set trigger pin LOW to fiish trigger after 10us. This will be called by low timer object.
+            trigger = OFF;
+        }
+        
+        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)
+            if(!measuring) return; //avoid fluctuations on echo pin if any. Continue echo calculation only if measuring is TRUE.
+            echoTimer.reset();
+            echoTimer.start(); //Timer start since Echo pin is HIGH
+        }
+        void stop_echo(void){//Function to stop echoTimer after echo received back. Will be based on Echo Pin FALL(or LOW).
+            if (!measuring)return; //avoid fluctuations on echo pin if any
+            echoTimer.stop(); //stop timer since echo pin back to LOW
+            echo_time_us = echoTimer.read_us(); //Calculate time for ultrasonic wave RTT.
+            if(echo_time_us > 2000 || echo_time_us < 125)return; //ignore reading in case abnormally high or low RTT time
+            measuring = false; //Marke measurement completed
+            fp(echo_time_us / (29 * 2));
+        }
+public: 
+        ultrasonic(PinName _trigger, PinName _echo,float _interval):trigger(_trigger), echo(_echo){ //Constructor: initialize trigger(default value OFF) & echo pin
+            interval = _interval;
+            echo.rise(callback(this, &ultrasonic::start_echo)); //Attach function to Interrupt on Echo pin Rise
+            echo.fall(callback(this, &ultrasonic::stop_echo)); //Attach function to Interrupt on Echo pin Fall
+            measuring = false;
+        }
+
+        void start_measure(){ //function to Set Trigger Pin high repeatedly every 'time' seconds
+            measure.attach(callback(this, &ultrasonic::set_trigger_high),interval);//ticker to trigger measurement with callback function
+        }
+        void stop_measure(void){ //Dettach from Ticker and stop measurements
+            measuring = false;
+            measure.detach();
+        }
+        void req_callBack(FP<void, int> _fp){
+            fp = _fp;
+        }
+};
 
-#include "easy-connect.h"
-#include "MQTTNetwork.h"
-#include "MQTTmbed.h"
-#include "MQTTClient.h"
+class pump{
+    private:
+        DigitalOut signal; //Signal for relay to set PUMP ON and OFF
+        ultrasonic sensor; //Ultrasonic module objet for measuring depth of water
+        volatile bool pump_on_request; //Bool to inform whether ita PUMP on request or only water depth meas.
+        const int LEVEL_LOW = 4; //Low Water level defined as 4CM. Signifies Tank FULL.
+        const int LEVEL_HIGH = 9; //High Water level defined as 11CM. Signifies Tank EMPTY.
+        FP<void, int> fp; //Function pointer to receive call back with depth of water level in tank.
+        
+    public:        
+        //Initialize Ultrasonic module with TRIG and ECHO pin along with measurement interval.
+        pump(PinName _signal, PinName _trigger, PinName _echo, float _interval):signal(_signal), sensor(_trigger, _echo, _interval){ 
+            pump_on_request = false;
+            fp.attach(this, &pump::update_depth); //update_depth function will be called bu ultrasonic module when depth meas is completed.
+            sensor.req_callBack(fp); //set call back.
+        }
+        void start_measurement(int interval){
+            sensor.start_measure(); //Start depth measurements to calculate the water level.
+        }
+        void stop_measurement(){
+            sensor.stop_measure(); //Start depth measurements to calculate the water level.
+        }
+    
+        void pump_on(){ //Pump On request by User.
+            pump_on_request = true; //bool to confirm that Pump On request is raised
+            //sensor.start_measure(); //Start depth measurements to calculate the water level.
+        }
+        void pump_off(){ //Switch OFF the pump
+            pump_on_request = false; //Set User request to flase.
+            //sensor.stop_measure(); //Stop the ultrasonic measurements
+            signal = OFF; //Relay Signal for pump OFF.
+            PUMP_STATE = OFF;
+        }
+        
+        void get_depth(){ //Only depth of water requried. no need to switch ON pump.
+            if(signal == OFF) //If Already PUMP ONdont start measurement again. 
+                sensor.start_measure(); //Start Ultrasonic Measurements
+        }
+        
+        void update_depth(int depth){ //Depth from ultrasonic is available
+            WATER_LEVEL = depth;
+            if(depth <= LEVEL_LOW) // set GREEN LED to inidicate the tank is FULL
+                led_indicator.green_led();
+            else if(depth <= LEVEL_HIGH)// set Amber LED to inidicate the tank is more than HALF
+                led_indicator.amber_led();
+            else 
+                led_indicator.red_led();// set RED LED to inidicate the tank is less than HALF
+            
+            if(depth <= LEVEL_LOW && signal == ON)//Tank FULL and PUMP ON. Switch OFF PUMP.
+                pump_off();
+            else if(signal == OFF && pump_on_request && depth > LEVEL_HIGH ) //Pump is OFF and User have requested to on PUMP
+                signal = ON;  //Pump ON 
+            else if(signal == ON && !pump_on_request) //If PUMP is ON but not requster by User.
+                pump_off(); //Pump OFF
+            else if(signal == OFF && !pump_on_request) // Only for depth measurement. Pump on is not requested by user.
+                pump_off();
+            PUMP_STATE = signal;
+        }
+};
+
+class control{ //Control object for fan and alarm. Only Switch ON and OFF requried.
+    private:
+        DigitalOut signal; //Signal pin for object
+    public:
+        control(PinName _signal, int state):signal(_signal,state){ //Initialize Signal PIN with default state(ON or OFF)
+        }
+        
+        void set_state(int state){ //Set the state of control
+            if (state >= 1){ //Switch ON
+                signal = ON;
+                led_indicator.pink_led(); //Blink RED LED
+            }
+            else //Switch OFF
+                signal = OFF; //Set Control OFF
+            //publish data
+        }
+        int get_state(){ //Get the state of the control
+            return signal.read(); 
+        }
+};
+
+class _temperature{ //Object for measuring current temperature and taking action accordingly
+    private:
+        LM75B temp_sensor; //LM75B temperature library used.
+        float temperature_threshold_fan; // Threshold value for switching ON the FAN
+        float temperature_threshold_alarm; // Threshold value for switching ON the ALARM
+        Ticker periodic_meas; //Ticker for periodic measurement of the temperature
+        control* alarm; //Poniter to control the alarm
+        control* fan; //Poniter to control the fan
+        void read_data(){ //Read the temperature from sensor
+            TEMPERATURE = temp_sensor.temp(); //Use global variable TEMPERATURE which will be sent to ThingSpeak.
+            if(TEMPERATURE >= temperature_threshold_alarm){ //Check if alarm threshold met.
+                alarm->set_state(ON); //Set Alarm ON
+                shield_led_indicator.red_led(); //Start RED LED Blinking
+            }
+            else if(TEMPERATURE >= temperature_threshold_fan){//Check if fan threshold met.
+                shield_led_indicator.amber_led();//Set Amber LED Blinking
+                fan->set_state(ON);//Set Alarm ON
+                FAN_STATE = ON;
+            }
+            else
+                shield_led_indicator.green_led();
+        }
+    public:
+        _temperature(control* _alarm, control* _fan):temp_sensor(D14,D15){ //Initialize temp sensor with shield PINs D14, D15
+            alarm = _alarm; //received object for alarm from Main function
+            fan = _fan;//received object for fan from Main function
+            temperature_threshold_fan = 30; //Fan threshold
+            temperature_threshold_alarm = 40; //Alarm threshold
+        }
+        void start_measurement(int interval){ 
+            periodic_meas.attach(callback(this, &_temperature::read_data), interval); //Start ticker based periodic temperature measurement
+        }
+        void stop_measurement(int interval){
+            periodic_meas.detach();  //Stop ticker.
+        }         
+};
+
+class _smoke_detector{ //Class to control the MQ2 Gas and Smoke detector
+    private:
+        MQ2 mq2; //Existing MQ2 library is used
+        MQ2_data_t data; //data field to read the CO, SMOKE & GAS levels
+        float CO_threshold_fan; //FAN Threshold for Carbon Monoxide
+        float CO_threshold_alarm;//ALARM Threshold for Carbon Monoxide
+        float GAS_threshold_fan; //FAN Threshold for combustible GASES
+        float GAS_threshold_alarm; //ALARM Threshold for combustible GASES
+        float SMOKE_threshold_fan; //FAN Threshold for SMOKE
+        float SMOKE_threshold_alarm;//ALARM Threshold for SMOKE
+        control* fan; //Poniter to control the fan
+        control* alarm; //Poniter to control the alarm
+        Ticker periodic_meas; //Ticker to complete periodic measurements
+        
+        void read_data(){ //Read the GAS/CO/SMOKE level from sensor
+            mq2.read(&data);
+            CO_level = mq2.readCO(); //CO Level
+            GAS_level = mq2.readLPG(); //GAS Level
+            SMOKE_level = mq2.readSmoke(); //SMOKE Level
+            //Check if alarm threhold is crossed for any measurements
+            if(data.co >= CO_threshold_alarm || data.lpg >= GAS_threshold_alarm || data.smoke >= SMOKE_threshold_alarm){ 
+                shield_led_indicator.red_led(); //Set RED Blinker
+                alarm->set_state(ON); //Set alarm ON
+            }
+            //Check if fan threhold is crossed for any measurements
+            else if(data.co >= CO_threshold_fan || data.lpg >= GAS_threshold_fan || data.smoke >= SMOKE_threshold_fan){ 
+                shield_led_indicator.amber_led(); //Set AMBER LED
+                fan->set_state(ON); //Set FAN ON
+            }
+        }
+        
+    public:
+        //Initialize MQ2 sensor using Analog pin.
+        _smoke_detector(PinName _analog, control* _alarm, control* _fan):mq2(_analog){ 
+            mq2.begin(); //mq2 begin method to Calibrate sensor
+            fan = _fan; //Fan control object from Main function
+            alarm = _alarm;//Alarm control object from Main function
+            CO_threshold_alarm = 3;
+            CO_threshold_fan = 2;
+            GAS_threshold_fan = 2;
+            GAS_threshold_alarm = 3;
+            SMOKE_threshold_alarm = 3;
+            SMOKE_threshold_fan = 2;
+        }
+               
+        void start_measurement(int interval){ //Start Ticker based periodic measurements
+            periodic_meas.attach(callback(this, &_smoke_detector::read_data), interval);
+        }
+        void stop_measurement(){//Stop Ticker based periodic measurements
+            periodic_meas.detach();
+        }  
+};
 
 int arrivedcount = 0;
 
+pump water_pump(PUMP,TRIGGER, ECHO, 1); //Water Pump object
+control alarm(ALARM_SIG, ON); //Alarm Pump object
+control fan(FAN_SIG, OFF); //Fan object
+_smoke_detector smoke_detector(MQ2_SIG, &alarm, &fan); //Smoke Detector object
+_temperature temperature(&alarm, &fan);//Uses fixed PIN on shiled- D14, D15. So no need to pass from main
+NetworkInterface* network = easy_connect(true); //Network object. Creates ethernt conncetion
+MQTTNetwork mqttNetwork(network); //MQTTNetwork object. Takes Network object as input for connection over ethernet
+MQTT::Client<MQTTNetwork, Countdown> client(mqttNetwork); //MQTT Client for Connction with broker, Subscribe and Publsih service.
 
-void messageArrived(MQTT::MessageData& md)
+ 
+void field1_pump_state(MQTT::MessageData& md) //Callback functionf for Field1 from thingspeak.
+{
+    MQTT::Message &message = md.message; //Message recived using MQTT
+    logMessage("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
+    logMessage("Message Field1 %s\r\n", message.payload); //Message Payload
+    if(strtol((char *)message.payload, '\0', 10) == 1){  //convert to int and check if power ON command
+        logMessage("Water Pump ON\r\n"); 
+        water_pump.stop_measurement();
+        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.
+        water_pump.pump_on(); //Start the pump for 1st time
+    }
+    else{
+        logMessage("Water Pump OFF\r\n"); 
+        water_pump.pump_off(); //Power off pump otherwise
+    }
+}
+
+void field2_fan_state(MQTT::MessageData& md)//Callback functionf for Field2 from thingspeak.
+{
+    MQTT::Message &message = md.message; //Message recived using MQTT
+    logMessage("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
+    logMessage("Message Field2 %s\r\n", message.payload);//Message Payload
+    if(strtol((char *)message.payload, '\0', 10) == 1){//convert to int and check if power ON command
+        logMessage("FAN ON\r\n");
+        fan.set_state(OFF);//Power On FAN
+    }
+    else{
+        logMessage("FAN OFF\r\n");
+        fan.set_state(ON);//Power off fan otherwise
+    }
+}
+
+void field3_alarm_state(MQTT::MessageData& md)
 {
     MQTT::Message &message = md.message;
     logMessage("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
-    logMessage("Payload %.*s\r\n", message.payloadlen, (char*)message.payload);
+    logMessage("Message Field3 %s\r\n", message.payload);
+//    RED = strtol((char *)message.payload, '\0', 10);
+    if(strtol((char *)message.payload, '\0', 10) == 1){//convert to int and check if power ON command
+        logMessage("Alarm ON\r\n");;//Power On Alarm. This scenario should never occur,
+        alarm.set_state(ON);
+    }
+    else{
+        logMessage("Alarm OFF\r\n");
+        alarm.set_state(OFF); //Power off Alarm otherwise
+    }
     ++arrivedcount;
 }
 
+void publish_field1(){ //Function to publish the values to ThingSpeak fields
+    static int last_update = -1;
+    if(PUMP_STATE == last_update)
+        return; //Ignore unncessary update in case no chnage in value.
+    last_update = PUMP_STATE;
+    logMessage("Publish Routine\r\n");
+    int rc = 0;
+    MQTT::Message message; 
+    char* topic = "channels/1608275/publish";//Topic contaning Channel ID
+    char buf[100]; //Buffer for storing data
+    sprintf(buf, "field1=%d&status=MQTTPUBLISH",PUMP_STATE);
+    message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf; //Copy buffer to Message Payload
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message); //Publsih data using MQTT client
+    logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
+}
+
+void publish_field2(){ //Function to publish the values to ThingSpeak fields
+    static int last_update = -1;
+    if(FAN_STATE == last_update)
+        return; //Ignore unncessary update in case no chnage in value.
+    last_update = FAN_STATE;
+    logMessage("Publish Routine\r\n");
+    int rc = 0;
+    MQTT::Message message; 
+    char* topic = "channels/1608275/publish";//Topic contaning Channel ID
+    char buf[100]; //Buffer for storing data
+    sprintf(buf, "field2=%d&status=MQTTPUBLISH",FAN_STATE);
+    message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf; //Copy buffer to Message Payload
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message); //Publsih data using MQTT client
+    logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
+}
+
+void publish_field3(){ //Function to publish the values to ThingSpeak fields
+    static int last_update = -1;
+    if(ALARM_STATE == last_update)
+        return; //Ignore unncessary update in case no chnage in value.
+    last_update = ALARM_STATE;
+    logMessage("Publish Routine\r\n");
+    int rc = 0;
+    MQTT::Message message; 
+    char* topic = "channels/1608275/publish";//Topic contaning Channel ID
+    char buf[100]; //Buffer for storing data
+    sprintf(buf, "field3=%d&status=MQTTPUBLISH",ALARM_STATE);
+    message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf; //Copy buffer to Message Payload
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message); //Publsih data using MQTT client
+    logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
+}
+
+void publish_field4(){ //Function to publish the values to ThingSpeak fields
+    static int last_update = -1;
+    last_update = WATER_LEVEL;
+    //logMessage("Publish Routine\r\n");
+    int rc = 0;
+    MQTT::Message message; 
+    char* topic = "channels/1608275/publish";//Topic contaning Channel ID
+    char buf[100]; //Buffer for storing data
+    //field5=%0.1f&field6=%0.1f&field7=%0.1f&field8=%0.1f&
+    sprintf(buf, "field4=%d&field1=%d&field2=%d&field3=%d&status=MQTTPUBLISH",WATER_LEVEL, PUMP_STATE,FAN_STATE,ALARM_STATE);
+    message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf; //Copy buffer to Message Payload
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message); //Publsih data using MQTT client
+    //logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
+}
+
+void publish_field5(){ //Function to publish the values to ThingSpeak fields
+    static int last_update = -1;
+    last_update = GAS_level;
+    //logMessage("Publish Routine\r\n");
+    int rc = 0;
+    MQTT::Message message; 
+    char* topic = "channels/1608275/publish";//Topic contaning Channel ID
+    char buf[100]; //Buffer for storing data
+    sprintf(buf, "field5=%d&field6=%d&field7=%d&field8=%d&status=MQTTPUBLISH",GAS_level, CO_level, SMOKE_level, TEMPERATURE);
+    message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf; //Copy buffer to Message Payload
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message); //Publsih data using MQTT client
+    //logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
+}
+
+void publish_field6(){ //Function to publish the values to ThingSpeak fields
+    static int last_update = -1;
+    if(CO_level == last_update)
+        return; //Ignore unncessary update in case no chnage in value.
+    last_update = CO_level;
+    logMessage("Publish Routine\r\n");
+    int rc = 0;
+    MQTT::Message message; 
+    char* topic = "channels/1608275/publish";//Topic contaning Channel ID
+    char buf[100]; //Buffer for storing data
+    sprintf(buf, "field6=%d&status=MQTTPUBLISH",CO_level);
+    message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf; //Copy buffer to Message Payload
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message); //Publsih data using MQTT client
+    logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
+}
+
+void publish_field8(){ //Function to publish the values to ThingSpeak fields
+    static int last_update = -1;
+    if(TEMPERATURE == last_update)
+        return; //Ignore unncessary update in case no chnage in value.
+    last_update = TEMPERATURE;
+    logMessage("Publish Routine\r\n");
+    int rc = 0;
+    MQTT::Message message; 
+    char* topic = "channels/1608275/publish";//Topic contaning Channel ID
+    char buf[100]; //Buffer for storing data
+    sprintf(buf, "field8=%d&status=MQTTPUBLISH",TEMPERATURE);
+    message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf; //Copy buffer to Message Payload
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message); //Publsih data using MQTT client
+    logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
+}
+
+void publish_field7(){ //Function to publish the values to ThingSpeak fields
+    static int last_update = -1;
+    if(SMOKE_level == last_update)
+        return; //Ignore unncessary update in case no chnage in value.
+    last_update = SMOKE_level;
+    logMessage("Publish Routine\r\n");
+    int rc = 0;
+    MQTT::Message message; 
+    char* topic = "channels/1608275/publish";//Topic contaning Channel ID
+    char buf[100]; //Buffer for storing data
+    sprintf(buf, "field7=%d&status=MQTTPUBLISH",SMOKE_level);
+    message.qos = MQTT::QOS0; //MQTT QOS 0 used. Best effort QOS
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf; //Copy buffer to Message Payload
+    message.payloadlen = strlen(buf)+1;
+    rc = client.publish(topic, message); //Publsih data using MQTT client
+    logMessage("Publish rc: %d, Buf: %s\r\n", rc, buf);
+}
 
 int main(int argc, char* argv[])
 {
+    smoke_detector.start_measurement(2); //Start periodic Smoke detector measurements at intervals of 10s
+   temperature.start_measurement(20); //Start periodic Temperaturre readings. At interval of 20s
+   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.
+   water_pump.pump_on(); //Start the pump for 1st time
     float version = 0.6;
-    char* topic = "mbed-sample";
-
     logMessage("HelloMQTT: version is %.2f\r\n", version);
-
-    NetworkInterface* network = easy_connect(true);
-    if (!network) {
+    int ret = 0;
+    
+    if (!network) { //Check if ethernet connection successful
         return -1;
     }
 
-    MQTTNetwork mqttNetwork(network);
-
-    MQTT::Client<MQTTNetwork, Countdown> client(mqttNetwork);
-
-    const char* hostname = "m2m.eclipse.org";
-    int port = 1883;
+    const char* hostname = "mqtt3.thingspeak.com"; //Thingspeak host name
+    int port = 1883; //MQTT default port number
     logMessage("Connecting to %s:%d\r\n", hostname, port);
-    int rc = mqttNetwork.connect(hostname, port);
+    int rc = mqttNetwork.connect(hostname, port); //Attempt to connect to MQTT host
     if (rc != 0)
-        logMessage("rc from TCP connect is %d\r\n", rc);
+        logMessage("rc- TCP connect: %d\r\n", rc);
 
-    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
-    data.MQTTVersion = 3;
-    data.clientID.cstring = "mbed-sample";
-    data.username.cstring = "testuser";
-    data.password.cstring = "testpassword";
-    if ((rc = client.connect(data)) != 0)
-        logMessage("rc from MQTT connect is %d\r\n", rc);
-
-    if ((rc = client.subscribe(topic, MQTT::QOS2, messageArrived)) != 0)
-        logMessage("rc from MQTT subscribe is %d\r\n", rc);
-
-    MQTT::Message message;
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer; //Build MQTT Client connection data
+    data.MQTTVersion = 3; //MQTT Version
+    data.clientID.cstring = "FA8KKzQ1CDY6EjENATYTESc"; //Thingspeak MQTT Client ID
+    data.username.cstring = "FA8KKzQ1CDY6EjENATYTESc";//Thingspeak MQTT Username
+    data.password.cstring = "vVdiiGscVIGLEgQIZ250Unxc";//Thingspeak MQTT Password
+    
+    
+    if ((rc = client.connect(data)) != 0) //Connect Client
+        logMessage("rc- connect: %d\r\n", rc);
+        
+    char* topic = "channels/1608275/subscribe/fields/field1"; //Subscribe for field1
+    if ((rc = client.subscribe(topic, MQTT::QOS0, field1_pump_state)) != 0)//Use field1_pump_state function pointer as call back function
+        logMessage("rc1: %d\r\n", rc);
+    
+    topic = "channels/1608275/subscribe/fields/field2";
+    if ((rc = client.subscribe(topic, MQTT::QOS0, field2_fan_state)) != 0)//Use field2_fan_state function pointer as call back function
+        logMessage("rc2: %d\r\n", rc);
 
-    // QoS 0
-    char buf[100];
-    sprintf(buf, "Hello World!  QoS 0 message from app version %f\r\n", version);
-    message.qos = MQTT::QOS0;
-    message.retained = false;
-    message.dup = false;
-    message.payload = (void*)buf;
-    message.payloadlen = strlen(buf)+1;
-    rc = client.publish(topic, message);
-    while (arrivedcount < 1)
-        client.yield(100);
-
-    // QoS 1
-    sprintf(buf, "Hello World!  QoS 1 message from app version %f\r\n", version);
-    message.qos = MQTT::QOS1;
-    message.payloadlen = strlen(buf)+1;
-    rc = client.publish(topic, message);
-    while (arrivedcount < 2)
-        client.yield(100);
-
-    // QoS 2
-    sprintf(buf, "Hello World!  QoS 2 message from app version %f\r\n", version);
-    message.qos = MQTT::QOS2;
-    message.payloadlen = strlen(buf)+1;
-    rc = client.publish(topic, message);
-    while (arrivedcount < 3)
-        client.yield(100);
-
+    topic = "channels/1608275/subscribe/fields/field3";
+    if ((rc = client.subscribe(topic, MQTT::QOS0, field3_alarm_state)) != 0)//Use field3_alarm_state function pointer as call back function
+        logMessage("rc: %d\r\n", rc);
+    
+    while (1){
+        logMessage("GAS: %d, CO: %d, Smoke: %d, TEMP = %0.1f, Water = %d", GAS_level, CO_level, SMOKE_level, TEMPERATURE, WATER_LEVEL);
+        //publish_field1();
+        //wait(1);
+        //publish_field2();
+        //wait(1);
+        //publish_field3();
+        //wait(1);
+        //publish_field4();
+        //wait(5);
+        //publish_field5();
+        //wait(5);
+        //publish_field5();
+        //wait(1);
+        //publish_field6();
+        //wait(1);
+        //publish_field7();
+        //wait(1);
+        //publish_field8();
+        client.yield(50);
+        //client.connect(data);
+    }
     if ((rc = client.unsubscribe(topic)) != 0)
         logMessage("rc from unsubscribe was %d\r\n", rc);
-
     if ((rc = client.disconnect()) != 0)
         logMessage("rc from disconnect was %d\r\n", rc);
-
     mqttNetwork.disconnect();
-
     logMessage("Version %.2f: finish %d msgs\r\n", version, arrivedcount);
-
     return 0;
 }