1

UPDATE: Thank you for the thoughts. I have debugged the issue I believe down to the connection between the android to the ESP8266. I believe there may be something going on with the ESP because when I connect the android to my pc it seems to connect and work well. There are some very minor delays but nothing like when it is connected to the ESP. Therefore I am thinking the ESP is causing the delay. That being said I am not sure what could cause this. I have tried using the ESP8266 2.3.0 ver of the libraries in Arduino IDE 1.6.8 but can't seem to figure out why the delay. I did connect the android app to my internal router and then send to the PC with no issues. However it doesn't seem to work with the ESP. I can't believe I am the only one that is seeing this... If anyone else has this working please let me know how you did it. My eternal gratitude would be yours.

Here is the ESP Arduino code:

WiFiServer server(2390); // TCP/IP
SoftwareSerial mySerial( 4, 5);    // RX, TX
void setup( ) 
{
    Serial.begin( 115200 );
    WiFi.mode(WIFI_STA);
    WiFi.softAP( "mySSID", "myPASS");

    server.begin();// START TCP/IP SERVER 
}
WiFiClient client;
void loop( ) 
{
    if (client) 
    {
        while (client.connected()) 
        {
            if (client.available()) 
            {
                char command = client.read();
                Serial.println(itoa(command,buffer,10));
            }
        }
    }
    else
    {
        client = server.available();
    }
}

I am trying to get almost instantaneous communication using TCP/IP sockets between android (Java) and ESP8266. The problem I am seeing is a significant delay between when I press the button to when the android will actually send the data. It seems to sometimes send right when I tap the Go Button but after the first time it will not send for 5-10 seconds. When it is stuck I tap the Go button a number of times and after the delay they all seem to send at once or start sending in spurts. I look at the network monitor in Android Studio and the delay is noticable from the time I tap the button until the traffic shows up on the network panel in the Monitors tab.

I am using the Android Studio Debugger to test the code.

Is there something that I am not doing correctly? Or perhaps is there a better implementation for near instant communication between devices?

Thank you for your assistance in advance!

Android Device: Samsung Note 4 - v5.1.1 Android v2.0

Android Studio

ESP Device: ESP8266 using Arduino Studio 1.6.8

Here is my Code:

public class MainActivity extends AppCompatActivity 
{
    private Socket socket;


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

    public void onClick(View view) 
    {
        try 
        {
            new AsyncTaskRunner().execute("");
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }

    private class AsyncTaskRunner extends AsyncTask<String, String, String> 
    {
        private String resp;
        ProgressDialog progressDialog;

        @Override
        protected String doInBackground(String... params) 
        {
            try 
            {
                DataOutputStream dataOut;
                Socket s = new Socket("192.168.4.1", 2390);

                dataOut=new DataOutputStream(s.getOutputStream());
                byte[] outputData = new byte[9];
                outputData[0] = 1;
                outputData[1] = 2;
                outputData[2] = 3;
                outputData[3] = 4;
                outputData[4] = 5;
                outputData[5] = 6;
                outputData[6] = 7;
                outputData[7] = 8;
                outputData[8] = 9;
                dataOut.write(outputData); // Red
                dataOut.flush();
                dataOut.close();
                s.close();
            }
            catch (UnknownHostException e)
            {
                e.printStackTrace();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }

            return resp;
        }

        @Override
        protected void onPostExecute(String result) {
        }

        @Override
        protected void onProgressUpdate(String... text) {
        }
    }
}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.jered.networktest.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Go"
        android:onClick="onClick"/>

</RelativeLayout>
Edster
  • 23
  • 5
  • the android code looks fine. could be an issue with the server code. – njzk2 Jul 04 '16 at 03:12
  • AsyncTask may cause add problems. Try using thread and handler – Mark Shen Jul 04 '16 at 03:13
  • 1
    You are making a socket connection every time you want to send a message, Why don't you consider creating a socket connection in an "Intent service" and keeping it alive till you explicitly close the connection. – Arpit Ratan Jul 04 '16 at 03:50
  • @Mark Shen - I tried using thread and handler but I see the same issue. It does seem to be better, however, after 3-4 taps there is a delay. I am going to try the Intent Service method next. – Edster Jul 04 '16 at 05:20
  • Same issue with me, but when enable the airplane mode it works good no delay, Anyone have idea how to fix it? – Vishva Vijay Dec 01 '20 at 10:34

2 Answers2

0

I had this problem for the case while I wanted to transmit some data to an access point Esp8266-01. I think this delay occurred since if (client. available()) inside while (client.connected())loop waits to receive data until client is available. hence, makes a delay (it was exactly 5 seconds me). to avoid this unpleasant behavior, I appended a carriage return '\r' in write command of AsyncTask in the android MainActivity.java file then modified Arduino sketch to wait until the server receives a carriage return, I mean some code like this String request = client.readStringUntil('\r'); finally, two buttons as known as btn1 and btn2 in the android app send two strings /led/on and /led/off respectively. by now ESP8266 receives carriage return and flush client immediately then there is no delay to execute other section of the program. the following program turns one led on or off (GPIO 0 pin of the ESP8266-01) according to the pressed button in Android app. but don't forget to set ground GPIO 0 of ESP8266-01 just while programming it and don't forget to connect mobile wifi to ESP wifi network first but you can use wifi configuration to connect to ESP wifi automatically too (see this link).

Arduino code:

#include<ESP8266WiFi.h>
// WiFi Definitions
const char* ssid = "Esp8266TestNet";
const char* password = "Esp8266Test"; // has to be longer than 7 chars
const char* value = "";

int ledPin = 0; // GPIO 0
WiFiServer server(80);

void setup() {

   Serial.begin(115200);
   delay(10);
   pinMode(ledPin, OUTPUT);
   digitalWrite(ledPin, HIGH); // turn on

   WiFi.mode(WIFI_AP);
   WiFi.softAP(ssid, password, 1, false);
  
   server.begin();
}

void loop() {
  // Check of client has connected
  WiFiClient client = server.available();
  if(!client) {
    return;
  }

  // Read the request line
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();
  
  // Match request
  if(request.indexOf("/led/on") != -1) {
     digitalWrite(ledPin, HIGH);
     value = "on";
  } else if (request.indexOf("/led/off") != -1) {
     digitalWrite(ledPin, LOW);
      value = "off";
  }
  else {
    Serial.println("not validate");
    }
  
  client.flush();
   
  // JSON response
  String s = "HTTP/1.1 200 OK\r\n";
  s += "Content-Type: application/json\r\n\r\n";
  s += "{\"data\":{\"message\":\"success\",\"value\":\"";
  s += value;
  s += "\"}}\r\n";
  s += "\n";

  // Send the response to the client
  client.print(s);
  delay(1);
  Serial.println("Client disconnected");

  // The client will actually be disconnected when the function returns and the client object is destroyed
}

manifest XML:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myhgrtest">
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn1"
        android:text="btn1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        ></Button>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn2"
        android:text="btn2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        ></Button>
</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java:

package com.example.myhgrtest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;

public class MainActivity extends AppCompatActivity {
    Button btn1,btn2;
    TcpClient mTcpClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn1=findViewById(R.id.btn1);
        btn2=findViewById(R.id.btn2);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                send_request1();
            }
        });
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                send_request2();
            }
        });
    }
    public class ConnectTask extends AsyncTask<String, String, TcpClient> {

        @Override
        protected TcpClient doInBackground(String... message) {

            //we create a TCPClient object
            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);
            //response received from server
            Log.d("test", "response " + values[0]);
            //process server response here....

        }
    }
    public void send_request1() {
        send_request1 sr = new send_request1();
        sr.execute();
    }
    public void send_request2() {
        send_request2 sr = new send_request2();
        sr.execute();
    }
    class send_request1 extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... voids) {
            try {             /*note : ip address must be in Quotation mark*/
                /*note : port doesn't need to be inside the Quotation mark*/
                Socket s = new Socket(/*ip address :*/"192.168.4.1",/*port :*/ 80);
                PrintWriter printWriter = new PrintWriter(s.getOutputStream());
                printWriter.write("/led/on"+"\r");
                printWriter.flush();
                printWriter.close();
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        public void onPostExecute(final String Data) {
            /*Data is what you receive from your server*/
            Log.e("my_Data","Data is : " + Data);
        }
    }
    class send_request2 extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... voids) {
            try {
                /*note : ip address must be in Quotation mark*/
                /*note : port doesn't need to be inside the Quotation mark*/
                Socket s = new Socket(/*ip address :*/"192.168.4.1",/*port :*/ 80);
                PrintWriter printWriter = new PrintWriter(s.getOutputStream());
                printWriter.write("/led/off"+"\r");
                printWriter.flush();
                printWriter.close();
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        public void onPostExecute(final String Data) {
            /*Data is what you receive from your server*/
            Log.e("my_Data","Data is : " + Data);
            //Toast.makeText(MainActivity.this, Data, Toast.LENGTH_SHORT).show();
        }
    }

}
-1

I don't think anyone can say for certain where the problem lays. To prevent you (and others) from chasing ghosts, you really want to split up your problem:

  • Make sure your 'doInBackground' isn't delayed, e.g. by logging to the android logging system, console, debugger, or doing something easy in the ui.
  • Make sure sending on the Android side isn't delayed, by writing a tiny listener in e.g. Java, and running that on your PC.
  • Make sure listening isn't delayed, by creating a tiny sender in Java, and running that on your PC.

This way divide your problem till you find the root cause :)

bluemind
  • 1,591
  • 11
  • 16