Twitter Coffee Maker

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "rtos.h"
00003 #include "EthernetInterface.h"
00004 #include "HTTPClient.h"
00005 #include "uLCD_4DGL.h"
00006 #include <string>
00007 #define TWOCUPS ((2*60)+19) //TIME to brew two cups (seconds)
00008 #define FOURCUPS ((4*60)+7) //""
00009 #define SIXCUPS ((5*60)+56) //""
00010 #define POSTURL "http://143.215.102.83:8080/1.1/statuses/update.json" //URL TO POST NEW STATUS
00011 #define GETURL "http://143.215.102.83:8080/1.1/statuses/mentions_timeline.json?count=1" //URL TO GET DATA
00012 #define REQUESTINTRVL 60  //Interval to make get requests
00013 
00014 
00015 void clientCheck();
00016 string checkCupTweet(string wholeTweet);
00017 void postTweet(string tweet);
00018 string getField(int startIndex,int startLength);
00019 void checkReady();
00020 void brew();
00021 
00022 DigitalIn ready(p5); //Ready pin
00023 DigitalOut coffeeTurnOn(p6); //Coffee Turn on pin
00024 EthernetInterface eth;
00025 HTTPClient client;
00026 uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin;
00027 char rawTweetInfo[8192];
00028 string tweetInfo; //response from twitter
00029 string previousID; //ID of preivously read tweet
00030 string currentID; //ID of newest read tweet
00031 string tweeter; //twitter handle of tweeter
00032 string numCups; //Number of cups 
00033 int state; //STATE MACHINE CONTROLLING PROCESS
00034 
00035 int main() {
00036     state=5;
00037     ready.mode(PullUp);
00038     //Initialize Connection and get IP address
00039     eth.init();
00040     eth.connect();
00041     //Get inital information for current ID field
00042     clientCheck();
00043     uLCD.cls();
00044     uLCD.printf("Machine Needs coffee and water");
00045     wait(5.0);
00046     //End initalization
00047     while(1){
00048         //Check if the machine is ready to brew (accepts input from pushbutton)
00049         checkReady();
00050         //Check if new tweet has been sent and if its proper format
00051         clientCheck();
00052         //See if brew process should start
00053         brew(); //END 
00054     }  
00055 }
00056 
00057 
00058 void checkReady() {
00059     int loopVar=1000000000/2;
00060     while(loopVar>0){
00061         if(state>0) break;
00062         else{
00063             if(!(ready)){
00064                 state=1;
00065                 uLCD.cls();
00066                 uLCD.printf("Machine Ready, waiting for Command");
00067             }
00068         }
00069         loopVar=loopVar-1;
00070     }
00071 }
00072 
00073 /*
00074     Post a tweet to twitter using the coffee machines handle.
00075     This allows us to notify the tweeter of our course of action.
00076     
00077     @param tweet- the tweet you are sending to the user
00078 
00079 */
00080 void postTweet(string tweet){
00081         char str[512];
00082         int i;
00083         HTTPText inText(str, 512);
00084         HTTPMap mapp;
00085         mapp.put("status",tweet.c_str());
00086         for(i=0;i<2;i++){//TRY POSTING IT 3 TIMES OTHERWISE LET IT GO
00087             int ret=client.post(POSTURL, mapp, &inText);
00088             if (!ret)
00089             {
00090                 uLCD.printf("Executed POST successfully - read characters\n");
00091                 break;
00092             }
00093             else
00094             {
00095                 uLCD.printf("Error Posting Data\n");
00096                 tweet+=".";
00097                 mapp.clear();
00098                 mapp.put("status",tweet.c_str());
00099                 wait(2.0);
00100                 continue;
00101             }
00102         }
00103 }
00104 /*
00105     Gets the value of a field sent back from twitter through an HTTP get request.
00106     The data is in JSON format and can be parsed accordingly. 
00107     
00108     @param startIndex- starting index in response (of header)
00109     @param startLength- the length of the header (in characters)
00110     
00111     return
00112     finalResult- the value of the field as a string
00113     
00114 */
00115 string getField(int startIndex,int startLength){
00116     int start=startIndex+startLength+1; //should be first letter
00117     char curChar=tweetInfo.at(start); //first letter
00118     string finalResult=""; 
00119     while(curChar !='\"'){
00120         finalResult+=curChar;
00121         start=start+1;
00122         curChar=tweetInfo.at(start);
00123     }
00124     return finalResult;
00125 }
00126 
00127 /*
00128     Gets the newest tweet from the coffee Machines twitter feed.
00129     Responds to the tweet based on the current state of the coffee machine
00130     and whether the tweet was in the proper format or not.
00131 */
00132 void clientCheck(){
00133     int ret = client.get(GETURL,rawTweetInfo,4096); //Do HTTP GET REQUEST
00134     double rqstInt=REQUESTINTRVL;
00135     if (ret) { //IF Request failed
00136         uLCD.cls();
00137         uLCD.printf("FAIL GETTING DATA\n");
00138         uLCD.printf("ERROR= %d\n",ret);
00139         uLCD.printf("Error - ret = %d - HTTP return code = %d\n", ret, client.getHTTPResponseCode());
00140         wait(rqstInt);
00141         return;
00142     }
00143     tweetInfo=rawTweetInfo;
00144     string tweeterStart="\"screen_name\":"; //Header in request for twitter handle
00145     string numCupsStart="\"text\":"; //Header in request for tweet
00146     string idStart="\"id_str\":"; //Header in request for the unique ID with every tweet
00147     int indexID=tweetInfo.find(idStart,0);
00148     int indexTweeter=tweetInfo.find(tweeterStart,0);
00149     int indexNumCups=tweetInfo.find(numCupsStart,0);
00150     int tweeterLength=tweeterStart.length();
00151     int cupsLength=numCupsStart.length();
00152     int idLength=idStart.length();     
00153     //Get the idString
00154     string tempID=getField(indexID,idLength);
00155     if(strcmp(tempID.c_str(),currentID.c_str())==0);//do nothing, no new tweet
00156     else{//got a new tweet
00157         previousID=currentID;
00158         currentID=tempID;
00159         string tempTweeter=getField(indexTweeter,tweeterLength); //NEED TO ADD @ Symbol
00160         tempTweeter=tempTweeter.insert(0,"@"); //Insert at symbol
00161         if(state==2){//already brewing
00162             tempTweeter+=" Currently brewing try again later";
00163             postTweet(tempTweeter);
00164         }
00165         else if(state==0){//Not ready so notify the machine is not ready
00166             tempTweeter+=" Coffee Machine not Ready. Needs Water and Grinds";
00167             postTweet(tempTweeter);
00168         }
00169         else if(state==5) state=0; //Initialization state
00170         else{
00171             //Check if its a valid cup tweet
00172             //Get the whole tweet
00173             string wholeTweet=getField(indexNumCups,cupsLength);
00174             string tempCup=checkCupTweet(wholeTweet);
00175             if(strcmp(tempCup.c_str(),"inv")==0){ //Invalid format. Notify user
00176                 tempTweeter+=" Invalid Format. Use <handle> <numcups> cups";
00177                 postTweet(tempTweeter);
00178             }
00179             else{//ALL GOOD SET EVERYTHING
00180                 numCups=tempCup;
00181                 tweeter=tempTweeter;
00182                 state=3;
00183             }
00184         }
00185     }
00186     wait(rqstInt); 
00187 }
00188 /*
00189     Extracts the number of cups specified in a tweet to the coffee maker.
00190     If no valid number, sets the cups field as inv.
00191     
00192     @param wholeTweet- tweet that a user sent to the coffee machine
00193     
00194     return
00195     result- a string with either the number of cups in the tweet or inv
00196 
00197 */
00198 string checkCupTweet(string wholeTweet){
00199     string subTweet;
00200     string result;
00201     char curChar=wholeTweet.at(0);
00202     if(curChar!='@'){
00203         result="inv";
00204     }
00205     else{
00206         while(curChar!=' '){
00207             wholeTweet.erase(0,1);
00208             curChar=wholeTweet.at(0);   
00209         }
00210         subTweet=wholeTweet;
00211         if(subTweet.find_first_of("2",0) != string::npos){
00212             result="2";    
00213         }
00214         else if(subTweet.find_first_of("4",0) != string::npos){
00215             result="4";
00216         }
00217         else if(subTweet.find_first_of("6",0) != string::npos){
00218             result="6";
00219         }
00220         else{
00221             result="inv";
00222         }
00223     }
00224     return result;    
00225 }
00226 
00227 
00228 
00229 /*
00230     Handles the brewing process. Checks if the state is set to the proper value (3)
00231     and then goes through the brewing process. If it is not the proper state, simply
00232     exits the function.
00233 */
00234 void brew(){
00235     double rqstInt=REQUESTINTRVL;
00236     if(state==3){//DO THE BREW
00237         uLCD.cls();
00238         uLCD.printf("BREWING");
00239         int numTimes;
00240         int i;
00241         double remainder;
00242         int timeToBrew;
00243         state=2;
00244         string sendTweet=tweeter;
00245         sendTweet+=" Starting to brew!";
00246         postTweet(sendTweet);
00247         coffeeTurnOn=1;
00248         if(strcmp(numCups.c_str(),"2")==0){
00249             timeToBrew=TWOCUPS;
00250             numTimes=timeToBrew/rqstInt;
00251             remainder= timeToBrew % ((int)rqstInt);
00252             for(i=0;i<numTimes;i++){
00253                 clientCheck();
00254             }
00255             wait(remainder);
00256         }
00257         else if(strcmp(numCups.c_str(),"4")==0){
00258             numTimes=FOURCUPS/rqstInt;
00259             remainder= FOURCUPS % ((int)rqstInt);
00260             for(i=0;i<numTimes;i++){
00261                 clientCheck();
00262             }
00263             wait(remainder);
00264         }
00265         else if(strcmp(numCups.c_str(),"6")==0){
00266             numTimes=SIXCUPS/rqstInt;
00267             remainder= SIXCUPS % ((int)rqstInt);  
00268             for(i=0;i<numTimes;i++){
00269                 clientCheck();
00270             }
00271             wait(remainder);  
00272         }
00273         sendTweet=tweeter;
00274         sendTweet+=" done brewing. Enjoy!";
00275         postTweet(sendTweet);
00276         coffeeTurnOn=0;
00277         state=0;  
00278     }
00279     else;     
00280 }