Happy new year all :)
I am working on a home automation project using Arduino Uno and Android application what can communicate through my TP-Link router.
I am having a java.io.IOException: unexpected end of stream on Connection
once I send a query to the Arduino and I'm not being able to solve it.
01-01 16:51:47.771 10592-11256/com.projects.mahmoudmahdi.etherdroid E/EtherDroid: java.io.IOException: unexpected end of stream on Connection{192.168.1.215:80, proxy=DIRECT# hostAddress=192.168.1.215 cipherSuite=none protocol=http/1.1} (recycle count=0)
at com.android.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:210)
at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:80)
at com.android.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:904)
at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:788)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:443)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:388)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:501)
at com.projects.mahmoudmahdi.etherdroid.MainActivity$commandArduino.doInBackground(MainActivity.java:50)
at com.projects.mahmoudmahdi.etherdroid.MainActivity$commandArduino.doInBackground(MainActivity.java:31)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.io.EOFException: \n not found: size=0 content=...
at com.android.okhttp.okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:200)
at com.android.okhttp.internal.http.HttpConnection.readHeaders(HttpConnection.java:220)
at com.android.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:199)
at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:80)
at com.android.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:904)
at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:788)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:443)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:388)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:501)
at com.projects.mahmoudmahdi.etherdroid.MainActivity$commandArduino.doInBackground(MainActivity.java:50)
at com.projects.mahmoudmahdi.etherdroid.MainActivity$commandArduino.doInBackground(MainActivity.java:31)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
My Arduino Sketch:
#include <UIPEthernet.h>
int relay = 2;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 215 }; // ip in lan (that's what you need to use in your browser. (F("192.168.1.200"))
byte gateway[] = { 192, 168, 1, 10 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(80); //server port
String readString;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
pinMode(relay, OUTPUT);
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip, gateway, subnet);
server.begin();
Serial.print(F("server is at "));
Serial.println(Ethernet.localIP());
}
void loop() {
// Create a client connection
EthernetClient client = server.available();
if (client) {
//clearing string for next read
readString = "";
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
client.println("HTTP/1.1 200 OK"); //send new page
client.println("Content-Type: text/html");
//stopping client
client.stop();
//controls the Arduino if you press the buttons
if (readString.indexOf("?relay1on") > 0) {
digitalWrite(relay, LOW);
Serial.println("relay is on");
}
if (readString.indexOf("?relay1off") > 0) {
digitalWrite(relay, HIGH);
Serial.println("relay is off");
}
}
}
}
}
}
My Android Code:
package com.projects.mahmoudmahdi.etherdroid;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity implements OnClickListener {
private class commandArduino extends AsyncTask<URL, Void, Integer> {
#Override
protected Integer doInBackground(URL... url) {
int response = 0;
if (isNetworkAvailable()) {
// params comes from the execute() call: params[0] is the url.
try {
HttpURLConnection urlConnection = (HttpURLConnection) url[0].openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
switch (urlConnection.getResponseCode()) {
case HttpURLConnection.HTTP_OK:
Log.d("RESPONSE", "**OK**");
break; // fine, go on
case HttpURLConnection.HTTP_GATEWAY_TIMEOUT:
Log.d("RESPONSE", "**gateway timeout**");
break;// retry
case HttpURLConnection.HTTP_UNAVAILABLE:
Log.d("RESPONSE", "**unavailable**");
break;// retry, server is unstable
default:
Log.d("RESPONSE", "**unknown response code**.");
break; // abort
}
urlConnection.disconnect();
Log.d("RESPONSE", "Aborting download of dataset.");
} catch (Exception e) {
Log.e("EtherDroid", "STACKTRACE");
Log.e("EtherDroid", Log.getStackTraceString(e));
}
}
return response;
}
}
static boolean relay1 = false;
commandArduino cmdAdn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button Relay1 = (Button) findViewById(R.id.relay1);
Relay1.setOnClickListener(this);
}
private boolean isNetworkAvailable() {
boolean available = false;
/** Getting the system's connectivity service */
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
/** Getting active network interface to get the network's status */
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isAvailable())
available = true;
/** Returning the status of the network */
return available;
}
public void onClick(View thisView) {
cmdAdn = new commandArduino();
switch (thisView.getId()) {
case R.id.relay1:
if (!relay1) {
relay1 = true;
try {
cmdAdn.execute(new URL("http://192.168.1.215/?relay1on"));
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), "relay1 on", Toast.LENGTH_SHORT).show();
} else {
relay1 = false;
try {
cmdAdn.execute(new URL("http://192.168.1.215/?relay1off"));
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), "relay1 off", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
In general terms, you're missing:
Send data in the response
Giving time for the socket to send data before closing
Reading Android's response before closing the connection.
More in detail, make sure to send some data after establishing the connection:
client.println("HTTP/1.1 200 OK"); //send new page
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("</html>");
// Give it time to close
delay(1);
client.close();
Reference: https://www.arduino.cc/en/Tutorial/WebServer , here's the full example:
void loop() {
// listen for incoming clients
EthernetClient 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(); // NOTE: You're missing this in your code
Serial.write(c);
// 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("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
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 disconnected");
Ethernet.maintain();
}
}
Also, consider using json instead of html for Arduino's response. To do that, you'll need to change:
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.println();
client.println("{\"status\":\"ok\"}"); // Or whatever you want to change
Related
I am currently trying to send a message from my Android-Smartphone to a raspberry pi.
I implemented an Android-Client by the example code given here:
Really simple TCP client
I changed the ip-address an port so it works with my server running on the pi. This server is written in c and before switching to android, I implemented a C-Client which worked so far without any problems.
The server just needs to receive a message and then it prints it and stops, so it is very simple.
EDIT 3
I created new outputs for debugging and analysis, I may got an idea now what is not working. As far as I can see, the SendMessageTask is never executed.
The Server outputs are now:
Success - create socket
Success - Binding
Listening
Success - Accept
now it stalls, "reading..." is never printed! (should happen in the while loop)
In Android I receive the following neccessary outputs:
D/TCP Client: C: Connecting...
D/TcpOptimizer: TcpOptimizer-ON
--> Connection happened
When I push the Send button:
D/myMessage1: button pushed
D/myMessage: testing
But I do not get the messages which should be logged in the SendMessageTask
When I click the disconnect button the server prints:
Client disconnected
And now Android logs:
D/RESPONSE FROM SERVER: S: Received Message: 'null'
D/sendMessageTask: try to send message
D/TcpClient: Cannot send --> mBufferOut is null
Therefore my guess is, the SendMessageTask never runs until it fails due to disconnection, but why?
Edit 3 - End
This is the (edited) server code:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
int main(){
int welcomeSocket, newSocket, read_size;
char buffer[10000];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
welcomeSocket = socket(AF_INET, SOCK_STREAM, 0);
if (welcomeSocket == -1) {
printf("Could not create socket\n");
}else {
printf("Success - create socket\n");
}
/*---- Configure settings of the server address struct ----*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = INADDR_ANY;
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Bind the address struct to the socket ----*/
if(bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0){
printf("Error - Binding\n");
}else {
printf("Success - Binding\n");
}
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error\n");
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
if(newSocket < 0){
printf("Error - Accept\n");
}else {
printf("Success - Accept\n");
}
while( (read_size = recv(newSocket, buffer, 10000, 0)) > 0){
write(newSocket, buffer, strlen(buffer));
printf("reading...");
}
if(read_size == 0){
printf("Client disconnected");
fflush(stdout);
}
else if(read_size == -1){
printf("Error - recv failed");
}
return 0;
}
I am not quite sure if the parameters in
welcomeSocket = socket(AF_INET, SOCK_STREAM, 0);
are still correct?
The Client-Code in Android is:
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class TcpClient {
public static final String TAG = TcpClient.class.getSimpleName();
public static final String SERVER_IP = "192.168.4.1"; //server IP address
public static final int SERVER_PORT = 7891;
// message to send to the server
private String mServerMessage;
// sends message received notifications
private OnMessageReceived mMessageListener = null;
// while this is true, the server will continue running
private boolean mRun = false;
// used to send messages
private PrintWriter mBufferOut;
// used to read messages from the server
private BufferedReader mBufferIn;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TcpClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
*
* #param message text entered by client
*/
public void sendMessage(final String message) {
Runnable runnable = new Runnable() {
#Override
public void run() {
if (mBufferOut != null) {
Log.d(TAG, "Sending: " + message);
mBufferOut.println(message);
mBufferOut.flush();
}else{
Log.d(TAG, "Cannot send --> mBufferOut is null");
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
/**
* Close the connection and release the members
*/
public void stopClient() {
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.d("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVER_PORT);
try {
//sends the message to the server
mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//receives the message which the server sends back
mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in this while the client listens for the messages sent by the server
while (mRun) {
/*
mServerMessage = mBufferIn.readLine();
if (mServerMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(mServerMessage);
}
*/
}
Log.d("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the Activity
//class at on AsyncTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
And my (edited) Mainactivity including the AsyncTask for connection is
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Button;
public class MyActivity extends AppCompatActivity {
private TextView mTextMessage;
private TextView myAwesomeTextView;
private TcpClient mTcpClient;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
mTextMessage.setText(R.string.title_home);
return true;
case R.id.navigation_dashboard:
mTextMessage.setText(R.string.title_dashboard);
return true;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
return true;
}
return false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_myActivity);
mTextMessage = (TextView) findViewById(R.id.message);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
myAwesomeTextView = (TextView)findViewById(R.id.editText);
//TCP connect
new ConnectTask().execute("");
//Buttons
final Button button_Send = findViewById(R.id.button_Send);
button_Send.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//Set text (debugging)
myAwesomeTextView.setText("My Awesome Text");
Log.d("myMessage1", "button pushed ");
//sends the message to the server
String message = "testing\0";
//String message = "testing\n\r";
if (mTcpClient != null) {
new SendMessageTask().execute(message);
//not needed just for debugging
Log.d("myMessage", "testing ");
}
}
});
final Button button_Disconnect = findViewById(R.id.button_Disconnect);
button_Disconnect.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mTcpClient != null) {
mTcpClient.stopClient();
}
}
});
}
#Override
protected void onPause() {
super.onPause();
if (mTcpClient != null) {
// disconnect
new DisconnectTask().execute();
}
}
/**
* Sends a message using a background task to avoid doing long/network operations on the UI thread
*/
public class SendMessageTask extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... params) {
// send the message
mTcpClient.sendMessage(params[0]);
Log.d("sendMessageTask", "try to send message ");
return null;
}
#Override
protected void onPostExecute(Void nothing) {
super.onPostExecute(nothing);
//nothing to do yet
}
}
/**
* Disconnects using a background task to avoid doing long/network operations on the UI thread
*/
public class DisconnectTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
// disconnect
mTcpClient.stopClient();
mTcpClient = null;
return null;
}
#Override
protected void onPostExecute(Void nothing) {
super.onPostExecute(nothing);
//nothing to do yet
}
}
public class ConnectTask extends AsyncTask<String, String, TcpClient> {
#Override
protected TcpClient doInBackground(String... message) {
//we create a TCPClient object and
mTcpClient = new TcpClient(new TcpClient.OnMessageReceived() {
#Override
//here the messageReceived method is implemented
public void messageReceived(String message) {
//this method calls the onProgressUpdate
publishProgress(message);
}
});
mTcpClient.run();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
Log.d("test", "response " + values[0]);
//process server response here....
}
}
}
EDIT #2 (failing behaviour still remains)
uncommented while(mRun) Loop in run-method of TcpClient
--> thought maybe the socket is closed by finally before the message has been sent.
moved the initial connection into onCreate(), so the button will just
handle the sending and the connection is established before.
removed closing the socket after sending the message
I managed to got this working.
I changed the line
new SendMessageTask().execute(message);
to
new SendMessageTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, message);
This got the sending working.
I also changed the server code to this:
#define MAX 2048
#define PORT 7891
#define SA struct sockaddr
// Function designed for chat between client and server.
void communicate(int sockfd)
{
char buff[MAX];
int n;
// infinite loop for chat
for (;;) {
bzero(buff, MAX);
// read the message from client and copy it in buffer
read(sockfd, buff, sizeof(buff));
// print buffer which contains the client contents
printf("From client: %s\t To client : ", buff);
bzero(buff, MAX);
n = 0;
// copy server message in the buffer
while ((buff[n++] = getchar()) != '\n');
// and send that buffer to client
write(sockfd, buff, sizeof(buff));
// if msg contains "Exit" then server exit and chat ended.
if (strncmp("exit", buff, 4) == 0) {
printf("Server Exit...\n");
break;
}
}
}
// Driver function
int main()
{
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;
// socket create and verification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
// Binding newly created socket to given IP and verification
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
// Now server is ready to listen and verification
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed..\n");
exit(0);
}
else
printf("Server listening...\n");
len = sizeof(cli);
// Accept the data packet from client and verification
connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0) {
printf("server acccept failed...\n");
exit(0);
}
else
printf("server acccept the client..\n");
// Function for chatting between client and server
communicate(connfd);
// After chatting close the socket
if(close(sockfd) < 0){
printf("Error - closing socket...\n");
}
else{
printf("Socket successfully closed..\n");
}
}
I'm using Android to toggle my led light with Arduino and ethernet shield. It didn't work despite having no problems during compilation neither on Android nor Arduino. I connected the ethernet shield with my computer and I gave it the same address as my computer.
This is my Android code:
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.ToggleButton;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/********************************/
/* Define all the buttons */
/********************************/
Switch led1 = (Switch) findViewById(R.id.Led1);
/*******************************************************/
/* Set an onclick/onchange listener for every button */
/*******************************************************/
led1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
/* Switch is led 1 */
new Background_get().execute("led1=1");
} else {
new Background_get().execute("led1=0");
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/*****************************************************/
/* This is a background process for connecting */
/* to the arduino server and sending */
/* the GET request withe the added data */
/*****************************************************/
private class Background_get extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
try {
/* Change the IP to the IP you set in the arduino sketch */
URL url = new URL("http://169, 254, 128, 184/?" + params[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder result = new StringBuilder();
String inputLine;
while ((inputLine = in.readLine()) != null)
result.append(inputLine).append("\n");
in.close();
connection.disconnect();
return result.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
And this is the Arduino code:
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(169, 254, 128, 184);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
// Pin 5
pinMode(5, OUTPUT);
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
String buffer = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
buffer += c;
// 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("Connection: close");
// the connection will be closed after completion of the response
client.println("Refresh: 5");
// refresh the page automatically every 5 sec
client.println();
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
buffer = "";
} else if (c != '\r') {
if (buffer.indexOf("GET /?led1=1") >= 0) { // If led1 = 1
digitalWrite(5, HIGH); // led 1 > on
}
if (buffer.indexOf("GET /?led1=0") >= 0) { // If led1 = 0
digitalWrite(5, LOW); // led 1 > off
}
} else {
// 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 disconnected");
}
}
Program your Arduino:
#include "etherShield.h"
#include "ETHER_28J60.h"
int led2 = 7;
int led1 = 6;
static uint8_t mac[6] = {0xAA, 0xBB, 0xCC, 0xDD, 0xBB, 0xAA}; // this just needs to be unique for your network,
// so unless you have more than one of these boards
// connected, you should be fine with this value.
static uint8_t ip[4] = {192, 168, 0, 15}; // the IP address for your board. Check your home hub
// to find an IP address not in use and pick that
// this or 10.0.0.15 are likely formats for an address
// that will work.
static uint16_t port = 80; // Use port 80 - the standard for HTTP
ETHER_28J60 e;
void setup(){
e.setup(mac, ip, port);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
}
void loop(){
char* params;
if (params = e.serviceRequest()){
if (strcmp(params, "?cmd=1") == 0){digitalWrite(led1, HIGH);}
if (strcmp(params, "?cmd=2") == 0){digitalWrite(led1, LOW); }
if (strcmp(params, "?cmd=3") == 0){digitalWrite(led2, HIGH);}
if (strcmp(params, "?cmd=4") == 0){digitalWrite(led2, LOW); }
e.respond();
}
}
Program your APP
Add Permission to Your Manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
MainActivity.java
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
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.Toast;
public class MainActivity extends Activity implements OnClickListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
StrictMode.ThreadPolicy policy = new StrictMode.
ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
View led1on = findViewById(R.id.led_1on);
View led1off = findViewById(R.id.led_1off);
View led2on = findViewById(R.id.led_2on);
View led2off = findViewById(R.id.led_2off);
led1on.setOnClickListener(this);
led1off.setOnClickListener(this);
led2on.setOnClickListener(this);
led2off.setOnClickListener(this);
}
public void commandArduino(String url){
try {
HttpClient httpclient = new DefaultHttpClient();
httpclient.execute(new HttpGet(url));
} catch (Exception e) {}
}
public void onClick(View thisView) {
switch(thisView.getId()){
case R.id.led_1on: commandArduino("http://192.168.0.15/?cmd=1"); break;
case R.id.led_1off: commandArduino("http://192.168.0.15/?cmd=2"); break;
case R.id.led_2on: commandArduino("http://192.168.0.15/?cmd=3"); break;
case R.id.led_2off: commandArduino("http://192.168.0.15/?cmd=4"); break;
}
}
}
Reference:
http://www.instructables.com/id/Arduino-Android-LED-control-Using-Ethernet-Shield/
I want to connect the VPN in my Application.
I download the demo from https://github.com/guardianproject/OrbotVPN
package org.torproject.android.vpn;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import android.app.PendingIntent;
import android.content.Intent;
import android.net.VpnService;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.widget.Toast;
import com.runjva.sourceforge.jsocks.protocol.ProxyServer;
import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone;
public class OrbotVpnService extends VpnService implements Handler.Callback, Runnable {
private static final String TAG = "OrbotVpnService";
private String mServerAddress = "192.xx.xx.xx";
private int mServerPort = xxxx;
private PendingIntent mConfigureIntent;
private Handler mHandler;
private Thread mThread;
private String mSessionName = "OrbotVPN";
private ParcelFileDescriptor mInterface;
private int mSocksProxyPort = 9999;
private boolean mKeepRunning = true;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Start a new session by creating a new thread.
mThread = new Thread(this, "OrbotVpnThread");
mThread.start();
startSocksBypass ();
return START_STICKY;
}
private void startSocksBypass ()
{
Thread thread = new Thread ()
{
public void run ()
{
try {
final ProxyServer server = new ProxyServer(new ServerAuthenticatorNone(null, null));
server.setVpnService(OrbotVpnService.this);
server.start(9999, 5, InetAddress.getLocalHost());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
};
thread.start();
}
#Override
public void onDestroy() {
if (mThread != null) {
mKeepRunning = false;
mThread.interrupt();
}
}
#Override
public boolean handleMessage(Message message) {
if (message != null) {
Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
}
return true;
}
#Override
public synchronized void run() {
try {
Log.i(TAG, "Starting");
// If anything needs to be obtained using the network, get it now.
// This greatly reduces the complexity of seamless handover, which
// tries to recreate the tunnel without shutting down everything.
// In this demo, all we need to know is the server address.
InetSocketAddress server = new InetSocketAddress(
mServerAddress, mServerPort);
mHandler.sendEmptyMessage(R.string.connecting);
run(server);
} catch (Exception e) {
Log.e(TAG, "Got " + e.toString());
try {
mInterface.close();
} catch (Exception e2) {
// ignore
}
mHandler.sendEmptyMessage(R.string.disconnected);
} finally {
}
}
/*
#Override
public synchronized void run() {
try {
Log.i(TAG, "Starting");
// If anything needs to be obtained using the network, get it now.
// This greatly reduces the complexity of seamless handover, which
// tries to recreate the tunnel without shutting down everything.
// In this demo, all we need to know is the server address.
InetSocketAddress server = new InetSocketAddress(
mServerAddress, mServerPort);
// We try to create the tunnel for several times. The better way
// is to work with ConnectivityManager, such as trying only when
// the network is avaiable. Here we just use a counter to keep
// things simple.
for (int attempt = 0; attempt < 10; ++attempt) {
mHandler.sendEmptyMessage(R.string.connecting);
// Reset the counter if we were connected.
if (run(server)) {
attempt = 0;
}
// Sleep for a while. This also checks if we got interrupted.
Thread.sleep(3000);
}
Log.i(TAG, "Giving up");
} catch (Exception e) {
Log.e(TAG, "Got " + e.toString());
} finally {
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = null;
mHandler.sendEmptyMessage(R.string.disconnected);
Log.i(TAG, "Exiting");
}
}*/
DatagramChannel mTunnel = null;
private boolean run(InetSocketAddress server) throws Exception {
boolean connected = false;
// Create a DatagramChannel as the VPN tunnel.
mTunnel = DatagramChannel.open();
DatagramSocket s = mTunnel.socket();
// Protect the tunnel before connecting to avoid loopback.
if (!protect(s)) {
throw new IllegalStateException("Cannot protect the tunnel");
}
mTunnel.connect(server);
// For simplicity, we use the same thread for both reading and
// writing. Here we put the tunnel into non-blocking mode.
mTunnel.configureBlocking(false);
// Authenticate and configure the virtual network interface.
handshake();
// Now we are connected. Set the flag and show the message.
connected = true;
mHandler.sendEmptyMessage(R.string.connected);
new Thread ()
{
public void run ()
{
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// Packets to be sent are queued in this input stream.
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
// Packets received need to be written to this output stream.
FileOutputStream out = new FileOutputStream(mInterface.getFileDescriptor());
// We use a timer to determine the status of the tunnel. It
// works on both sides. A positive value means sending, and
// any other means receiving. We start with receiving.
int timer = 0;
Log.d(TAG,"tunnel open:" + mTunnel.isOpen() + " connected:" + mTunnel.isConnected());
// We keep forwarding packets till something goes wrong.
while (true) {
try
{
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
Log.d(TAG,"got outgoing packet; length=" + length);
// Write the outgoing packet to the tunnel.
packet.limit(length);
mTunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
// If we were receiving, switch to sending.
if (timer < 1) {
timer = 1;
}
}
// Read the incoming packet from the mTunnel.
length = mTunnel.read(packet);
if (length > 0) {
Log.d(TAG,"got inbound packet; length=" + length);
// Write the incoming packet to the output stream.
out.write(packet.array(), 0, length);
packet.clear();
// There might be more incoming packets.
idle = false;
// If we were sending, switch to receiving.
if (timer > 0) {
timer = 0;
}
}
// If we are idle or waiting for the network, sleep for a
// fraction of time to avoid busy looping.
if (idle) {
Thread.sleep(100);
// Increase the timer. This is inaccurate but good enough,
// since everything is operated in non-blocking mode.
timer += (timer > 0) ? 100 : -100;
// We are receiving for a long time but not sending.
if (timer < -15000) {
// Switch to sending.
timer = 1;
}
// We are sending for a long time but not receiving.
if (timer > 20000) {
//throw new IllegalStateException("Timed out");
//Log.d(TAG,"receiving timed out? timer=" + timer);
}
}
}
catch (Exception e)
{
Log.d(TAG,"error in tunnel",e);
}
}
}
}.start();
return connected;
}
private void handshake() throws Exception {
if (mInterface == null)
{
Builder builder = new Builder();
builder.setMtu(1500);
builder.addAddress("10.0.2.0",24);
builder.setSession("OrbotVPN");
builder.addRoute("0.0.0.0",0);
builder.addDnsServer("8.8.8.8");
// builder.addDnsServer("127.0.0.1:5400");
// Close the old interface since the parameters have been changed.
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
// Create a new interface using the builder and save the parameters.
mInterface = builder.setSession(mSessionName)
.setConfigureIntent(mConfigureIntent)
.establish();
}
}
private void debugPacket(ByteBuffer packet)
{
/*
for(int i = 0; i < length; ++i)
{
byte buffer = packet.get();
Log.d(TAG, "byte:"+buffer);
}*/
int buffer = packet.get();
int version;
int headerlength;
version = buffer >> 4;
headerlength = buffer & 0x0F;
headerlength *= 4;
Log.d(TAG, "IP Version:"+version);
Log.d(TAG, "Header Length:"+headerlength);
String status = "";
status += "Header Length:"+headerlength;
buffer = packet.get(); //DSCP + EN
buffer = packet.getChar(); //Total Length
Log.d(TAG, "Total Length:"+buffer);
buffer = packet.getChar(); //Identification
buffer = packet.getChar(); //Flags + Fragment Offset
buffer = packet.get(); //Time to Live
buffer = packet.get(); //Protocol
Log.d(TAG, "Protocol:"+buffer);
status += " Protocol:"+buffer;
buffer = packet.getChar(); //Header checksum
String sourceIP = "";
buffer = packet.get(); //Source IP 1st Octet
sourceIP += buffer;
sourceIP += ".";
buffer = packet.get(); //Source IP 2nd Octet
sourceIP += buffer;
sourceIP += ".";
buffer = packet.get(); //Source IP 3rd Octet
sourceIP += buffer;
sourceIP += ".";
buffer = packet.get(); //Source IP 4th Octet
sourceIP += buffer;
Log.d(TAG, "Source IP:"+sourceIP);
status += " Source IP:"+sourceIP;
String destIP = "";
buffer = packet.get(); //Destination IP 1st Octet
destIP += buffer;
destIP += ".";
buffer = packet.get(); //Destination IP 2nd Octet
destIP += buffer;
destIP += ".";
buffer = packet.get(); //Destination IP 3rd Octet
destIP += buffer;
destIP += ".";
buffer = packet.get(); //Destination IP 4th Octet
destIP += buffer;
Log.d(TAG, "Destination IP:"+destIP);
status += " Destination IP:"+destIP;
/*
msgObj = mHandler.obtainMessage();
msgObj.obj = status;
mHandler.sendMessage(msgObj);
*/
//Log.d(TAG, "version:"+packet.getInt());
//Log.d(TAG, "version:"+packet.getInt());
//Log.d(TAG, "version:"+packet.getInt());
}
}
It also connected with VPN and show the key symbol on top of the bar, but dont found any server entry in my server Interfaces.Same server I register in mobile network it Connected and I found the Server entry in my server Interfaces.
Is there any server Implementation require?
Am I wrong in above VPN service or I make the mistake in it?
Is there other way for connecting the VPN using the Username,password and server Id?
Try this :
void startVPN(String name) {
Intent i=new Intent("doenter.onevpn.ACTION_CONNECT");
i.putExtra("name",name);
i.putExtra("force", true);
i.putExtra("force_same", false);
startActivity(i);
}
void restartVPN(String name) {
Intent i=new Intent("doenter.onevpn.ACTION_CONNECT");
i.putExtra("name",name);
i.putExtra("force", true);
i.putExtra("force_same", true);
startActivity(i);
}
void stopVPN() {
Intent i=new Intent("doenter.onevpn.ACTION_DISCONNECT");
// Stops any VPN regardless of name
startActivity(i);
}
So I've created a webserver that outputs the values from a couple of analogue sensors when a command is received from an android app. However it lags whenever any button is pressed and only occasionally works, usually crashing the app. This is the arduino code:
//ARDUINO 1.0+ ONLY
//ARDUINO 1.0+ ONLY
#include <Ethernet.h>
#include <SPI.h>
// the value of the 'other' resistor
#define SERIESRESISTOR 10000
// What pin to connect the sensor to
#define THERMISTORPIN A0
boolean reading = false;
const int analogInPin = A1;
int sensorValue = 0;
////////////////////////////////////////////////////////////////////////
//CONFIGURE
////////////////////////////////////////////////////////////////////////
byte ip[] = { 192, 168, 0, 101 }; //Manual setup only
byte gateway[] = { 192, 168, 0, 1 }; //Manual setup only
byte subnet[] = { 255, 255, 255, 0 }; //Manual setup only
// if need to change the MAC address (Very Rare)
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetServer server = EthernetServer(80); //port 80
////////////////////////////////////////////////////////////////////////
void setup(){
Serial.begin(9600);
//Pins 10,11,12 & 13 are used by the ethernet shield
pinMode(7, OUTPUT);
Ethernet.begin(mac, ip, gateway, subnet); //for manual setup
server.begin();
Serial.println(Ethernet.localIP());
}
void loop(){
// listen for incoming clients, and process qequest.
checkForClient();
tempReading();
}
void tempReading(){
sensorValue = analogRead(analogInPin);
EthernetClient client2 = server.available();
if (client2) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
boolean sentHeader = false;
while (client2.connected()) {
if (client2.available()) {
if(!sentHeader){
// send a standard http response header
client2.println("HTTP/1.1 200 OK");
client2.println("Content-Type: text/html");
client2.println();
sentHeader = true;
}
float reading;
reading = analogRead(THERMISTORPIN);
Serial.print("Analog reading ");-
Serial.println(reading);
// convert the value to resistance
reading = (1023 / reading) - 1;
reading = SERIESRESISTOR / reading;
Serial.print("Thermistor resistance ");
Serial.println(reading);
delay(1000);
float reading2;
char d = client2.read();
if(reading2 && d == ' ') reading2 = false;
if(d == '?') reading2 = true; //found the ?, begin reading the info
if(reading2){
switch (d) {
case '4':
//add code here to trigger on 2
client2.print("Thermistor resistance: ");
client2.println(reading);
client2.println("\n");
break;
case '5':
client2.print("Light Level: ");
client2.println(sensorValue);
client2.println("\n");
}
}
}
}
delay(1); // give the web browser time to receive the data
client2.stop(); // close the connection:
}
}
void checkForClient(){
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
boolean sentHeader = false;
while (client.connected()) {
if (client.available()) {
if(!sentHeader){
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
sentHeader = true;
}
char c = client.read();
if(reading && c == ' ') reading = false;
if(c == '?') reading = true; //found the ?, begin reading the info
if(reading){
Serial.print(c);
switch (c) {
case '1':
//add code here to trigger on 2
pinOn(7, client);
break;
case '2':
//add code here to trigger on 3
pinOff(7, client);
break;
}
}
if (c == '\n' && currentLineIsBlank) break;
if (c == '\n') {
currentLineIsBlank = true;
}else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection:
}
void pinOff(int pin, EthernetClient client){
digitalWrite(pin, HIGH);
}
void pinOn(int pin, EthernetClient client){
digitalWrite(pin, LOW);
}
and this is the Android code:
package com.example.liam.arduinocontroller;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.os.StrictMode;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
public class ControlClass extends ActionBarActivity implements OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
StrictMode.ThreadPolicy policy = new StrictMode.
ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_control_class);
View led1on = findViewById(R.id.led_1on);
View led1off = findViewById(R.id.led_1off);
View led2on = findViewById(R.id.led_2on);
View led2off = findViewById(R.id.led_2off);
led1on.setOnClickListener(this);
led1off.setOnClickListener(this);
led2on.setOnClickListener(this);
led2off.setOnClickListener(this);
}
public void commandArduino(String url) {
try {
HttpClient httpclient = new DefaultHttpClient();
HttpParams httpParameters = httpclient.getParams();
HttpConnectionParams.setTcpNoDelay(httpParameters, true);
httpclient.execute(new HttpGet(url));
} catch (Exception e) {
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_control_class, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onClick(View thisView) {
switch(thisView.getId())
{
case R.id.led_1on:
commandArduino("http://192.168.0.101/?2");
Toast.makeText(getApplicationContext(), "led_1on", Toast.LENGTH_LONG).show();
break;
case R.id.led_1off:
commandArduino("http://192.168.0.101/?3");
Toast.makeText(getApplicationContext(), "led_1off", Toast.LENGTH_LONG).show();
break;
case R.id.led_2on:
commandArduino("http://192.168.0.101/?4");
Intent intent = new Intent(this, TempDisplay.class);
startActivity(intent);
break;
case R.id.led_2off:
commandArduino("http://192.168.0.101/?5");
Intent j = new Intent(this, LightDisplay.class);
startActivity(j);
break;
}
}
}
Any ideas?
I try to refactor your code
//ARDUINO 1.0+ ONLY
#include <Ethernet.h>
#include <SPI.h>
// the value of the 'other' resistor
#define SERIESRESISTOR 10000
// What pin to connect the sensor to
#define THERMISTORPIN A0
const int analogInPin = A1;
////////////////////////////////////////////////////////////////////////
//CONFIGURE
////////////////////////////////////////////////////////////////////////
byte ip[] = { 192, 168, 0, 101 }; //Manual setup only
byte gateway[] = { 192, 168, 0, 1 }; //Manual setup only
byte subnet[] = { 255, 255, 255, 0 }; //Manual setup only
// if need to change the MAC address (Very Rare)
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetServer server = EthernetServer(80); //port 80
////////////////////////////////////////////////////////////////////////
void setup(){
Serial.begin(9600);
//Pins 10,11,12 & 13 are used by the ethernet shield
pinMode(7, OUTPUT);
Ethernet.begin(mac, ip, gateway, subnet); //for manual setup
server.begin();
Serial.println(Ethernet.localIP());
}
void loop() {
boolean reading = false;
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
boolean sentHeader = false;
while (client.connected()) {
if (client.available()) {
if (!sentHeader){
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
sentHeader = true;
}
char c = client.read();
if (reading && c == ' ') {
reading = false;
}
if (c == '?') {
//found the ?, begin reading the info
reading = true;
}
if (reading){
Serial.print(c);
switch (c) {
case '1':
pinOn(7, client);
break;
case '2':
pinOff(7, client);
break;
case '4':
print_thermistor(&client);
break;
case '5':
print_light(&client);
break;
}
}
if (c == '\n' && currentLineIsBlank)
break;
if (c == '\n') {
currentLineIsBlank = true;
} else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(500); // give the web browser time to receive the data
client.stop(); // close the connection:
}
}
void print_thermistor(EthernetClient *client) {
float th;
th = analogRead(THERMISTORPIN);
Serial.print("Analog th ");
Serial.println(th);
// convert the value to resistance
th = (1023 / th) - 1;
th = SERIESRESISTOR / th;
Serial.print("Thermistor resistance ");
Serial.println(th);
client->print("Thermistor resistance: ");
client->println(th);
client->println("\n");
}
void print_light(EthernetClient *client) {
int sensorValue;
sensorValue = analogRead(analogInPin);
client->print("Light Level: ");
client->println(sensorValue);
client->println("\n");
}
void pinOff(int pin, EthernetClient client){
digitalWrite(pin, HIGH);
}
void pinOn(int pin, EthernetClient client){
digitalWrite(pin, LOW);
}
I know there are other topics about that but in my case I want the Android device to initialize the bluetooth connection as a server. I followed the Documentation and I wrote the server in this way:
private class AcceptThread implements Runnable {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
try {
tmp = mBluetooth.listenUsingRfcommWithServiceRecord(
"myService", mUuid);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
System.out.println("SERVER SOCKET LISTENING");
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
System.out.println("SIGNAL RECEIVED");
// Do work to manage the connection (in a separate thread)
Toast.makeText(getApplicationContext(), "SIGNAL RECEIVED", Toast.LENGTH_LONG).show();
try {
mmServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
On the other side I have bluecove API that discover remote devices and services.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Vector;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
/**
* A simple SPP client that connects with an SPP server
*/
public class SampleSPPClient implements DiscoveryListener{
//object used for waiting
private static Object lock=new Object();
//vector containing the devices discovered
private static Vector vecDevices=new Vector();
private static String connectionURL=null;
public static void main(String[] args) throws IOException {
SampleSPPClient client=new SampleSPPClient();
//display local device address and name
LocalDevice localDevice = LocalDevice.getLocalDevice();
System.out.println("Address: "+localDevice.getBluetoothAddress());
System.out.println("Name: "+localDevice.getFriendlyName());
//find devices
DiscoveryAgent agent = localDevice.getDiscoveryAgent();
System.out.println("Starting device inquiry...");
agent.startInquiry(DiscoveryAgent.GIAC, client);
try {
synchronized(lock){
lock.wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Device Inquiry Completed. ");
//print all devices in vecDevices
int deviceCount=vecDevices.size();
if(deviceCount <= 0){
System.out.println("No Devices Found .");
System.exit(0);
}
else{
//print bluetooth device addresses and names in the format [ No. address (name) ]
System.out.println("Bluetooth Devices: ");
for (int i = 0; i <deviceCount; i++) {
RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(i);
System.out.println((i+1)+". "+remoteDevice.getBluetoothAddress()+" ("+remoteDevice.getFriendlyName(true)+")");
}
}
System.out.print("Choose Device index: ");
BufferedReader bReader=new BufferedReader(new InputStreamReader(System.in));
String chosenIndex=bReader.readLine();
int index=Integer.parseInt(chosenIndex.trim());
//check for spp service
RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(index-1);
UUID[] uuidSet = new UUID[1];
uuidSet[0]=new UUID("4e3aea40e2a511e095720800200c9a66", false);
System.out.println("\nSearching for service...");
agent.searchServices(null,uuidSet,remoteDevice,client);
try {
synchronized(lock){
lock.wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
if(connectionURL==null){
System.out.println("Device does not support Simple SPP Service.");
System.exit(0);
}
//connect to the server and send a line of text
StreamConnection streamConnection=(StreamConnection)Connector.open(connectionURL);
//send string
OutputStream outStream=streamConnection.openOutputStream();
PrintWriter pWriter=new PrintWriter(new OutputStreamWriter(outStream));
pWriter.write("Test String from SPP Client\r\n");
pWriter.flush();
//read response
InputStream inStream=streamConnection.openInputStream();
BufferedReader bReader2=new BufferedReader(new InputStreamReader(inStream));
String lineRead=bReader2.readLine();
System.out.println(lineRead);
}//main
//methods of DiscoveryListener
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
//add the device to the vector
if(!vecDevices.contains(btDevice)){
vecDevices.addElement(btDevice);
}
}
//implement this method since services are not being discovered
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
System.out.println(servRecord[0].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false));
if(servRecord!=null && servRecord.length>0){
connectionURL=servRecord[0].getConnectionURL(ServiceRecord.AUTHENTICATE_ENCRYPT,false);
}
synchronized(lock){
lock.notify();
}
}
//implement this method since services are not being discovered
public void serviceSearchCompleted(int transID, int respCode) {
synchronized(lock){
lock.notify();
}
}
public void inquiryCompleted(int discType) {
synchronized(lock){
lock.notify();
}
}//end method
}
The client found the device and the service but when retrieve the url from the ServiceRecord to establish the connection it fails. It retrieve an Url in which the channel is wrong and it throws an exception: javax.bluetooth.BluetoothConnectionException: Failed to connect;
How can I solve the problem?
I managed to find some phone ServiceRecords when using:
UUID[] uuidSet = new UUID[1];
uuidSet[0]=new UUID(0x0100);
int[] attrIds = { 0x0100 };
System.out.println("\nSearching for service...");
agent.searchServices(attrIds, uuidSet, remoteDevice, client);
And you will be calling lock.notify() twice after a serviceSearch, remove it in the servicesDiscovered function.
You should also go through the service records and look for the one you are interested in. The URL will state btgoep:// or btspp://
When searching through the for loop use this code to list the service name
for(int i = 0; i < servRecord.length; i++)
{
String url = servRecord[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
DataElement serviceName = srs[i].getAttributeValue(0x0100);
if (serviceName != null) {
System.out.println("service " + serviceName.getValue() + " found " + url);
} else {
System.out.println("service found " + url);
}
I have the exact problem, it seems like the android api doesn't register the ServiceRecord with the SDP so the Bluecove api can find it.
No matter what UUID I use it will only find the ones my phone register as default, i e Audio gateways and Phonebook OBEX push and such.
EDIT ---
I had the same problem, but realized I had not actually called listenUsingInsecureRFCOMMSocket yet. And then it did not register the service record.
But after that it worked just fine.