【问题标题】:ESP8266 wifi server to android clientESP8266 wifi 服务器到安卓客户端
【发布时间】:2016-03-20 09:22:35
【问题描述】:

我一直在尝试在特定端口上使用 ESP8266 wifi 模块设置服务器。我已经完成了。

我现在想收到它的消息。 每当我使用 socket.connect() 连接时,我都能在 esp8266 中检测到它。但是我收不到任何消息,服务器通过同一个套接字发送。

我正在尝试使用 DataInputStream 在异步任务中连续地在 while 循环中获取消息。如果我的方法或代码错误,请告诉我!谢谢!

这是我的代码:

    package test.espclient;

import java.io.DataInputStream;
//import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;



public class MainActivity extends Activity {

    TextView textResponse;
    EditText editTextAddress, editTextPort;
    Button buttonConnect, buttonClear,buttonDiscon , buttonSendMsg;

    EditText welcomeMsg;

    Socket socket;

    boolean socketStatus = false;

    MyClientTask myClientTask;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editTextAddress = (EditText) findViewById(R.id.address);
        editTextPort = (EditText) findViewById(R.id.port);
        buttonConnect = (Button) findViewById(R.id.connect);
        buttonClear = (Button) findViewById(R.id.clear);
        buttonDiscon = (Button) findViewById(R.id.closeSocket);
        buttonSendMsg = (Button) findViewById(R.id.sendMsg);
        textResponse = (TextView) findViewById(R.id.response);

        welcomeMsg = (EditText)findViewById(R.id.welcomemsg);

        buttonConnect.setOnClickListener(buttonConnectOnClickListener);

        buttonDiscon.setOnClickListener(buttonDisconnectOnCLickListener);

        //buttonSendMsg.setOnClickListener(sendMessage);

        buttonClear.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                textResponse.setText("");
            }
        });
    }

    OnClickListener buttonConnectOnClickListener = new OnClickListener() {

        @Override
        public void onClick(View arg0) {
      if(socketStatus)
          Toast.makeText(MainActivity.this,"Already talking to a Socket!! Disconnect and try again!", Toast.LENGTH_LONG).show();
      else {
          socket = null;
          String address = editTextAddress.getText().toString();
          int port = Integer.parseInt(editTextPort.getText().toString());
          String tMsg = welcomeMsg.getText().toString();

          if (address == null || port == 0)
              Toast.makeText(MainActivity.this, "Please enter valid address/port", Toast.LENGTH_LONG).show();

          else {
                           myClientTask = new MyClientTask(address,port,tMsg);
                          myClientTask.execute();

          } //else when no active socket conn. and credentials are validated.


      } //else when already active socket conn.
        }
    };

    OnClickListener buttonDisconnectOnCLickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            if (!socketStatus)
                Toast.makeText(MainActivity.this, "SOCKET Already Closed!!", Toast.LENGTH_SHORT).show();
            else {
                try {
                    onDisconnect();
                    if(myClientTask.isCancelled()) {
                        socket.close();
                        Toast.makeText(MainActivity.this, "Socket Closed!", Toast.LENGTH_SHORT).show();
                        socketStatus = false;
                    }
                    else
                    {
                        Toast.makeText(MainActivity.this, "Couldn't Disconnect! Pls try again!", Toast.LENGTH_SHORT).show();
                        socketStatus = true;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    Toast.makeText(MainActivity.this,e.toString(), Toast.LENGTH_SHORT).show();

                }
            }
        }
    };

//    OnClickListener sendMessage = new OnClickListener() {
//        @Override
//        public void onClick(View v) {
//            String msg = welcomeMsg.toString();
//            if(msg.equals(""))
//            {
//                Toast.makeText(MainActivity.this, "Message is empty!!!", Toast.LENGTH_SHORT).show();
//            }
//            else if(!socketStatus)
//            {
//                Toast.makeText(MainActivity.this, "Please Establish Socket Connection first!", Toast.LENGTH_SHORT).show();
//            }
//            else
//            {
//                MyClientTask myClientTask = new MyClientTask(editTextAddress
//                    .getText().toString(), Integer.parseInt(editTextPort
//                    .getText().toString()),
//                    msg);
//            myClientTask.execute();
//
//            }
//
//        }
//    };

    public void onDisconnect()
    {
        myClientTask.cancel(true);
    }

    public class MyClientTask extends AsyncTask<Void, String, Void> {

        String dstAddress;
        int dstPort;
        String response ="";
        String msgToServer;

        MyClientTask(String addr, int port, String msgTo) {
            dstAddress = addr;
            dstPort = port;
            msgToServer = msgTo;
            Log.w("MSG","Entering async task");
        }



        @Override
        protected Void doInBackground(Void... arg0) {


          //  DataOutputStream dataOutputStream = null;
            DataInputStream dataInputStream = null;

            try {
                socket = new Socket(dstAddress, dstPort);
                socketStatus = true;

               // dataOutputStream = new DataOutputStream(socket.getOutputStream());

//                if(msgToServer != null){
//                    dataOutputStream.writeUTF(msgToServer);
//                }
            }
            catch (UnknownHostException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
                response = "UnknownHostException: " + e.toString();
                socketStatus = false;
            }
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                response = "IOException: " + e.toString();
            }

            Log.w("MSG","Inside while loop for retrieving data");
           while(!isCancelled()){
               try {
                   dataInputStream = new DataInputStream(socket.getInputStream());
                   response = dataInputStream.readUTF();

                   if(!response.isEmpty())
                   {
                       publishProgress(response);
                       Log.w("Data:",response);
                   }

               } catch (IOException e) {
                   e.printStackTrace();
               }
           }


//                if (dataOutputStream != null) {
//                    try {
//                        dataOutputStream.close();
//                    } catch (IOException e) {
//                        // TODO Auto-generated catch block
//                        e.printStackTrace();
//                    }
//                }

                if (dataInputStream != null) {
                    try {
                        dataInputStream.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

            try {
                Log.w("MSG","Stopping async task");
                socket.close();
                socketStatus = false;
            } catch (IOException e) {
                e.printStackTrace();
                socketStatus = true;
            }
            return null;
        }


        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            textResponse.setText(values[0]);
            Toast.makeText(MainActivity.this,"Server:"+values[0],Toast.LENGTH_LONG).show();
            Log.w("MSG","Updating with msg");
        }

        @Override
        protected void onPostExecute(Void result) {
            Log.w("MSG","On postExecute method..");
            textResponse.setText(response);
            super.onPostExecute(result);
        }

    }

}

UPDATE(16-12-15) 我在 doInBackground() 下做了以下更改。 最初,我使用 DataInputStream,现在我将其替换为 BufferedReader。 更改是在 while 循环部分下进行的,用于不断检查套接字输入流。还添加了ESP8266代码供参考。

现在我可以接收从 ESP8266 发送的文本,但它只有在我通过 CIPSEND cmd 发送 3 或 4 条消息后才能到达。例如如果我发送“hi”、“hello”、“yo”,在发送第三个单词后,我会收到所有单词作为“hihelloyo” 我没有在每条消息发送后立即收到它,而是很晚才收到它。 我不确定究竟是什么导致了这个问题。可能是缓冲区大小? 如何解决?

修改后的代码

     protected Void doInBackground(Void... arg0) {


          //  DataOutputStream dataOutputStream = null;
          //  DataInputStream dataInputStream = null;

            try {
                socket = new Socket(dstAddress, dstPort);
                socketStatus = true;
               // dataOutputStream = new DataOutputStream(socket.getOutputStream());

//                if(msgToServer != null){
//                    dataOutputStream.writeUTF(msgToServer);
//                }
            }
            catch (UnknownHostException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
                response = "UnknownHostException: " + e.toString();
                socketStatus = false;
            }
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                response = "IOException: " + e.toString();
            }


            Log.w("MSG","Inside while loop for retrieving data");

            while(!isCancelled() && socketStatus) {
                try {
//                  dataInputStream = new DataInputStream(socket.getInputStream());
//                      response = dataInputStream.readUTF();
                    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    response = br.readLine();
                    if (!response.isEmpty()) {
                        publishProgress(response);
                        Log.w("Data:", response);
                    }


                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

ESP266 代码

    #include <AltSoftSerial.h>
AltSoftSerial ESP8266 ;//(8,9)|Rx,Tx

int LED = 13;

boolean FAIL_8266 = false;

#define BUFFER_SIZE 128
char buffer[BUFFER_SIZE];

String ssid="\"SSID\"";
String pass="\"PASSWORD\"";

void clearESP8266SerialBuffer()
{
  Serial.println("= clearESP8266SerialBuffer() =");
  while (ESP8266.available() > 0) {
    char a = ESP8266.read();
    Serial.write(a);
  }
  Serial.println("==============================");
}



void sendHTTPResponse(int id, String content)
{
  String response;
  response = "HTTP/1.1 200 OK\r\n";
  response += "Content-Type: text/html; charset=UTF-8\r\n"; 
  response += "Content-Length: ";
  response += content.length();
  response += "\r\n";
  response +="Connection: close\r\n\r\n";
  response += content;

  String cmd = "AT+CIPSEND=";
  cmd += id;
  cmd += ",";
  cmd += response.length();

  Serial.println("--- AT+CIPSEND ---");
  sendESP8266Cmdln(cmd, 1000);

  Serial.println("--- data ---");
  sendESP8266Data(response, 1000);
}

boolean waitOKfromESP8266(int timeout)
{
  do{
    Serial.println("wait OK...");
    delay(1000);
    if(ESP8266.find("OK"))
    {
      return true;
    }

  }while((timeout--)>0);
  return false;
}

//Send command to ESP8266, assume OK, no error check
//wait some time and display respond
void sendESP8266Cmdln(String cmd, int waitTime)
{
  ESP8266.println(cmd);
  delay(waitTime);
  clearESP8266SerialBuffer();
}

//Basically same as sendESP8266Cmdln()
//But call ESP8266.print() instead of call ESP8266.println()
void sendESP8266Data(String data, int waitTime)
{
  ESP8266.print(data);
  delay(waitTime);
  clearESP8266SerialBuffer();
}

void adc()
{
  int ldr;

  for(int i=0;i<=3;i++)
  {
    ldr = analogRead(A0); 
    sendESP8266Cmdln("AT+CIPSEND=0,5",1000);
    sendESP8266Cmdln(String(ldr),1000); 
    delay(1000);
  }
}

void setup() 
{
  Serial.begin(9600);
  ESP8266.begin(9600);
  pinMode(LED,OUTPUT);

  do{
  ESP8266.println("AT+RST");
    delay(1000);
    if(ESP8266.find("Ready"))
    {
      Serial.println("Module is ready");
      delay(1000);
      clearESP8266SerialBuffer();

      sendESP8266Cmdln("AT+CWMODE=1",1000);

      //Join Wifi network
      sendESP8266Cmdln("AT+CWJAP="+ssid+","+pass,6500);

      //Get and display my IP
      sendESP8266Cmdln("AT+CIFSR", 1000);  

      //Set multi connections
      sendESP8266Cmdln("AT+CIPMUX=1", 1000);
      //Setup web server on port 80
      sendESP8266Cmdln("AT+CIPSERVER=1,3333",1000);

      Serial.println("Server setup finish");

      FAIL_8266 = false;
    }else{
      Serial.println("Module have no response.");
      delay(500);
      FAIL_8266 = true;
    }
  }while(FAIL_8266);

  digitalWrite(LED, HIGH);
  ESP8266.setTimeout(1000);
}
void loop() {

  // listen for communication from the ESP8266 and then write it to the serial monitor

     if(ESP8266.available()) // check if the esp is sending a message 
  {
    String msg = ESP8266.readString();

    if(msg.substring(0,4)=="Link")
    Serial.println("Client connected!");

    else if(msg.substring(0,6)=="Unlink")
    Serial.println("Client Disconncected!!");


      else if(msg.substring(1,5)=="+IP")
      {
        Serial.println("Client says: "+msg.substring(9,14));
      }

      else
      {
       // Serial.println("Calling ADC.!");
        //adc();

       // Serial.println("Msg:"+msg.charAt(0)+msg.charAt(1)+msg.charAt(2)+msg.charAt(3));
       // Serial.println("Something recieved!: "+msg.substring(1,2));
        Serial.println("MSG:"+msg);  
      }
  } 

    // listen for user input and send it to the ESP8266
    if ( Serial.available() )       {  ESP8266.write( Serial.read() );  }
  }


//Clear and display Serial Buffer for ESP8266

更新(17-12-15):添加图片供参考 我的 arduino 串行窗口显示 AT+CIPSEND 命令。

在手机上运行的应用程序的图片。

【问题讨论】:

  • 看看esp8266的一些代码会很有用。另外,你的java代码有什么错误?例外?超时?
  • 我的 logcat 没有收到任何错误。最初,如果我使用 Datainputstream,我什么也没收到。现在,我将其更改为 bufferedReader。但是,我仅在使用 AT+CIPSEND 命令从 ESP8266 发送至少 9 个字符后才收到消息。否则,之前发送的较短的消息,就像我在上面的帖子中提到的一样。
  • 现在我注意到它不是,只有 9 个字符,在它出现在 android 中之前要发送的最小字符数,一直在变化。今天,大约有 14 个字符。它与缓冲阅读器的缓冲区大小有关吗?我不认为,问题出在 esp8266 上,因为我使用 telnet android 应用程序对其进行了测试。我可以立即收到所有像“嗨”、“你好”这样的小词。
  • 好的,感谢您发布 ESP8266 的代码。我会抓住机会,因为我无法测试你的 java 端。您在 JAVA 代码中有以下行: response = br.readLine();但是在 ESP8266 上,我看不到您实际上是在发送行尾,您是在用键盘输入要发送的文本并希望将其传输到 JAVA 端吗?尝试在代码中实际添加行尾,然后重试。
  • 在esp端,发送响应后关闭连接。

标签: android sockets android-asynctask bufferedinputstream esp8266


【解决方案1】:

关于这条评论:

...成功了!在我使用 cipclose=0 关闭 esp 端的连接后,无论消息的长度如何,我都可以立即获取消息。但这是唯一的方法吗?是否可以让设备和应用程序对话?怎么可能在 telnet 应用程序中,我可以连续发送数据,直到我关闭一侧的连接。?

在上层应用层,来自 TCPIP 连接的数据以流的形式呈现。将此流与定义良好的应用程序协议(如 HTTP 或 telnet)一起使用,定义了消息交换。在您的情况下,基本上 Android 端不知道要接收多少数据。使用缓冲阅读器后,您会得到缓冲的答案,而不是全部。

例如在 telnet 协议中有控制命令。因此系统继续工作。

解决你的问题:

  1. 每条消息后关闭连接。 (这会减慢速度)
  2. 实现一个基本的应用协议。例如:实现一个消息框架:
框架 第一个字节:长度(这个字节给出了有效载荷的长度) 第 2...255 个字节:有效载荷(这是实际消息) 逻辑 -Sender 打包给出长度和有效负载的帧。 -Sender 发送数据 ... -接收器查询可用字节。 - 当可用字节大于 1 时,只接收 1 个字节,说它是 'n' -'n' 是总帧的长度 - 从流中读取“n”个字节。如果 EOF 则返回收到的内容。

除此之外,您还可以执行控制命令。 例如,您可能希望接收器关闭连接,以便您的框架可以是:

字节 1:长度 字节 2:命令(0=无,1=关闭连接) 字节 3..n:有效载荷 逻辑 - 当接收器完成接收并且命令为 1 时关闭连接。

【讨论】:

  • 控制命令到底是什么意思?你能举几个例子吗?
猜你喜欢
  • 2012-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-31
  • 2012-01-22
  • 1970-01-01
相关资源
最近更新 更多