Webserver and twitter

Hi there,

I have tried the Arduino web server (with static ip address). I also tried out sending twitter by using thingspeak API (uses dhcp).

I want to know is it doable to combine these two in a project?
For example : an html button on a page hosted by the arduino server. It send a tweet when the button pressed.

I am unable to get it working, is it because my web server is using static ip?
If this is the issue, I would stop trying as my current network I am unable to try the port forwarding.

Correct me if I am wrong, I notice that to create html file, it send a html header. And for the API in send another header. What are these header actually?

Do advise. Excuse my English.

Do advise.

I advise you to post your code.

nsmf:
Hi there,

I have tried the Arduino web server (with static ip address). I also tried out sending twitter by using thingspeak API (uses dhcp).

I want to know is it doable to combine these two in a project?

You say you have 'tried'. Did you actually get both of these working (separately) on an Arduino? That is a prerequisite to getting them working together.

Yes I manage to do the webserver and tweet but separately.

Here is the code I use to send tweet. I am using thingSpeak API key.

#include <SPI.h>
#include <Ethernet.h>

// Local Network Settings
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// ThingSpeak Settings
char thingSpeakAddress[] = "api.thingspeak.com";
String thingtweetAPIKey = "MYAPIKEY ";    // here I put my API key from thingSpeak

// Variable Setup
long lastConnectionTime = 0;
boolean lastConnected = false;
int failedCounter = 0;
int tweetID = 0;
String tweetThis = "";

// Initialize Arduino Ethernet Client
EthernetClient client;

void setup()
{
  // Start Serial for debugging on the Serial Monitor
  Serial.begin(9600);

  startEthernet();
  
  delay(1000);
  
  // Update Twitter via ThingTweet
  tweetID = random(100);
  tweetThis += "Hello. #";
  tweetThis += tweetID;
  Serial.println(tweetID);
  updateTwitterStatus(tweetThis);
}

void loop()
{
  // Print Update Response to Serial Monitor
  if (client.available()){
    char c = client.read();
    Serial.print(c);
  }

  // Disconnect from ThingSpeak
  if (!client.connected() && lastConnected){
    Serial.println("...disconnected");
    Serial.println();
    
    client.stop();
  }
  // Check if Arduino Ethernet needs to be restarted
  if (failedCounter > 3 ) {startEthernet();}
  
  lastConnected = client.connected();
}

void updateTwitterStatus(String tsData)
{
  if (client.connect(thingSpeakAddress, 80)){
    // Create HTTP POST Data
    tsData = "api_key="+thingtweetAPIKey+"&status="+tsData;
            
    client.print("POST /apps/thingtweet/1/statuses/update HTTP/1.1\n");
    client.print("Host: api.thingspeak.com\n");
    client.print("Connection: close\n");
    client.print("Content-Type: application/x-www-form-urlencoded\n");
    client.print("Content-Length: ");
    client.print(tsData.length());
    client.print("\n\n");

    client.print(tsData);
    
    lastConnectionTime = millis();
    
    if (client.connected()){
      Serial.println("Connecting to ThingSpeak...");
      Serial.println();
      
      failedCounter = 0;
    }
    else{
      failedCounter++;
  
      Serial.println("Connection to ThingSpeak failed ("+String(failedCounter, DEC)+")");
      Serial.println();
    }
    
  }
  else
  {
    failedCounter++;
    Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")");
    Serial.println();
    lastConnectionTime = millis();
  }
}

void startEthernet()
{
  client.stop();
  Serial.println("Connecting Arduino to network...");
  Serial.println();
  delay(1000);
  // Connect to network amd obtain an IP address using DHCP
  if (Ethernet.begin(mac) == 0)
  {
    Serial.println("DHCP Failed, reset Arduino to try again");
    Serial.println();
  }
  else
  {
    Serial.println("Arduino connected to network using DHCP");
    Serial.println();
  }
  
  delay(1000);
}

This is the code of my failed attempt to combine them. I comment out few parts, so just the web server are working.

#include <SPI.h>
#include <Ethernet.h>

EthernetServer server (80);
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {10, 100, 156, 61};
byte gateway[] = {10, 100, 156, 62};
byte subnet[] = { 255, 255, 255, 192 };

// ThingSpeak Settings
char thingSpeakAddress[] = "api.thingspeak.com";

String thingtweetAPIKey = "MYAPIKEY ";    // here I put my API key from thingSpeak

int piezoPin = 9;
String inString = String (100);
// Variable Setup
String tweetThis = "";
boolean lastConnected = false;
long lastConnectionTime = 0;
int prevID=0, tweetID = 0, failedCounter=0;

//FUNCTION DECLARATIONS
void header(EthernetClient);
void body(EthernetClient);
void footer(EthernetClient);
//tweet function
void startTweeting();
void startEthernet();

EthernetClient clientTweet;

void setup(){
  Serial.begin(9600);
  //start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  
  pinMode(piezoPin,OUTPUT);
}

void loop(){
  EthernetClient client = server.available(); //listen for incoming clients
  
  if(client){
    Serial.println("Got a client");
    Serial.print(inString);
    
    boolean current_line_is_blank = true;
    
    while(client.connected()){
      
      if(client.available()){
        char c = client.read();

        if (inString.length() < 100) {
          inString.concat(c);
        } 
        
        //then the request is over:
        if (c == '\n' && current_line_is_blank){
          //send a standard http response header
          header(client);
          body(client);
          footer(client);
          break;
        }
        
        if (c == '\n') {
          // we're starting a new line
          current_line_is_blank = true;
        } 
        else if (c != '\r') {
          current_line_is_blank = false;  // we've gotten a character on the current line
        }
        
      }//if
    }//while
    delay(1);
    client.stop(); //close the connection
    inString = "";
  }

  //startTweeting();
}  // loop - end


void startTweeting(){
  do{
    tweetID = random(1000);
  }while(prevID==tweetID);
  tweetThis = "Hello "; 
  tweetThis += "#"; tweetThis += tweetID;
  
  startEthernet();
  delay(1000);
  updateTwitterStatus(tweetThis);
}

void startEthernet(){
}

void updateTwitterStatus(String tsData){
  if (clientTweet.connect(thingSpeakAddress, 80))
  {
    // Create HTTP POST Data
    tsData = "api_key="+thingtweetAPIKey+"&status="+tsData;
            
    clientTweet.print("POST /apps/thingtweet/1/statuses/update HTTP/1.1\n");
    clientTweet.print("Host: api.thingspeak.com\n");
    clientTweet.print("Connection: close\n");
    clientTweet.print("Content-Type: application/x-www-form-urlencoded\n");
    clientTweet.print("Content-Length: ");
    clientTweet.print(tsData.length());
    clientTweet.print("\n\n");

    clientTweet.print(tsData);
    lastConnectionTime = millis();
    
    if (clientTweet.connected()){
      Serial.println("Connecting to ThingSpeak...");
      Serial.println();
      failedCounter = 0;
    }
    else{
      failedCounter++;
      Serial.println("Connection to ThingSpeak failed ("+String(failedCounter, DEC)+")");
      Serial.println();
    }
  }
  else{
    failedCounter++;
    Serial.println("Connection to ThingSpeak Failed ("+String(failedCounter, DEC)+")");
    Serial.println();
    lastConnectionTime = millis();
  }
} // updateTwitterStatus - end



void header(EthernetClient thisClient){
  thisClient.print("HTTP/1.1 200 OK\n");
  thisClient.print("Content-Type: text/html\n\n");
  thisClient.print("<head><title>project 238</title></head><body>\n");
}

void footer(EthernetClient thisClient){
  thisClient.print("</body></html>\n");
}

void body(EthernetClient thisClient){
    thisClient.println("<p>NSMF</p>");
    thisClient.println(F("<form method=\"get\">"));
    thisClient.println(F("   <fieldset>"));
    thisClient.println(F("   <legend>Send tweet</legend>"));
    thisClient.println(F("   <input type=\"hidden\" name=\"tweet\" value=\"on\">
"));
    thisClient.println(F("   <button type=\"submit\">Tweet</button>"));
    thisClient.println(F("   </fieldset>"));
    thisClient.println(F("</form>"));
    thisClient.println(F(""));
    thisClient.println(F(""));
}

I would have thought it made more sense to put the call to startTweeting(); in the block of code that executes when you receive an HTTP request, not at the bottom of loop() where it would be executed repeatedly.

I don't know what the piezoPin is for but I suggest you remove all references to that since it wasn't present in the sketch that successfully sent a tweet.

I suggest you reinstate the code in setup() to send a single hard-coded tweet after the rest of the initialisation has completed and confirm that still works before you try to make this happen in response to an HTTP request.

I recommend that you stop using the String class since it can cause memory leaks leading to stability problems. All you need is sprintf() to print your string to a char array variable and to build the URL string.

Basic web client/server code that might be of interest.

//zoomkat 12-08-11, combined client and server
//simple button GET with iframe code
//for use with IDE 1.0
//open serial monitor and send an g to test client and
//see what the arduino client/server receives
//web page buttons make pin 5 high/low
//use the \ slash to escape the " in the html 
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields
//note that the below bug fix may be required
// http://code.google.com/p/arduino/issues/detail?id=605

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
IPAddress ip(192,168,1,102); // ip in lan
IPAddress gateway(192,168,1,1); // internet access via router
IPAddress subnet(255,255,255,0); //subnet mask
//IPAddress myserver(208,104,2,86); // zoomkat web page
EthernetServer server(84); //server port
EthernetClient client;
String readString; 
char serverName[] = "web.comporium.net"; // zoomkat's test web page server

//////////////////////

void setup(){

  pinMode(5, OUTPUT); //pin 5 selected to control
  Ethernet.begin(mac,ip,gateway,gateway,subnet); 
  server.begin();
  Serial.begin(9600); 
  Serial.println("server/client 1.0 test 12/08/11"); // keep track of what is loaded
  Serial.println("Send an g in serial monitor to test client"); // what to do to test client

  /*if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    while(true);
  }*/

}

void loop(){
  // check for serial input
  if (Serial.available() > 0) 
  {
    byte inChar;
    inChar = Serial.read();
    if(inChar == 'g')
    {
      sendGET(); // call sendGET function
    }
  }  

  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string 
          readString += c; 
          //Serial.print(c);
        } 

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging 

            //now output HTML data header
          if(readString.indexOf('?') >=0) { //don't send new page
            client.println("HTTP/1.1 204 Zoomkat");
            client.println();
            client.println();  
          }
          else {
            client.println("HTTP/1.1 200 OK"); //send new page
            client.println("Content-Type: text/html");
            client.println();

            client.println("<HTML>");
            client.println("<HEAD>");
            client.println("<TITLE>Arduino GET test page</TITLE>");
            client.println("</HEAD>");
            client.println("<BODY>");

            client.println("<H1>Zoomkat's simple Arduino 1.0 button</H1>");

            client.println("<a href=\"/?on\" target=\"inlineframe\">ON</a>"); 
            client.println("<a href=\"/?off\" target=\"inlineframe\">OFF</a>"); 

            //client.println("<IFRAME name=inlineframe src=\"res://D:/WINDOWS/dnserror.htm\" width=1 height=1\">");
            client.println("<IFRAME name=inlineframe style=\"display:none\" >");          
            client.println("</IFRAME>");

            client.println("</BODY>");
            client.println("</HTML>");
          }

          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on") >0)//checks for on
          {
            digitalWrite(5, HIGH);    // set pin 5 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(5, LOW);    // set pin 5 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
} 

//////////////////////////
void sendGET() //client function to send/receive GET request data.
{
  if (client.connect(serverName, 80)) {
    Serial.println("connected");
    client.println("GET /~shb/arduino.txt HTTP/1.0");
    client.println();
  } 
  else {
    Serial.println("connection failed");
    Serial.println();
  }

  while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read();
    Serial.print(c);
  }

  Serial.println();
  Serial.println("disconnecting.");
  Serial.println("==================");
  Serial.println();
  client.stop();

}