Introduction
Twitter is a social networking service that allows its users to send messages to other users, a mobile phone, and the user’s Twitter homepage. These messages are under 140 characters in length, to conform to the SMS (Short Message Service) standards.
Twitter has found a market in embedded devices. Developers are allowing their modules to “tweet” status updates to the web. This opens a simple communication channel between the device and the user. For instance, you may want to know whenever a dog door in your home is used when you are not home. A simple embedded device monitoring the dog door could be set up to send a message to your mobile phone whenever the dog heads outside.
Twitter provides an API to access many core features of the service. We will use the API in this example to get the current status of a user, and to send a new status to the service. Additional API commands are available, and can be found in full at http://apiwiki.twitter.com/Twitter-API-Documentation.
In this example, we will call two Twitter API commands (user/show) and (statuses/update) using a custom get and a custom post command. The custom post also includes a demonstration of how to use basic authentication in a post.
Getting the Twitter Status of a User
Getting a Twitter status uses the Twitter API call user/show. This call requires an HTML GET command. Authentication is not required, and you can pull the latest status updates from any public user (enabled by default) on Twitter.
In this example, we will request the status of the user NetBurner. Once the request is sent to Twitter, we will use a very basic parsing algorithm to parse out and print the status via UART0 (serial).
Code: Select all
// Function to get the latest Twitter status for a user
void getTwitterStatus(int sock, PCSTR url) {
char method[] = "GET";
char host[] = "api.twitter.com";
char hosturl[] = "/1/users/show.json?id=NetBurner";
char useragent[] = "NetBurner/PK70";
// Getting IP Address
IPADDR DestIP_Addr;
while ((DestIP_Addr = GetIPAddress(host)) == 0) {
OSTimeDly(TICKS_PER_SECOND * 5);
}
// Building GET Command
char cmd[1024];
int sizeOfMethod = 0;
sizeOfMethod = siprintf(cmd, "%s %s HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: %s\r\n"
"\r\n",
method, hosturl, host, useragent);
// Sending GET
int fd = connect(DestIP_Addr, 0, 80, 5 * TICKS_PER_SECOND);
write(fd, cmd, sizeOfMethod);
// Reading Results
// Loop and record all incoming data
DWORD BytesRead = 0;
DataBuffer[0] = '\0';
while ((fd > 0) && (BytesRead < DATA_BUFSIZE - 1)) {
int n = ReadWithTimeout(fd, RxBuffer, RX_BUFSIZE, TICKS_PER_SECOND * 5);
if (n > 0) {
BytesRead += n;
RxBuffer[n] = '\0';
//iprintf("Read %d bytes: %s\n", n, RxBuffer);
iprintf("BytesRead: %d\r", BytesRead);
if ((BytesRead + n) < DATA_BUFSIZE)
strncat(DataBuffer, RxBuffer, n);
} else // connection closed by server or timeout
{
iprintf("Connection closed by server, n = %d\r\n", n);
close(fd);
fd = 0;
}
}
DataBuffer[BytesRead] = '\0';
// Parsing Results
int parseState = 0;
char *cp = DataBuffer;
while (*cp) {
switch (parseState) {
case 0:
if (*cp == '"') {
parseState = 1;
} else
parseState = 0;
break;
case 1:
if (*cp == 't') {
parseState = 20;
} else {
parseState = 0;
}
break;
case 20:
if (*cp == 'e') {
parseState = 21;
} else {
parseState = 0;
}
break;
case 21:
if (*cp == 'x') {
parseState = 22;
} else {
parseState = 0;
}
break;
case 22:
if (*cp == 't') {
parseState = 23;
} else {
parseState = 0;
}
break;
case 23:
if (*cp == '"') {
parseState = 24;
} else {
parseState = 0;
}
break;
case 24:
if (*cp == ':') {
parseState = 25;
iprintf("text: ");
} else {
parseState = 0;
}
break;
case 25: // Got "text":
if (*cp == '}') {
parseState = 0;
iprintf("\r\n");
} else {
iprintf("%c", *cp);
}
break;
default:
parseState = 0;
}
*cp++;
}
// Closing Socket
close(fd);
}
• id. The ID or screen name of a user.
Example: http://api.twitter.com/1/users/show/12345.json or http://api.twitter.com/1/users/show/bob.xml
• user_id. Specfies the ID of the user to return. Helpful for disambiguating when a valid user ID is also a valid screen name.
Example: http://api.twitter.com/1/users/show.xml?user_id=1401881
• screen_name. Specfies the screen name of the user to return. Helpful for disambiguating when a valid screen name is also a user ID.
Example: http://api.twitter.com/1/users/show.xml ... ame=101010
Sending a Twitter Update
Sending a Twitter update uses the Twitter API call statuses/update. The update requires you to create an HTML POST command. This post uses basic authentication, which is a base64 encoded string representing the string “username:password”. In addition you will need to provide the update string you intend to post to Twitter.
In our example, the update request entails encoding the base64 authentication, building the form post, opening a network socket to twitter, and sending the post. No response is collected. The update will be immediately visible on the Twitter homepage.
Code: Select all
char un[] = ""; // Twitter user name
char pw[] = ""; // Twitter password
// Function to post a twitter update
void postTwitterUpdate(int sock, PCSTR url) {
char method[] = "POST";
char host[] = "api.twitter.com";
char hosturl[] = "/1/statuses/update.json";
char useragent[] = "NetBurner";
char update[] = "status=hello+world\r\n";
// Generate username/password string
char unpw[64];
char p64Buff[64];
Base64Encode((PBYTE) unpw, siprintf(unpw, "%s:%s", un, pw), p64Buff);
// Getting IP Address
IPADDR DestIP_Addr;
while ((DestIP_Addr = GetIPAddress(host)) == 0) {
OSTimeDly(TICKS_PER_SECOND * 5);
}
// Building POST Command
char cmd[1024];
int sizeOfMethod = 0;
sizeOfMethod = siprintf(cmd,
"%s %s HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: %s\r\n"
"Content-Length: %d\r\n"
"Authorization: Basic %s\r\n"
"\r\n"
"%s",
method, hosturl, host, useragent, sizeof(update),p64Buff, update);
// Sending POST
int fd = connect(DestIP_Addr, 0, 80, 5 * TICKS_PER_SECOND);
write(fd, cmd, sizeOfMethod);
// Closing Socket
close(fd);
}
• status. Required. The text of your status update. URL encode as necessary. Statuses over 140 characters will cause a 403 error to be returned from the API.
• in_reply_to_status_id. Optional. The ID of an existing status that the update is in reply to.
Note: This parameter will be ignored unless the author of the tweet this parameter references is mentioned within the status text. Therefore, you must include @username, where username is the author of the referenced tweet, within the update.
• lat. Optional. The location's latitude that this tweet refers to. The valid ranges for latitude is -90.0 to +90.0 (North is positive) inclusive. This parameter will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding long parameter with this tweet.
• long. Optional. The location's longitude that this tweet refers to. The valid ranges for longitude is -180.0 to +180.0 (East is positive) inclusive. This parameter will be ignored if outside that range, if it is not a number, if geo_enabled is disabled, or if there not a corresponding lat parameter with this tweet.