B4J Question COM Port (Serial) Proper Way to Close and Re-Open

walterf25

Expert
Licensed User
Longtime User
Hi Everyone, I am using the Jserial library to communicate with a device, this device enumerates 3 different COM Ports but only one can be open to communicate with the device, the other two are for debugging purposes, so far everything works as expected, however I had the need to come up with a way to detect when the COM port has been unplugged and plugged back in.

I found this project here and decided to do a small wrapper for it, this seems to do exactly what I need as it raises two events, One when the COM Port is disconnected and another when the COM Port is connected back again, all this as I mentioned works perfect for my purposes.

The issue I am having now and I know this is probably an easy fix, is that I need to Re-establish the COM port communication after the USB COM Port has been disconnected and re-connected again.

I thought it would be as easy as re-initializing the Serial object and passing the COMPort String to re-open the port again, but I am seeing some issues where the com port communication will be established intermittently, where sometimes it will work and some others it wont.

Is there anything special that needs to be done as far as the JSerial library goes, I am using the Astreams Library as well to be able to capture the data being sent by the device and be able to send data back to the device as well. My question is, is there any special handling that needs to be done on the comport side when the cable is disconnected, i.e. flush any buffers etc.

Below is the functions that capture when the USB COM Port is disconnected and re-connected and how I am handling the reconnection of the serial port.
COM Port Disconnection:
Sub hid2_HidDeviceAttached (PID As Int, VID As Int)
    Log($"new device attached with PID ${PID} and VID ${VID}"$)
    If Not(Common.PortFound) Then
    Dim rs As ResumableSub = FindComPorts
    wait for (rs) complete (comport As String)
    Log("comport: " & comport)
    Common.ComPort = comport
    OpenComPort(Common.ComPort)
    End If
End Sub

Sub hid2_HidDeviceDetached (PID As Int, VID As Int)
    Common.PortFound = False
    Log($"new device Detached with PID ${PID} and VID ${VID}"$)
End Sub

Public Sub OpenComPort(comport As String)
    Try
        If rpc.IsInitialized Then
            Log("opening or re-opening comport: " & comport)
            Main.ser.Close
        End If
        Main.ser.Initialize("serial")
        Main.ser.Open(comport)
        Main.ser.SetParams(115200, 8, 1, 0)
        Sleep(500)
        rpc.Initialize(Me)
        rpc.Flush
    Catch
        Log("error opening comport: " & LastException.Message)
    End Try
End Sub

As you can see the it should be very straight forward, but for some reason when I try re-opening the COM Port again, I don't get any errors but I can tell that the communication is not working, if it was I would start seeing data right away from the device, I can't go into too much detail about the device itself because is highly confidential but is essentially a custom device running a custom Android Image.

Any thoughts on what may be needed, or what I may be doing wrong. I just can't seem to be able to re-open the COM Port back after being closed.

Thanks All.
Walter
 

MicroDrie

Well-Known Member
Licensed User
Detecting a broken serial connection is a challenging job because it is not supported in a serial interface. You can combine with one or more options below:

  1. From the library you used the interface routines: HidDeviceDetached, HidDeviceAttached and (not shown) hidDataReceived. There is also a hidFailure event function in the interface of the hid4java library. The question is what does disconnecting the serial connection result in as an event?

  2. In addition to this software detection, you can also use the hardware RTS/CTS flow control (detection is also possible via the hidFailure event function).

  3. Furthermore, you may be able to use the CTS signal to see if the connection is broken between the receiver and transmitter. If you do not have a free core in the cable for this, you can put a loop in the serial connector.
 
Upvote 0

walterf25

Expert
Licensed User
Longtime User
Detecting a broken serial connection is a challenging job because it is not supported in a serial interface. You can combine with one or more options below:

  1. From the library you used the interface routines: HidDeviceDetached, HidDeviceAttached and (not shown) hidDataReceived. There is also a hidFailure event function in the interface of the hid4java library. The question is what does disconnecting the serial connection result in as an event?

  2. In addition to this software detection, you can also use the hardware RTS/CTS flow control (detection is also possible via the hidFailure event function).

  3. Furthermore, you may be able to use the CTS signal to see if the connection is broken between the receiver and transmitter. If you do not have a free core in the cable for this, you can put a loop in the serial connector.
I think I probably didn't make my message clear, I am using the HidDeviceAttached and HidDeviceDetached functions precisely to capture when a new usb device has been plugged in and when a device has been unplugged, the problem is not that I don't know when the serial communication has been lost.

The problem is that after I try to re-establish the serial communication after the usb being unplugged and being plugged back in, that the serial communication doesn't work as expected. For example I get the following error after the Serial communication has been re-established.
new device attached with PID 516 and VID 3368
stdout: COM102
comports: COM102
opening or re-opening comport: COM102
com port opened: true
java.lang.RuntimeException: Failed to write data. Data length = 6
at anywheresoftware.b4j.serial.Serial$2.write(Serial.java:210)
at anywheresoftware.b4j.serial.Serial$2.write(Serial.java:197)
at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AOUT.run(AsyncStreams.java:380)
at java.base/java.lang.Thread.run(Thread.java:832)
java.lang.RuntimeException: java.lang.RuntimeException: Failed to write data. Data length = 6
at anywheresoftware.b4j.serial.Serial$2.write(Serial.java:213)
at anywheresoftware.b4j.serial.Serial$2.write(Serial.java:197)
at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AOUT.run(AsyncStreams.java:380)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.RuntimeException: Failed to write data. Data length = 6
at anywheresoftware.b4j.serial.Serial$2.write(Serial.java:210)
... 3 more
Astream Error
As you can see the HidDeviceAttached function is fired up and once it does I re-open the com port again but it throws an error when I try to send some data to the device.

My assumption is the following, that there was probably some data that was either being sent or being received when the usb disconnection occurs but then when the serial connection is re-established whatever data was left over somehow screws the newly established connection, I may be wrong but that's my input on this.

My problem is not knowing how to empty or clear whatever buffer was left from the previous connection.

Hope this makes a little more sense.

Walter
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
My problem is not knowing how to empty or clear whatever buffer was left from the previous connection.
The problem exists on both sides, with the problem being that you only have control over the software on the local side. So if you send something and the connection is broken, part of the sent message does not reach the receiving party. Therefore, the status signals Request To Send (RTS) and Clear To Send (CTS) and Carrier Detect (CD) are intended in a serial connection. The question is whether you can use one or more signals in the connection with the number of available cores, or which serial connector and how many cores does the cable consist of?
 
Upvote 0
Top