Go Down

Topic: Arduino WiFi Shield (Read 3194 times) previous topic - next topic

kazimurtaza

Dec 18, 2012, 09:10 am Last Edit: Dec 18, 2012, 10:35 am by kazimurtaza Reason: 1
hello, I recently bought Arduino WiFi Shield, and I cant help but notice its not working straight,
what I require of it is that I send data from android in this form [8=128, 9=0] and it at least receives it,
and write in Serial. what I get is;
//In Serial
Code: [Select]

new client

POST / HTTP/1.1
Content-Length: 9
Content-Type: application/x-www-form-urlencoded
Host: 10.0.0.10
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)


client disonnected


and when I send again from android;

Code: [Select]
new client

8=128&9=0POST / HTTP/1.1
Content-Length: 26
Content-Type: application/x-www-form-urlencoded
Host: 10.0.0.10
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)


client disonnected


you can see in second block before POST my needed values are present it some how remain in buffer or something.

code I am using in Arduino is;

Code: [Select]

#include <SPI.h>
#include <WiFi.h>


char ssid[] = "Kazi-House";      //  your network SSID (name)
char pass[] = "123456789";   // your network password
int keyIndex = 0;                 // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;

WiFiServer server(80);

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    while(true);
  }

  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:   
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(1000);
  }
  server.begin();
  // you're connected now, so print out the status:
  printWifiStatus();
  pinMode(8,OUTPUT);
}


void loop() {
  // listen for incoming clients
  WiFiClient client = server.available();
  if (client) {
    Serial.println("");
    Serial.println("new client");
    Serial.println("");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("Hello");
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    delay(10);
    client.stop();
    Serial.println("");
    Serial.println("client disonnected");
    Serial.println("");
  }
}
////////////////////////////////////////////////////////////////
void printWifiStatus() {
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}



is my android code required ?

EDIT: is there no proper way to communicate with WiFi Shield using Android, Json or some sort, current code takes about 2secs

pgaston

I got this to work - on the Android using 'XMLHTTPRequest' in my javascript code talking to an Arduino running wifiserver.   My way of communicating information to the arduino is to make the url contain the information to send through url parameters, e.g., http://192.168.1.100/arduino.htm?x=1&y=128&z=545   .     On the arduino side the first line of the http request you receive will be a GET \arduino.htm?x-1&y=128&z=545 - you'll need to parse this out to get your information there.

The Arduino can respond with information back to the Android be sending it's payload at the end of the request.    I send back JSON, but you can send back anything and parse it on the Android.

The key question I have (didn't get an answer to my post a couple of days back btw - I post my code there as well for above) is that the wifi shield/wifiserver is amazingly slow - I timed it out at 1.3 seconds for the code to run, responding to this httprequest.    Clearly not usuable.    Not sure if it's my fault (e.g., not uploading the most recent code to the wifi shield) or a poor implementation on the shield - would be nice to have someone weigh in on that.

Best - p


pylon

The problem with your code is that your just reading the header of the client's request and then send the response immediately, you don't care about the type of request (GET or POST) or even read the whole request. If you handle the request correctly, you'll probably be successful.

kazimurtaza


I got this to work - on the Android using 'XMLHTTPRequest' in my javascript code talking to an Arduino running wifiserver.   My way of communicating information to the arduino is to make the url contain the information to send through url parameters, e.g., http://192.168.1.100/arduino.htm?x=1&y=128&z=545   .     On the arduino side the first line of the http request you receive will be a GET \arduino.htm?x-1&y=128&z=545 - you'll need to parse this out to get your information there.

The Arduino can respond with information back to the Android be sending it's payload at the end of the request.    I send back JSON, but you can send back anything and parse it on the Android.

The key question I have (didn't get an answer to my post a couple of days back btw - I post my code there as well for above) is that the wifi shield/wifiserver is amazingly slow - I timed it out at 1.3 seconds for the code to run, responding to this httprequest.    Clearly not usuable.    Not sure if it's my fault (e.g., not uploading the most recent code to the wifi shield) or a poor implementation on the shield - would be nice to have someone weigh in on that.

Best - p




could you share your Arduino code, I want to see how are you parsing, and yes its slow, when I click a button on android it takes approx. 3 - 4 sec for it to reach Arduino and on 5th sec it executes desired action,
below is the new working code, but still glitchy, I guess WiFi shield is to blame because sometimes I have to press the button twice for it to catch. although "ajson" seemed promising but I could not got it to work with WiFi, its was perfect, but in beta stage for now.

btw my project is controlling lights and all :)

Code: [Select]

      #include <SPI.h>
      #include <WiFi.h>
     
     
      char ssid[] = "Kazi-House";      //  your network SSID (name)
      char pass[] = "123456789";   // your network password
      int keyIndex = 0;                 // your network key Index number (needed only for WEP)
     
      int status = WL_IDLE_STATUS;
     
      WiFiServer server(80);
     
      void setup() {
        //Initialize serial and wait for port to open:
        Serial.begin(9600);
        while (!Serial) {
          ; // wait for serial port to connect. Needed for Leonardo only
        }
       
        // check for the presence of the shield:
        if (WiFi.status() == WL_NO_SHIELD) {
          Serial.println("WiFi shield not present");
          // don't continue:
          while(true);
        }
       
        // attempt to connect to Wifi network:
        while ( status != WL_CONNECTED) {
          Serial.print("Attempting to connect to SSID: ");
          Serial.println(ssid);
          // Connect to WPA/WPA2 network. Change this line if using open or WEP network:   
          status = WiFi.begin(ssid, pass);
     
          // wait 10 seconds for connection:
          delay(10000);
        }
        server.begin();
        // you're connected now, so print out the status:
        printWifiStatus();
        pinMode(49, OUTPUT);
      }
     
     
      void loop() {
        // listen for incoming clients
        WiFiClient client = server.available();
        if (client) {
          //Serial.println("new client");
          // an http request ends with a blank line
          boolean currentLineIsBlank = true;
          while (client.connected()) {
            if (client.available()) {
              char c = client.read();
              //Serial.write(c);
              if(c=='8'){
                if(client.read() == '=') {
                  char onoff = client.read();
                  if( onoff == '1'){
                    Serial.println("Lamp On");
                    digitalWrite(49,HIGH);
                  }
                  else if(onoff == '0'){
                    Serial.println("Lamp Off");
                    digitalWrite(49,LOW);
                  }
                }
              }
              // if you've gotten to the end of the line (received a newline
              // character) and the line is blank, the http request has ended,
              // so you can send a reply
              if (c == '\n' && currentLineIsBlank) {
                // send a standard http response header
                client.println("HTTP/1.1 200 OK");
                client.println("Content-Type: text/html");
                client.println("Connnection: close");
                client.println();
                client.println("<!DOCTYPE HTML>");
                client.println("<html>");
                // add a meta refresh tag, so the browser pulls again every 5 seconds:
                client.println("<meta http-equiv=\"refresh\" content=\"5\">");
                // output the value of each analog input pin
                client.println("</html>");
                 break;
              }
              if (c == '\n') {
                // you're starting a new line
                currentLineIsBlank = true;
              }
              else if (c != '\r') {
                // you've gotten a character on the current line
                currentLineIsBlank = false;
              }
            }
          }
          // give the web browser time to receive the data
          delay(1);
            // close the connection:
            client.stop();
            //Serial.println("client disonnected");
        }
      }
     
     
      void printWifiStatus() {
        // print your WiFi shield's IP address:
        IPAddress ip = WiFi.localIP();
        Serial.print("IP Address: ");
        Serial.println(ip);
        }


Bluetooth is faster than this :(

kazimurtaza


The problem with your code is that your just reading the header of the client's request and then send the response immediately, you don't care about the type of request (GET or POST) or even read the whole request. If you handle the request correctly, you'll probably be successful.

could you explain more on than, may b with a code, if its not to much trouble.
thank you.

kazimurtaza

just so you guys could understand the whole app, I will the android side of code as well;

MainActivity
Code: [Select]

package com.lamp.test.v1;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import com.mycar.other.ConnectionManager;
import com.mycar.other.HttpManager;

public class MainActivity extends Activity implements OnClickListener {

public Button on;
public Button off;

public List<NameValuePair> data;

@SuppressLint({ "NewApi", "NewApi", "NewApi" })
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

setTitle("My Lamp Test v1");

this.on = (Button) findViewById(R.id.on);
this.off = (Button) findViewById(R.id.off);

this.on.setOnClickListener(this);
this.off.setOnClickListener(this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

public void onClick(View v) {

switch(v.getId()){
case R.id.on:
//final Handler myHandler = new Handler();
(new Thread(new Runnable() {
public void run() {
lightOn();
}
public List<NameValuePair> data;
private void lightOn() {
if(ConnectionManager.isOnline(getApplicationContext())){
this.data = new ArrayList<NameValuePair>(1);
this.data.add(new BasicNameValuePair("8", "1"));
//call the service
@SuppressWarnings("unused")
InputStream is = HttpManager.callService(getString(R.string.url), this.data);
}
}
})).start();
break;
case R.id.off:
//final Handler myHandler1 = new Handler();
(new Thread(new Runnable() {
public void run() {
lightOff();
}
public List<NameValuePair> data;
private void lightOff() {
if(ConnectionManager.isOnline(getApplicationContext())){
this.data = new ArrayList<NameValuePair>(1);
this.data.add(new BasicNameValuePair("8", "0"));
//call the service
@SuppressWarnings("unused")
InputStream is = HttpManager.callService(getString(R.string.url), this.data);
}
}
})).start();
break;
}
}

}



HttpManager
Code: [Select]

package com.mycar.other;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;

import android.util.Log;

public class HttpManager {
public static InputStream callService(String Url, List<NameValuePair> data){
HttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost(Url);
    try{
    httppost.setEntity(new UrlEncodedFormEntity(data));
    Log.v("Hello",String.valueOf(data));
    //HttpResponse response =
    httpclient.execute(httppost);
        //HttpEntity entity = response.getEntity();
       // return entity.getContent();
    } catch (ClientProtocolException e) {
    Log.v("Came in here","Exception for protocol");
    } catch (IOException e) {
    Log.v("Came in here with IOEXception",e.getMessage());
    }
    return null;
}
}


Connection Manager
Code: [Select]

package com.mycar.other;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

public class ConnectionManager {
public static boolean isOnline(Context ctx) {
    ConnectivityManager cm =
        (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnectedOrConnecting()) {
        return true;
    }
    return false;
}
}


if you have some suggestion on how to make this more robust let me know .. this is my first test, upon perfecting it, I will convert my whole room :)

pylon

Quote
could you explain more on than, may b with a code, if its not to much trouble.
thank you.


I have no ready made code for an HTTP server accepting POST requests on the Arduino. If it's possible for you, it's much easier to parse a GET request than to provide all the code to correctly parse and analyze a POST request. So change the HttpPost to a HttpGet and send the data in the query parameter of the URL.

kazimurtaza

if its not much trouble I was hoping to see how are you parsing get request on arduino :)

pgaston

Here's my code for parsing out and responding to a GET request...

Near the top
Code: [Select]

char aSet[] = "GET /setServo.htm";             // set the Servos and also return sensor readings
char aGet[] = "GET /getReadings.htm";       // just return sensor readings
char aSetRudder[] = "rudder=";
char aSetSail[] = "sail=";

// http://192.168.1.101/setServo.htm?rudder=45&sail=70   
// http://192.168.1.101/getReadings.htm


Here's code that's called from the 'loop'
Code: [Select]

  WiFiClient client = server.available();    // listen for incoming clients
  if (client) {
    int index=0;
    int lineNo=0;
    boolean weLike = false;  // only respond to messages that pertain to us (i.e., would like to ignore favicon.ico requests if possible...
   
    //  Serial.println("new client: ");    // try to reduce extra cruft to speed things up???
   
    long start = millis();
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();      // read character
    //    Serial.print(c);
        if ( c != '\r' ) {           // ignore \r characters
          inBuff[index++] = c;       // save line in buffer
          if ( index >= 80 )         // ignore really long lines
            index=70;
          if ( c == '\n' )           // make into true string
            inBuff[index] = 0;

          if (c == '\n' && (index <= 1)) {  // http request ends with a blank line, implies time for us to respond - always send back our readings           
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Access-Control-Allow-Origin: *");    // to allow XMLHTTPRequest       
            client.println("Connnection: close");
            client.println();
            if ( weLike )  {           
              int anaValue1 = analogRead(pinRelativeWind1);
              int anaValue2 = analogRead(pinRelativeWind2);
              int iWater1 = digitalRead(pinWater1);
              int iWater2 = digitalRead(pinWater2);
             
              client.print("{\"ArdRelativeWind1\":");
              client.print(anaValue1);
              client.print(",\"ArdRelativeWind2\":");
              client.print(anaValue2);
              client.print(",\"ArdWater1\":");
              client.print(iWater1);
              client.print(",\"ArdWater2\":");
              client.print(iWater2);
              client.println("}");
            } else {
              Serial.println("WE DO NOT LIKE!!");
            } 
            break;
          }
          if (c == '\n') {
            if ( lineNo == 0 )  {    // first line - this holds the GET url ...           
              char *get = strstr( inBuff, aGet);
              char *set = strstr( inBuff, aSet);             
              if ( get )  {                // just get values
                weLike = true;
              } else if ( set )  {    // read value to set servos
                 char *rudder = strstr( inBuff, aSetRudder);
                 char *sail = strstr( inBuff, aSetSail);
                 int iRudder = atoi( rudder + 7 );  // move past the 'rudder='
                 int iSail = atoi( sail + 5 );      // move past the 'sail='
                 if ( (iRudder>=0) && (iSail>=0) )  {  // dbl check for good values
                   vServosOut( iRudder, iSail );
                 }     
              }
            } else {
                 // skip line - other heading information
            }
           
            lineNo++;
            index=0;
          }
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    //  Serial.println("client disonnected");
     
    Serial.println("Msg:"+String(++iMsgCount)+",  elapsed: "+String(millis()-start)+" ms");
    iBlinkAction = !iBlinkAction;
    digitalWrite(pinLEDAction,iBlinkAction?HIGH:LOW);  // flips every time a request is received
  }


Not guaranteed to be efficient - but given how slow the wifiserver / wifi shield is it could go out for coffee halfway through and no one would notice...   :)


Go Up