This project was inspired by this article, where the author explains how to fetch your status message from Twitter to an Arduino and show it on a LCD placed at your office door. At the end, a few improvements are mentioned and the complete implementation can be found here. I wanted do basically the same, but did not have the Arduino Ethernet Shield. Instead, I used an embedded system that was in our lab doing nothing.
TS-7260 running Debian Etch → $179 http://www.embeddedarm.com/products/board-detail.php?product=TS-7260#
16×2 LCD → $13.95 http://www.sparkfun.com/products/255
Twitcurl, library for Twitter API's.
Libcurl, Libcurl dependency.
Perl, for the main script.
Perl module: http://search.cpan.org/~grantm/XML-Simple-2.18/lib/XML/Simple.pm XML::Simple, so you can parse the XML file.
Libcurl:
cd mkdir scr cd scr/ wget http://curl.haxx.se/download/curl-7.21.7.tar.gz tar xvfz curl-7.21.7.tar.gz cd curl-7.21.7 ./configure --prefix=/usr make make install
Twitcurl:
cd ../../ mkdir twitcurl cd twitcurl/ apt-get install g++ apt-get install subversion svn co http://twitcurl.googlecode.com/svn/branches/libtwitcurl cd libtwitcurl/ make cp twitcurl.h oauthlib.h /usr/include/ cp libtwitcurl.so.1.0 /usr/lib/ ln -sf /usr/lib/libtwitcurl.so.1.0 /usr/lib/libtwitcurl.so.1 ln -sf /usr/lib/libtwitcurl.so.1.0 /usr/lib/libtwitcurl.so
Perl (I tried to use cpan
, but the system kept getting out of memory):
cd ../../ mkdir perlModules cd perlModules/ wget http://search.cpan.org/CPAN/authors/id/M/MS/MSCHWERN/ExtUtils-MakeMaker-6.58.tar.gz tar xvfz ExtUtils-MakeMaker-6.58.tar.gz cd ExtUtils-MakeMaker-6.58 perl Makefile.PL make make install cd .. wget http://search.cpan.org/CPAN/authors/id/P/PE/PERIGRIN/XML-NamespaceSupport-1.11.tar.gz tar xvfz XML-NamespaceSupport-1.11.tar.gz cd XML-NamespaceSupport-1.11 perl Makefile.PL make make install cd .. wget http://search.cpan.org/CPAN/authors/id/G/GR/GRANTM/XML-SAX-0.96.tar.gz tar xvfz XML-SAX-0.96.tar.gz cd XML-SAX-0.96 perl Makefile.PL make make install cd .. wget http://search.cpan.org/CPAN/authors/id/G/GR/GRANTM/XML-Simple-2.18.tar.gz tar xvfz XML-Simple-2.18.tar.gz cd XML-Simple-2.18 perl Makefile.PL make make install
LCD:
cd ../../ mkdir lcd cd lcd wget ftp://ftp.embeddedarm.com/ts-arm-sbc/ts-7260-linux/samples/lcdmesg.c gcc -o lcdmesg lcdmesg.c
Sign in to your Twitter account. Go to settings → applications → developers → create new application. Complete the information screen, copy the consumer key and consumer secret. You'll need it next.
Create the application that's going to fetch the status and display it on the LCD:
cd /home/src/ mkdir twitterReader
Here's the code for twitterReader.h:
#include <cstdio> #include <iostream> #include <fstream> #include "twitcurl.h"
The code for twitterReader.cpp is this one (update myConsumerKey and myConsumerSecret with data from last step):
#include "twitterReader.h" void printUsage() { printf( "\nUsage:\ntwitterClient -u username -p password\n" ); } int main( int argc, char* argv[] ) { std::string userName( "" ); std::string passWord( "" ); if( argc > 4 ) { for( int i = 1; i < argc; i += 2 ) { if( 0 == strncmp( argv[i], "-u", strlen("-u") ) ) { userName = argv[i+1]; } else if( 0 == strncmp( argv[i], "-p", strlen("-p") ) ) { passWord = argv[i+1]; } } if( ( 0 == userName.length() ) || ( 0 == passWord.length() ) ) { printUsage(); return 0; } } else { printUsage(); return 0; } twitCurl twitterObj; std::string tmpStr( "" ); std::string replyMsg( "" ); /* OAuth flow begins */ /* Step 0: Set OAuth related params. These are got by registering your app at twitter.com */ twitterObj.getOAuth().setConsumerKey( std::string( "myConsumerKey" ) ); twitterObj.getOAuth().setConsumerSecret( std::string( "myConsumerSecret" ) ); /* Step 1: Check if we alredy have OAuth access token from a previous run */ char szKey[1024]; std::string myOAuthAccessTokenKey(""); std::string myOAuthAccessTokenSecret(""); std::ifstream oAuthTokenKeyIn; std::ifstream oAuthTokenSecretIn; oAuthTokenKeyIn.open( "twitterReader_token_key.txt" ); oAuthTokenSecretIn.open( "twitterReader_token_secret.txt" ); memset( szKey, 0, 1024 ); oAuthTokenKeyIn >> szKey; myOAuthAccessTokenKey = szKey; memset( szKey, 0, 1024 ); oAuthTokenSecretIn >> szKey; myOAuthAccessTokenSecret = szKey; oAuthTokenKeyIn.close(); oAuthTokenSecretIn.close(); if( myOAuthAccessTokenKey.size() && myOAuthAccessTokenSecret.size() ) { /* If we already have these keys, then no need to go through auth again */ printf( "\nUsing:\nKey: %s\nSecret: %s\n\n", myOAuthAccessTokenKey.c_str(), myOAuthAccessTokenSecret.c_str() ); twitterObj.getOAuth().setOAuthTokenKey( myOAuthAccessTokenKey ); twitterObj.getOAuth().setOAuthTokenSecret( myOAuthAccessTokenSecret ); } else { /* Step 2: Get request token key and secret */ twitterObj.oAuthRequestToken( tmpStr ); /* Step 3: Ask user to visit web link and get PIN */ char szOAuthVerifierPin[1024]; memset( szOAuthVerifierPin, 0, 1024 ); printf( "\nPlease visit this link in web browser and authorize this application:\n%s", tmpStr.c_str() ); printf( "\nEnter the PIN provided by twitter: " ); gets( szOAuthVerifierPin ); tmpStr = szOAuthVerifierPin; twitterObj.getOAuth().setOAuthPin( tmpStr ); /* Step 4: Exchange request token with access token */ twitterObj.oAuthAccessToken(); /* Step 5: Now, save this access token key and secret for future use without PIN */ twitterObj.getOAuth().getOAuthTokenKey( myOAuthAccessTokenKey ); twitterObj.getOAuth().getOAuthTokenSecret( myOAuthAccessTokenSecret ); /* Step 6: Save these keys in a file or wherever */ std::ofstream oAuthTokenKeyOut; std::ofstream oAuthTokenSecretOut; oAuthTokenKeyOut.open( "twitterReader_token_key.txt" ); oAuthTokenSecretOut.open( "twitterReader_token_secret.txt" ); oAuthTokenKeyOut.clear(); oAuthTokenSecretOut.clear(); oAuthTokenKeyOut << myOAuthAccessTokenKey.c_str(); oAuthTokenSecretOut << myOAuthAccessTokenSecret.c_str(); oAuthTokenKeyOut.close(); oAuthTokenSecretOut.close(); } /* OAuth flow ends */ /* Set twitter username and password */ twitterObj.setTwitterUsername( userName ); twitterObj.setTwitterPassword( passWord ); /* Read status */ if( twitterObj.timelineUserGet( userName, false ) ) { twitterObj.getLastWebResponse( replyMsg ); /* Save response from twitter in a file or wherever */ std::ofstream replyMsgOut; replyMsgOut.open( "twitterReader_reply_message.xml" ); replyMsgOut.clear(); replyMsgOut << replyMsg.c_str(); replyMsgOut.close(); //printf( "\ntwitterClient:: twitCurl::statusUpdate web response:\n%s\n", replyMsg.c_str() ); printf("\nWeb response saved!\n"); } else { twitterObj.getLastCurlError( replyMsg ); printf( "\ntwitterClient:: twitCurl::statusUpdate error:\n%s\n", replyMsg.c_str() ); } return 0; }
This will download a XML file with the response from Twitter.
Save and compile:
g++ -ltwitcurl -o statusReader twitterReader.cpp
./statusReader -u username -p password
Visit the website and copy the PIN. Check the XML file saved to see the response from Twitter.
Create a folder for the application:
cd ../../ mkdir tweetMyDoor cd tweetMyDoor/
Copy the statusReader and lcdmesg programs:
cp ../src/twitterReader/statusReader ./ cp ../src/lcd/lcdmesg ./
Create the main application:
nano tweetMyDoor.pl
Here's the code:
#!/usr/bin/perl # use modules use strict; use warnings; use XML::Simple; use Data::Dumper; # create object my $xml = new XML::Simple (ForceArray => 1); #my $xml = new XML::Simple; while (1) { # first call twitterReader to get timeline from twitter my $status = system("./statusReader -u username -p password"); # read XML file my $data = $xml->XMLin("twitterReader_reply_message.xml"); #open (MYFILE, '>>data.txt'); #print MYFILE Dumper($data); #close (MYFILE); # access XML data print "Last tweet: $data->{'status'}->[0]->{'text'}->[0]\n"; #print "Tweet 2: data->{'status'}->[1]->{'text'}->[0]\n"; # update LCD system("echo $data->{'status'}->[0]->{'text'}->[0] | ./lcdmesg"); sleep(180); }
Run it (repeat steps for PIN):
perl tweetMyDoor.pl