Twitter Coffee Maker
Dependencies: 4DGL-uLCD-SE EthernetInterface HTTPClientAuthAndPathExtension mbed-rtos mbed
main.cpp
- Committer:
- tlisowski3
- Date:
- 2014-04-23
- Revision:
- 0:fe8909182706
File content as of revision 0:fe8909182706:
#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; }