How can I restart a Bluetooth Server listening?

This is where you talk about the EV3 software itself, installation issues, and programming talk.

Moderators: roger, gloomyandy, skoehler

How can I restart a Bluetooth Server listening?

Postby Programus » Sun Aug 17, 2014 4:56 am

I want to build a robot which could be connected by other Bluetooth clients like an android device. Once the client disconnected, the server could listen again and allow the client to reconnected.
I do this by close the server once client send a disconnect signal to the server and call the BTConnector.waitConnection() again, but it always have native socket errors.

To focus this problem, I built two simple programs:
Code: Select all
public class EV3Test {
   public static void main(String[] args) {
      try {
         System.out.println("Server ready.");
         BTConnector connector = new BTConnector();
         NXTConnection conn = connector.waitForConnection(0, NXTConnection.RAW);
         Delay.msDelay(1000);
         conn.close();
         System.out.println("Server restarted.");
         connector = new BTConnector();
         conn = connector.waitForConnection(0, NXTConnection.RAW);
         Delay.msDelay(1000);
         conn.close();
      } catch (Exception e) {
         e.printStackTrace(System.out);
      }
   }
}

I got an error said
com.sun.jna.LastErrorException: errno was 98
at lejos.internal.io.NativeSocket$Linux_C_lib_DirectMapping.bind(Native Method)
at lejos.internal.io.NativeSocket.bind(Unknown Source)
at lejos.remote.nxt.BTConnector.waitForConnection(Unknown Source)
at org.programus.lejos.test.EV3Test.main(EV3Test.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at lejos.internal.ev3.EV3Wrapper.invokeClass(Unknown Source)
at lejos.internal.ev3.EV3Wrapper.main(Unknown Source)

and
Code: Select all
public class EV3Test {

   public static void main(String[] args) {
      try {
         System.out.println("Server ready.");
         BTConnector connector = new BTConnector();
         NXTConnection conn = connector.waitForConnection(0, NXTConnection.RAW);
         Delay.msDelay(1000);
         conn.close();
         System.out.println("Server restarted.");
         conn = connector.waitForConnection(0, NXTConnection.RAW);
         Delay.msDelay(1000);
         conn.close();
      } catch (Exception e) {
         e.printStackTrace(System.out);
      }
   }
}

with this error
com.sun.jna.LastErrorException: errno was 77
at lejos.internal.io.NativeSocket$Linux_C_lib_DirectMapping.bind(Native Method)
at lejos.internal.io.NativeSocket.bind(Unknown Source)
at lejos.remote.nxt.BTConnector.waitForConnection(Unknown Source)
at org.programus.lejos.test.EV3Test.main(EV3Test.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at lejos.internal.ev3.EV3Wrapper.invokeClass(Unknown Source)
at lejos.internal.ev3.EV3Wrapper.main(Unknown Source)

The only difference between these two program is that I recreated a new instance of BTConnector before I start the listening in the 1st one while reuse the same BTConnector in the 2nd one.

I did some investigation about these errno, and I found this
#define EADDRINUSE 98 /* Address already in use */
#define EBADFD 77 /* File descriptor in bad state */

And according to the java source of BTConnector.waitConnection(), I guess, in the 1st case, the error is because the instance of NativeSocket in BTConnector is not destroyed and still using the address; and in the 2nd case, the error is because a rebind.

I cannot find a way to get out by current leJOS framework. Is there any way to implement a bluetooth server could be reconnected without relaunching the whole program?
User avatar
Programus
Novice
 
Posts: 34
Joined: Fri Sep 18, 2009 1:43 pm
Location: China

Re: How can I restart a Bluetooth Server listening?

Postby gloomyandy » Sun Aug 17, 2014 6:57 am

This code is all pretty new and untested. Lawrie may have some suggestions, but it looks like a bug in the leJOS code, fix it and rebuild the ev3classes.jar, let us know what the fix is that you come up with.
User avatar
gloomyandy
leJOS Team Member
 
Posts: 4084
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Re: How can I restart a Bluetooth Server listening?

Postby Programus » Sun Aug 17, 2014 9:42 am

gloomyandy wrote:This code is all pretty new and untested. Lawrie may have some suggestions, but it looks like a bug in the leJOS code, fix it and rebuild the ev3classes.jar, let us know what the fix is that you come up with.


Well, unfortunately, I am not familiar with the socket programming about Linux at all. But if there is no existed solution, I would like to have a try.
I would like to wait a while to see whether Lawrie would bring a better news. 8)

btw. where can I find the native C code for NativeSocket class? I did not find it in the sourceforge git repository...
User avatar
Programus
Novice
 
Posts: 34
Joined: Fri Sep 18, 2009 1:43 pm
Location: China

Re: How can I restart a Bluetooth Server listening?

Postby gloomyandy » Sun Aug 17, 2014 4:36 pm

There is no C code for that class, on the Ev3 we make use of JNA, which allows us to call native libs directly from Java. The classes you are looking for are here:
https://sourceforge.net/p/lejos/ev3/ci/ ... ternal/io/
User avatar
gloomyandy
leJOS Team Member
 
Posts: 4084
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Re: How can I restart a Bluetooth Server listening?

Postby Programus » Mon Aug 18, 2014 1:43 pm

gloomyandy wrote:There is no C code for that class, on the Ev3 we make use of JNA, which allows us to call native libs directly from Java. The classes you are looking for are here:
https://sourceforge.net/p/lejos/ev3/ci/ ... ternal/io/


Thank you! I had located the java classes, but I knew nothing about JNA before. I will learn about JNA and then get back to the problem.
btw. Is there a spell that could call Lawrie out and give me a hand? :P
User avatar
Programus
Novice
 
Posts: 34
Joined: Fri Sep 18, 2009 1:43 pm
Location: China

Re: How can I restart a Bluetooth Server listening?

Postby lawrie » Mon Aug 18, 2014 7:01 pm

It is a while since I worked on this. I will have a look at it. I stopped working on Bluetooth serial partly because of the unsupported state of Java Bluetooth projects like Bluecove and DbusJava. There was a lot of JNA code to write and support, and it is difficult.
lawrie
leJOS Team Member
 
Posts: 922
Joined: Mon Feb 05, 2007 1:27 pm

Re: How can I restart a Bluetooth Server listening?

Postby Programus » Tue Aug 19, 2014 1:40 pm

lawrie wrote:It is a while since I worked on this. I will have a look at it. I stopped working on Bluetooth serial partly because of the unsupported state of Java Bluetooth projects like Bluecove and DbusJava. There was a lot of JNA code to write and support, and it is difficult.


I think the Bluetooth connection interface inherit from NXT API is enough for most use cases. Just get rid of this bug, it is pretty good for me. :)
(Maybe another improvement might be necessary is the timeout support, but I do not need it yet. )

I learned a little about JNA and Bluetooth programming in Linux recently and found a solution to fix this bug.
The solution is just add a close() method in BTConnector class, and once the connection is lost, just close the current BTConnector and recreate a new instance for the next connection.

Here is the code:

BTConnector.close
Code: Select all
public class BTConnector extends NXTCommConnector  {
   NativeSocket socket = new NativeSocket(NativeHCI.AF_BLUETOOTH, NativeHCI.SOCK_STREAM, NativeHCI.BTPROTO_RFCOMM);

// other methods here....

   /**
    * Close the internal server socket.
    * This method MUST be invoked before you want to create a new instance of BTConnector.
    */
   public void close() {
      this.socket.close();
   }
}


EV3Test, the simple testing code.
Code: Select all
public class EV3Test {

   public static void main(String[] args) {
      try {
         while (!Button.ESCAPE.isDown()) {
            System.out.println("Server ready.");
            BTConnector connector = new BTConnector();
            NXTConnection conn = connector.waitForConnection(0, NXTConnection.RAW);
            Delay.msDelay(1000);  // some data transfer here in the real case
            conn.close();
            connector.close();
            System.out.println("Server closed.");
         }
      } catch (Exception e) {
         // to redirect error message to EV3Control
         e.printStackTrace(System.out);
      }
   }
}


I am not sure whether this is a leJOSful or standard way to solve this problem. At least it works for me.

Could you please tell me what kind of solution would you put into the next release since I am writing a book about some projects that connect Android device with EV3 by leJOS and I hope the hack to ev3classes is not necessary for the readers of the book.
User avatar
Programus
Novice
 
Posts: 34
Joined: Fri Sep 18, 2009 1:43 pm
Location: China


Return to EV3 Software

Who is online

Users browsing this forum: No registered users and 2 guests

more stuff