2

Ive пытался настроить сервер, используя модуль WIFI ESP8266 на конкретном порту. Я покончил с этим.ESP8266 сервер wifi для клиента android

Я хочу получить сообщение от него сейчас. Когда я подключаюсь через socket.connect(), я могу обнаружить его в esp8266. Но я не могу получить какое-либо сообщение, сервер отправляет через тот же сокет.

Я пытаюсь получить сообщение с использованием DataInputStream внутри цикла while непрерывно в async task.Pls, дайте мне знать, если мой подход или код неверны! Благодаря!

Это мой код:

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, но он достигает только после отправки 3 или 4 сообщений через CIPSEND cmd. например. если я отправлю «привет», «привет» «лет», после отправки третьего слова, я получаю все слова вместе как «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 

UPDATE (17-12-15): Добавлены фото для справки Мой Arduino серийный окно, отображающее AT + Команды CIPSEND. My arduino serial window, showing the AT+CIPSEND commands

pic приложения, работающие по телефону. from my app running on phone

+1

Это будет очень полезно, чтобы увидеть некоторые из кода для esp8266. Кроме того, какая ошибка вы получаете по вашему java-коду? Исключение? Тайм-аут? – ProgrammerV5

+0

У меня нет ошибок на моем логарифме. Первоначально, если я использовал Datainputstream, я ничего не получил. Теперь я изменил его на bufferedReader. однако я получаю сообщение только после отправки минимум 9 символов из ESP8266, используя команду AT + CIPSEND. В противном случае, ранее отправленные более короткие сообщения, объединяются вместе, как Ive, упомянутые выше в сообщении. –

+0

Теперь я заметил, что его нет, всего 9 символов, минимальное количество символов, которое должно быть отправлено до того, как оно появится в андроиде, будет меняться. сегодня это было около 14 символов. Имеет ли это какое-либо отношение к размеру буфера буферизованного читателя? Я не думаю, что проблема связана с esp8266, потому что я тестировал его с помощью приложения telnet android. Я могу получить все маленькие слова, такие как «Привет», «Привет». –

ответ

1

Как этот комментарий:

... это сработало! Я могу получать сообщения сразу, независимо от их длины, после того, как я закрываю соединение на стороне esp, используя cipclose = 0. Но разве это единственный способ? Можно ли говорить об устройстве и приложении? Как это возможно в приложении telnet, где я могу непрерывно отправлять данные, пока я не закрываю соединение с одной стороны.?

В верхних слоях приложений данные из соединения TCPIP представлены в виде потока. Используя этот поток с четко определенными протоколами приложений, такими как HTTP или telnet, определяется обмен сообщениями. В вашем случае в основном сторона Android не знает, какой объем данных будет получать. После использования буферизованного считывателя вы получите буферный ответ, а не весь.

В протоколе telnet, например, есть команды управления. Таким образом, система продолжает работать.

Чтобы решить случай:

  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. 

В дополнении к этому вы можете реализовать команды управления. Например, вы можете захотеть, приемник, чтобы закрыть соединение, чтобы ваш кадр может быть:

 
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. 
+0

Что именно вы подразумеваете под командами управления? не могли бы вы привести мне несколько примеров? –

Смежные вопросы