Twitter Coffee Maker

Dependencies:   4DGL-uLCD-SE EthernetInterface HTTPClientAuthAndPathExtension mbed-rtos mbed

Revision:
0:fe8909182706
diff -r 000000000000 -r fe8909182706 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Apr 23 18:39:34 2014 +0000
@@ -0,0 +1,280 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "EthernetInterface.h"
+#include "HTTPClient.h"
+#include "uLCD_4DGL.h"
+#include <string>
+#define TWOCUPS ((2*60)+19) //TIME to brew two cups (seconds)
+#define FOURCUPS ((4*60)+7) //""
+#define SIXCUPS ((5*60)+56) //""
+#define POSTURL "http://143.215.102.83:8080/1.1/statuses/update.json" //URL TO POST NEW STATUS
+#define GETURL "http://143.215.102.83:8080/1.1/statuses/mentions_timeline.json?count=1" //URL TO GET DATA
+#define REQUESTINTRVL 60  //Interval to make get requests
+
+
+void clientCheck();
+string checkCupTweet(string wholeTweet);
+void postTweet(string tweet);
+string getField(int startIndex,int startLength);
+void checkReady();
+void brew();
+
+DigitalIn ready(p5); //Ready pin
+DigitalOut coffeeTurnOn(p6); //Coffee Turn on pin
+EthernetInterface eth;
+HTTPClient client;
+uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin;
+char rawTweetInfo[8192];
+string tweetInfo; //response from twitter
+string previousID; //ID of preivously read tweet
+string currentID; //ID of newest read tweet
+string tweeter; //twitter handle of tweeter
+string numCups; //Number of cups 
+int state; //STATE MACHINE CONTROLLING PROCESS
+
+int main() {
+    state=5;
+    ready.mode(PullUp);
+    //Initialize Connection and get IP address
+    eth.init();
+    eth.connect();
+    //Get inital information for current ID field
+    clientCheck();
+    uLCD.cls();
+    uLCD.printf("Machine Needs coffee and water");
+    wait(5.0);
+    //End initalization
+    while(1){
+        //Check if the machine is ready to brew (accepts input from pushbutton)
+        checkReady();
+        //Check if new tweet has been sent and if its proper format
+        clientCheck();
+        //See if brew process should start
+        brew(); //END 
+    }  
+}
+
+
+void checkReady() {
+    int loopVar=1000000000/2;
+    while(loopVar>0){
+        if(state>0) break;
+        else{
+            if(!(ready)){
+                state=1;
+                uLCD.cls();
+                uLCD.printf("Machine Ready, waiting for Command");
+            }
+        }
+        loopVar=loopVar-1;
+    }
+}
+
+/*
+    Post a tweet to twitter using the coffee machines handle.
+    This allows us to notify the tweeter of our course of action.
+    
+    @param tweet- the tweet you are sending to the user
+
+*/
+void postTweet(string tweet){
+        char str[512];
+        int i;
+        HTTPText inText(str, 512);
+        HTTPMap mapp;
+        mapp.put("status",tweet.c_str());
+        for(i=0;i<2;i++){//TRY POSTING IT 3 TIMES OTHERWISE LET IT GO
+            int ret=client.post(POSTURL, mapp, &inText);
+            if (!ret)
+            {
+                uLCD.printf("Executed POST successfully - read characters\n");
+                break;
+            }
+            else
+            {
+                uLCD.printf("Error Posting Data\n");
+                tweet+=".";
+                mapp.clear();
+                mapp.put("status",tweet.c_str());
+                wait(2.0);
+                continue;
+            }
+        }
+}
+/*
+    Gets the value of a field sent back from twitter through an HTTP get request.
+    The data is in JSON format and can be parsed accordingly. 
+    
+    @param startIndex- starting index in response (of header)
+    @param startLength- the length of the header (in characters)
+    
+    return
+    finalResult- the value of the field as a string
+    
+*/
+string getField(int startIndex,int startLength){
+    int start=startIndex+startLength+1; //should be first letter
+    char curChar=tweetInfo.at(start); //first letter
+    string finalResult=""; 
+    while(curChar !='\"'){
+        finalResult+=curChar;
+        start=start+1;
+        curChar=tweetInfo.at(start);
+    }
+    return finalResult;
+}
+
+/*
+    Gets the newest tweet from the coffee Machines twitter feed.
+    Responds to the tweet based on the current state of the coffee machine
+    and whether the tweet was in the proper format or not.
+*/
+void clientCheck(){
+    int ret = client.get(GETURL,rawTweetInfo,4096); //Do HTTP GET REQUEST
+    double rqstInt=REQUESTINTRVL;
+    if (ret) { //IF Request failed
+        uLCD.cls();
+        uLCD.printf("FAIL GETTING DATA\n");
+        uLCD.printf("ERROR= %d\n",ret);
+        uLCD.printf("Error - ret = %d - HTTP return code = %d\n", ret, client.getHTTPResponseCode());
+        wait(rqstInt);
+        return;
+    }
+    tweetInfo=rawTweetInfo;
+    string tweeterStart="\"screen_name\":"; //Header in request for twitter handle
+    string numCupsStart="\"text\":"; //Header in request for tweet
+    string idStart="\"id_str\":"; //Header in request for the unique ID with every tweet
+    int indexID=tweetInfo.find(idStart,0);
+    int indexTweeter=tweetInfo.find(tweeterStart,0);
+    int indexNumCups=tweetInfo.find(numCupsStart,0);
+    int tweeterLength=tweeterStart.length();
+    int cupsLength=numCupsStart.length();
+    int idLength=idStart.length();     
+    //Get the idString
+    string tempID=getField(indexID,idLength);
+    if(strcmp(tempID.c_str(),currentID.c_str())==0);//do nothing, no new tweet
+    else{//got a new tweet
+        previousID=currentID;
+        currentID=tempID;
+        string tempTweeter=getField(indexTweeter,tweeterLength); //NEED TO ADD @ Symbol
+        tempTweeter=tempTweeter.insert(0,"@"); //Insert at symbol
+        if(state==2){//already brewing
+            tempTweeter+=" Currently brewing try again later";
+            postTweet(tempTweeter);
+        }
+        else if(state==0){//Not ready so notify the machine is not ready
+            tempTweeter+=" Coffee Machine not Ready. Needs Water and Grinds";
+            postTweet(tempTweeter);
+        }
+        else if(state==5) state=0; //Initialization state
+        else{
+            //Check if its a valid cup tweet
+            //Get the whole tweet
+            string wholeTweet=getField(indexNumCups,cupsLength);
+            string tempCup=checkCupTweet(wholeTweet);
+            if(strcmp(tempCup.c_str(),"inv")==0){ //Invalid format. Notify user
+                tempTweeter+=" Invalid Format. Use <handle> <numcups> cups";
+                postTweet(tempTweeter);
+            }
+            else{//ALL GOOD SET EVERYTHING
+                numCups=tempCup;
+                tweeter=tempTweeter;
+                state=3;
+            }
+        }
+    }
+    wait(rqstInt); 
+}
+/*
+    Extracts the number of cups specified in a tweet to the coffee maker.
+    If no valid number, sets the cups field as inv.
+    
+    @param wholeTweet- tweet that a user sent to the coffee machine
+    
+    return
+    result- a string with either the number of cups in the tweet or inv
+
+*/
+string checkCupTweet(string wholeTweet){
+    string subTweet;
+    string result;
+    char curChar=wholeTweet.at(0);
+    if(curChar!='@'){
+        result="inv";
+    }
+    else{
+        while(curChar!=' '){
+            wholeTweet.erase(0,1);
+            curChar=wholeTweet.at(0);   
+        }
+        subTweet=wholeTweet;
+        if(subTweet.find_first_of("2",0) != string::npos){
+            result="2";    
+        }
+        else if(subTweet.find_first_of("4",0) != string::npos){
+            result="4";
+        }
+        else if(subTweet.find_first_of("6",0) != string::npos){
+            result="6";
+        }
+        else{
+            result="inv";
+        }
+    }
+    return result;    
+}
+
+
+
+/*
+    Handles the brewing process. Checks if the state is set to the proper value (3)
+    and then goes through the brewing process. If it is not the proper state, simply
+    exits the function.
+*/
+void brew(){
+    double rqstInt=REQUESTINTRVL;
+    if(state==3){//DO THE BREW
+        uLCD.cls();
+        uLCD.printf("BREWING");
+        int numTimes;
+        int i;
+        double remainder;
+        int timeToBrew;
+        state=2;
+        string sendTweet=tweeter;
+        sendTweet+=" Starting to brew!";
+        postTweet(sendTweet);
+        coffeeTurnOn=1;
+        if(strcmp(numCups.c_str(),"2")==0){
+            timeToBrew=TWOCUPS;
+            numTimes=timeToBrew/rqstInt;
+            remainder= timeToBrew % ((int)rqstInt);
+            for(i=0;i<numTimes;i++){
+                clientCheck();
+            }
+            wait(remainder);
+        }
+        else if(strcmp(numCups.c_str(),"4")==0){
+            numTimes=FOURCUPS/rqstInt;
+            remainder= FOURCUPS % ((int)rqstInt);
+            for(i=0;i<numTimes;i++){
+                clientCheck();
+            }
+            wait(remainder);
+        }
+        else if(strcmp(numCups.c_str(),"6")==0){
+            numTimes=SIXCUPS/rqstInt;
+            remainder= SIXCUPS % ((int)rqstInt);  
+            for(i=0;i<numTimes;i++){
+                clientCheck();
+            }
+            wait(remainder);  
+        }
+        sendTweet=tweeter;
+        sendTweet+=" done brewing. Enjoy!";
+        postTweet(sendTweet);
+        coffeeTurnOn=0;
+        state=0;  
+    }
+    else;     
+}  
\ No newline at end of file