Android HttpUrl与Arduino Uno的连接



祝大家新年快乐:)

我正在使用Arduino Uno和Android应用程序进行一个家庭自动化项目,它可以通过我的TP-Link路由器进行通信。

我有一个java.io.IOException:连接上的流意外结束一旦我向Arduino发送了一个查询,我就无法解决它。

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) 

我的Arduino素描:

#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");
          }
        }
      }
    }
  }
}

我的Android代码:

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;
        }
    }
}

一般来说,您缺少:

  1. 在响应中发送数据
  2. 为套接字在关闭前发送数据提供时间
  3. 关闭连接前读取Android的响应

更详细地说,确保在建立连接后发送一些数据:

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();

参考:https://www.arduino.cc/en/Tutorial/WebServer,这是完整的示例:

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();
  }
}

此外,考虑使用json而不是html作为Arduino的响应。要做到这一点,您需要更改:

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

相关内容

  • 没有找到相关文章

最新更新