You are viewing an older revision! See the latest version

tweet remote control

Table of Contents

    Description

    In this project, I created a way to remotely control different devices using twitter accounts. There are a few main components to this set-up:

    • mbed's Twitter account
    • Controlling Twitter account
    • A supertweet.net interface for your application
    • mbed's Ethernet interface
    • Devices being controlled

    The purpose is to use the controlling Twitter account to tweet at the mbed's account with a predetermined syntax that the mbed can translate into commands. This serves practical purposes where you might need to set values on internet-ready household devices (like preheating your oven while you're buying supplies for dinner or changing your thermostat while you are on vacation).

    Example

    In this example, I used a Nokia LCD screen with a breakout board from Sparkfun as the device I'm controlling. There are a few commands that I can send to the mbed:

    • background [color] -> You can use this command to set the background color of the LCD to 'blue', 'green', or 'red' (example: @mbedcontroller background green)
    • write [text] -> This writes text specified in the tweet to the LCD screen. You cannot use anything with quotation marks (") (example: @mbedcontroller write Hello World!)
    • square [length] -> This draws an empty square in the screen with a side length of the number included in the tweet. The size of the screen is 130 x 130, so a size of over 130 will cause an error. (example: @mbedcontroller square 20)

    Any other commands will cause the screen to display an error message. The unique commands will stack on each other, but if background is set and the background command is sent again with a new value that new value will overwrite the old one on the screen.

    New tweets are retrieved every 30 seconds. Multiple commands can be sent at once and will be processed in the order in which they were received.

    Connections

    With the example code...

    mbedEthernet breakout boardLCD Display
    VoutVBATT, 3.3V
    GNDGND
    TD+P1
    TD-P2
    RD+P7
    RD-P8
    P5DIO
    P7SCK
    P8CS
    P9RESET

    Code

    In addition to the following code, a few changes have to me made to the HTTPClient library. First, the buffer for the path of the request needs to be increased so that we can make larger requests with the JSON arguments.

    Second, you have to add your own authentication header in like this

      snprintf(buf, sizeof(buf), "Authorization: Basic bWJlZGNvbnRyb2xsZXI6U2MxZW5jZSEh\r\n");
      ret = send(buf);
      CHECK_CONN_ERR(ret);
    

    where the bWJlZGNvbnRyb2xsZXI6U2MxZW5jZSEh part comes from running your username and password in the format of "username:password" through a 64-bit encoder. The officially supported library unfortunately does not include basic authentication at the moment.

    #include "mbed.h"
    #include "EthernetInterface.h"
    #include "HTTPClient.h"
    #include "NokiaLCD.h"
    #include <string>
    
    EthernetInterface eth;
    HTTPClient client;
    DigitalOut indicatorLED(LED1);
    NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::LCD6610); // mosi, sclk, cs, rst, type
    char *str;
    char url[1024];
    
    int main() {
        string text;
        int background = 0x0000FF;
        int squareColor = 0x00FF00;
        int squareLength = 0;
        
        string previousID;
        
        eth.init();
        eth.connect();
        
        str = (char *) malloc(8192);
        
        
        while(1) {
            int ret;
            if(previousID.empty()) {
                ret = client.get("http://api.supertweet.net/1.1/statuses/mentions_timeline.json?count=1", str, 4096);
            } else {
                sprintf(url, "http://api.supertweet.net/1.1/statuses/mentions_timeline.json?since_id=%s\0", previousID.c_str());
                ret = client.get(url, str, 4096);
            }
            if (ret) {
              printf("Error - ret = %d - HTTP return code = %d\n", ret, client.getHTTPResponseCode());
              return 1;
            }
            
            string tweetInfo(str);
            string tweetCommand;
            string tweetSetting;
            size_t foundStart = string::npos;
            if(tweetInfo.compare("[]")) {
                foundStart = tweetInfo.rfind("\"text\":\"@");
            }
            size_t foundEnd;
            while(foundStart != string::npos) {
                foundStart += 24;
                foundEnd = tweetInfo.find(" ",foundStart);
                if(foundEnd != string::npos) {
                    tweetCommand = tweetInfo.substr(foundStart, foundEnd - foundStart);
                } else {
                    continue;
                }
                foundStart = foundEnd + 1;
                foundEnd = tweetInfo.find("\"",foundStart);
                tweetSetting = tweetInfo.substr(foundStart, foundEnd - foundStart);
                
                printf("%s*%s*\n", tweetCommand.c_str(), tweetSetting.c_str());
                
                if(!tweetCommand.compare("background")) {
                    if(!tweetSetting.compare("blue")) {
                        background = 0x0000FF;
                        squareColor = 0x00FF00;
                    } else if(!tweetSetting.compare("green")) {
                        background = 0x00FF00;
                        squareColor = 0xFF0000;
                    } else if(!tweetSetting.compare("red")) {
                        background = 0xFF0000;
                        squareColor = 0x0000FF;
                    } else {
                        text = "Invalid tweet setting";
                    }
                } else if(!tweetCommand.compare("write")) {
                    text = tweetSetting;
                } else if(!tweetCommand.compare("square")) {
                    squareLength = atoi(tweetSetting.c_str());
                } else {
                    text = "Invalid tweet command";
                }
                
                foundStart -= 60;
                foundStart = tweetInfo.rfind("\"text\":\"@", foundStart);
                printf("%d*%d*\n", foundStart, string::npos);
            }
            
            lcd.cls();
            lcd.fill(0, 0, 130, 130, background);
            lcd.background(background);
            lcd.locate(0, 7);
            lcd.printf(text.c_str());
            if(squareLength > 0) {
                int i;
                for(int i=65-(squareLength/2); i<65+(squareLength/2);i++) {
                    lcd.pixel(i, 65-(squareLength/2), squareColor);
                    lcd.pixel(i, 65+(squareLength/2), squareColor);
                }
                for(i=65-(squareLength/2); i<65+(squareLength/2);i++) {
                    lcd.pixel(65-(squareLength/2), i, squareColor);
                    lcd.pixel(65+(squareLength/2), i, squareColor);
                }
            }
            
            if(tweetInfo.compare("[]")) {
                foundStart = tweetInfo.find("\"id_str\":\"");
                foundStart += 10;
                foundEnd = tweetInfo.find("\"", foundStart);
                previousID = tweetInfo.substr(foundStart, foundEnd - foundStart);
                printf("%s\n", previousID.c_str());
            }
            
            wait(30);
        }
        
    }
    

    All wikipages