DI WIFI Week 2: News Feed From Google

WIFI Week 2 Header

WIFI-WEEK-2---News-from-Google to your NXT over the internet

News from Google to your LEGO MINDSTORMS NXT

We’re finishing up WIFI Week 2 with a small program that lets you download headlines from Google News and display them on the NXT using the Wifi Module.

Like our weather program, this program pulls down XML information on Google News, and sorts out where the headlines are, displaying them on the NXT Screen.

Google provides all sorts of data (that’s what they do!) so this example can serve as a way to get your LEGO MINDSTORMS NXT to interact with the interwebs, via the Wifi Module.

The project code is posted below.  The code is in RobotC but is heavily commented.

DIWIFI-News.c

[sourcecode language=”cpp”] // News Ticker for the LEGO MINDSTORMS NXT
//
// DIWFI News uses the Dexter Industries Wifi Sensor to get the
// latest headlines from from Google.com
//
// ** Run this program with the RobotC Debugging Stream On to view any errors.
// ** Run AFTER connecting to a Wifi network!
// ** For more information visit http://www.dexterindustries.com/
//
// This program uses HTTP GET examples to retrieve the news headlines and
// display them on the NXT. The news is retrieved in XML format. We wrote some
// simple routines to fish out the headlines from the XML.
//
// See more about the Dexter Industries Wifi Sensor for the
// LEGO MINDSTORMS NXT here: http://www.dexterindustries.com/wifi.html
// This is the website we’re going after: http://www.google.com/ig/api?news
//////////////////////////////////////////////////////////////////////////////////////////////////////

#include "drivers/common.h"
#include "DIWIFI-News.h"

void news(){

closeAllConns(); // Housekeeping: Close any open connections.
clear_read_buffer(); // Housekeeping: Clear out the buffer.
int CID = 0; // Connection Identification
CID = start_TCP_client(); // We start the HTTP client here. Now we’re acting as a client, not a server.
wait10Msec(100); // Necessary pause.
GetNews(CID); // This kicks off the meat of the project. We’re starting to send a tweet through the connection ID.
read_news_data(); // Load the news data into an array so we can deal with it.
print_news(); // This function goes through the array, gets the headlines
// And then prints them to the debug screen and on the NXT screen.
}

task main()
{
// ** MAKE SURE YOUR NXT IS CONNECTED TO THE INTERNET!! ** //
clear_read_buffer();
while(true) news(); // Get the headlines all day!
}

[/sourcecode]

DIWIFI-News.h

[sourcecode language=”cpp”]

string IP_num = "173.194.73.106"; // Google IP Number
ubyte byteStart[] = {27, ‘S’, ‘0’}; // Begin a Transmission
ubyte byteEnd[] = {27, ‘E’}; // End a transmission
ubyte BytesRead[8]; // Placeholder array for a function below
char news_data[10000]; // Weather Data goes into this array.
int index = 0; // This will be the position index in news_data
int lastPosn = 0; // Last position we were in in the array when looking for something.

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Clear Read Buffer
// Run this to clear out the reading buffer.
// Simply sends a carriage return, then clears the buffer out.
////////////////////////////////////////////////////////////////////////////////////////////////////////

void clear_read_buffer()
{
ubyte nData[] = {13};
nxtWriteRawHS(nData[0], 1); // Send the carriage return
wait10Msec(100);
while(BytesRead[0] < 0){
nxtReadRawHS(BytesRead[0], 1); // Read the response. Probably an error.
}
wait10Msec(100);
}

// This function writes a string to the DebugStream and Port4
// We wrote this out because it is easier to recognize and see
// strings; easier than working with arrays of characters.
void writeStr(string sData)
{
ubyte byteData = 0;
for(int i = 0; i < strlen(sData); i++) { byteData = strIndex(sData, i); nxtWriteRawHS(byteData, 1); writeDebugStream("%c", byteData); // Critical for debugging. Make sure you’re getting some time in there // to read what you wrote. while(nxtHS_Status == HS_SENDING) wait1Msec(1); wait1Msec(1); // With } } // // This function just writes a line break to DebugStream and Port4. // It is necessary to have this in RobotC because strings are limited to 17 characters // and sometimes you will need to send commands longer than 17 characters. void writeLineBreak() { writeDebugStream("%c", 13); ubyte newline = 0x0D; nxtWriteRawHS(newline, 1); } //////////////////////////////////////////////////////////////////////////////////////////////////////// // Send Carriage Return, New Line // This is used in the HTTP request //////////////////////////////////////////////////////////////////////////////////////////////////////// void crln() { writeDebugStream("%c", 13); writeDebugStream("%c", 10); // Display this on the debug for our information. ubyte newline[] = {0x0D, 0x0A}; // Carriage return and then line feed. nxtWriteRawHS(newline, 2); wait1Msec(5); // ABSOLUTELY CRITICAL. We added this because // we found that in line-feeds, the first bytes of the next transmission get // dropped. VERY IMPORTANT TO HAVE THIS DELAY IN HERE. } //////////////////////////////////////////////////////////////////////////////////////////////////////// // Receive Bytes // Reads whatever is in the buffer and prints to debug //////////////////////////////////////////////////////////////////////////////////////////////////////// void Receive(bool wait=false) { if (wait) while (nxtGetAvailHSBytes() == 0) wait1Msec(5); while (nxtGetAvailHSBytes() > 0) {
nxtReadRawHS(BytesRead[0], 1);
// writeDebugStream("%c", BytesRead[0]);
wait1Msec(1);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Housekeeping: Close down the Connections
////////////////////////////////////////////////////////////////////////////////////////////////////////
void closeAllConns() {
writeDebugStreamLine("closeAllCons");
clear_read_buffer();
writeStr("at+ncloseall");
writeLineBreak();
wait10Msec(10);
Receive(true);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Connect to google via TCP.
// Open up a client connection with the Google Server.
////////////////////////////////////////////////////////////////////////////////////////////////////////
int start_TCP_client() {
int CID = 0;
bool connected = false; // This will tell us if we’re connected or not.
string port = ",80";

while(!connected){ // Do this over and over again until we get a connection.
writeStr("AT+NCTCP=");
writeStr(IP_num);
writeStr(port);
writeLineBreak();

// Don’t replace the following code with a Receive function.
// This code picks out the CID number.
while (nxtGetAvailHSBytes() == 0) wait1Msec(5);
while (nxtGetAvailHSBytes() > 0) {
nxtReadRawHS(BytesRead[0], 1);
writeDebugStream("%c", BytesRead[0]);
if(BytesRead[0] < 58 && BytesRead[0] > 47){ // So if it’s a number . . .
CID = BytesRead[0]-48; // Works for connections 0 through 9.
connected = true;
}
wait1Msec(2);
}
}
return CID;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Send information to Google to get news headlines.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void GetNews(int CID) {
wait1Msec(1000);

nxtWriteRawHS(byteStart, 3);
writeDebugStream("%c", byteStart, 2);
writeDebugStreamLine("%c", (CID+48));

wait1Msec(200);
// Get this –> http://www.google.com/ig/api?news
writeStr("GET /ig/api?"); // This code sends the location on the google server we’re looking for.
writeStr("news"); // and more
writeStr(" HTTP/1.1"); // And the version of HTTP we’re using.
crln();

writeStr("User-Agent: "); // Necessary for HTTP Transmission.
writeStr("DIWifi");
crln();

writeStr("Host: ");
writeStr("www.google.com"); // We’re looking at Google.
crln();
crln();

wait1Msec(10);
nxtWriteRawHS(byteEnd, 2); // End the HTTP transmission.
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Utility: Load up a response into a large array.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void Receive2Array(bool wait=false)
{
if (wait)
while (nxtGetAvailHSBytes() == 0) wait1Msec(5);

while (nxtGetAvailHSBytes() > 0) {
nxtReadRawHS(BytesRead[0], 1);
//writeDebugStream("%c", BytesRead[0]);
news_data[index] = BytesRead[0];
index++;
wait1Msec(1);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Read the weather data from Port4.
// Put it into news_data[].
////////////////////////////////////////////////////////////////////////////////////////////////////////
void read_news_data(){
while(true){ // Do this until you get a break.
Receive2Array(true); // This function loads the buffer into an array.
if(news_data[index-1] == 69 && news_data[index-2] == 27) break; // This looks for the E Sequence that signals the end of a transmission.
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Find the the position of the string.
// Returns the postion in the news_data
// array of the string of characters we’re looking for
////////////////////////////////////////////////////////////////////////////////////////////////////////
int find_string_posn(string stringIN, int start_posn){
for(int i = start_posn; i < (sizeof(news_data)-20); i++){
if(news_data[i] == 0) break;
byte array_holder[20];
memset(array_holder, 0, 20);
// Load up an array subsection of weather.
for(int j = 0; j< (strlen(stringIN)); j++){ array_holder[j] = news_data[j+i]; } string posn; StringFromChars(posn, array_holder); if(strcmp(posn, stringIN) == 0){ return i; } } return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////////// // Find the incoming string, pring it on the particular line. // Print also on the Debug screen. //////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////// // Find the incoming string, pring it on the particular line. // Print also on the Debug screen. //////////////////////////////////////////////////////////////////////////////////////////////////////// void find_and_print(string findme, string Header, int DispLine){ int start_posn = find_string_posn(findme, lastPosn); string findend = "/"; int end_posn = find_string_posn(findend, start_posn); start_posn = start_posn+strlen(findme)+1; // Points to the beggining of the string end_posn = end_posn-1; // Points to the end of the string. int strLength = end_posn-start_posn; // Length of the string we’re looking for. byte condition[150]; memset(condition, 0, sizeof(condition)); if(strLength > 0){
for(int i=0; i < strLength; i++){
condition[i] = news_data[start_posn+i];
}

int i = 0; // First: write the string to the Debug Scree.
while(condition[i] != 0){ // End of the string will be singified by a 0x00
writeDebugStream("%c", condition[i]); // Write it all to the debug stream, byte by byte.
i++;
}
writeDebugStreamLine(" ");
i = 0;
int x = 0;
int linenumber = 0;
byte array_holder[18];

while(condition[i] != 0){ // This code may look confusing, but the whole idea
array_holder[x] = condition[i]; // Is to get it to wrap around on the screen. So we break it out
x++; // into 17 byte long character arrays, and then turn them into
if(x == 15){ // strings, and then print them on the screen.
x = 0;
linenumber++;
nxtDisplayClearTextLine(linenumber);
string headlineline;
StringFromChars(headlineline, array_holder);
nxtDisplayString(linenumber, "%s", headlineline);
wait1Msec(250);
}
i++;
}
}
lastPosn = end_posn;
wait1Msec(2000); // Display the headline for 2 seconds.
eraseDisplay(); // Clear it out, start over.
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// Print the weather.
////////////////////////////////////////////////////////////////////////////////////////////////////////
void print_news(){
find_and_print("title data=", "1", 1); // Get Headline 1
find_and_print("title data=", "2", 2); // Get Headline 2
find_and_print("title data=", "3", 3); // Get Headline 3
find_and_print("title data=", "4", 4); // ETC
find_and_print("title data=", "5", 5);
find_and_print("title data=", "6", 6);
find_and_print("title data=", "7", 7);
find_and_print("title data=", "8", 8);
index = 0; // Reset the count so we can do this over and over again.
memset(news_data, 0, sizeof(news_data)); // Reset the array to zeros. Good housekeeping.
}
[/sourcecode]

0 Comments

Leave a reply