![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Twitter Coffee Maker
Dependencies: 4DGL-uLCD-SE EthernetInterface HTTPClientAuthAndPathExtension mbed-rtos mbed
Diff: main.cpp
- 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