ESP8266 wifi服务器到android客户端 [英] ESP8266 wifi server to android client

查看:170
本文介绍了ESP8266 wifi服务器到android客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Ive been trying to setup a server using ESP8266 wifi module on a particular port. I'm done with that.

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

I want to receive the message from it now. Whenever I connect using socket.connect(), I am able to detect it in the esp8266. But I cant receive any message, the server sends through the same socket.

我试图在异步任务中的while循环内使用DataInputStream连续获取消息。让我知道我的方法或代码是否错误!谢谢!

I am trying to obtain the message using DataInputStream inside a while loop continuously in a async task.Pls let me know if my approach or code is wrong! Thanks!

这是我的代码:

    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代码以供参考。

UPDATE(16-12-15) I made the following changes under the doInBackground(). originally, I used DataInputStream, now I replaced it with BufferedReader. The change was made under the while loop part for constantly checking the socket input stream. Also added the ESP8266 code for reference.

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

Now I able to Receive the text sent from ESP8266, but it reaches only after I send 3 or 4 messages via CIPSEND cmd. for e.g. if i send "hi", "hello" "yo", after sending the third word, I receive all the words together as "hihelloyo" Instead of recieving each message as soon as it is sent, I receive it very late. I am not sure what exactly is causing this problem. May be the buffer size? How to solve this ?

修改后的代码

     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命令。

UPDATE(17-12-15):Added pics for reference My arduino serial window showing the AT+CIPSEND commands.

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

pic of the app running on phone.

推荐答案

对此评论:


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

... it worked! I can get the messages immediately irrespective of their lengths, after i close the connection on esp side using cipclose=0. But is this is the only way? Is it possible to make the device and the app talk? How come it is possible in the telnet application, where i can continuously send data till i close connection on one side.?

来自TCPIP连接的上层应用程序层数据以流的形式显示。将此流与定义明确的应用程序协议(例如HTTP或telnet)结合使用,即可定义消息交换。就您而言,基本上Android方面不知道要接收多少数据。使用缓冲的阅读器后,您得到的是缓冲的答案,而不是全部。

On the upper application layers data from TCPIP connection is presented as a Stream. Using this stream with well-defined application protocols like HTTP or telnet, message exchange is defined. In your case basically Android side does not know what amount of data to receive. After using buffered reader you get buffered answer, not the whole.

例如在telnet协议中,有一些控制命令。这样系统就可以继续工作了。

In telnet protocol for example there are control commands. Thus the system goes on working.

解决您的情况:


  1. 每条消息后关闭连接。 (这会减慢速度)

  2. 实施基本的应用协议。例如:实施消息框:




FRAME
1st byte         : length ( this byte gives the length of the payload )
2nd...255th byte : payload ( this is the actual message )

LOGIC
-Sender packs the frame giving length and payload.
-Sender sends the data
...
-Receiver queries for the available bytes. 
-When available bytes are >1 receive only 1 byte say it is 'n'
-'n' is the length of the total frame
-Read 'n' bytes from the stream. if EOF then return what is received.

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

In addition to this you can implement control commands. For example you may want the receiver to close the connection so your frame can be:


Byte 1 : length
Byte 2 : command (0=nothing, 1=close conn)
Byte 3..n : payload

LOGIC
-When receiver finished receiving and command is 1 then closes the connection. 

这篇关于ESP8266 wifi服务器到android客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆