B4J Question Jserial Error

Duncan williamson

Member
Licensed User
Longtime User
I have been writing an b4j app to monitor various aspects of my network, this includes checking hardware is online, pinging servers etc. changes of status send messages via Firebase if there are changes... this is all working well except that if my internet connection dies firebase fails.. To overcome this I have utilised a cell modem plugged into a serial port to send sms messages if the internet fails, this uses Jserial and I have used try/end try to capture serial errors during initialisation however I cannot work out how to capture errors caused by the serial link disconnecting during use. for example if the USB cable becomes unplugged or the modem looses power.
The error is as below if this happens....

java.lang.NegativeArraySizeException: -1
at jssc.SerialNativeInterface.readBytes(Native Method)
at jssc.SerialPort.readBytes(SerialPort.java:437)
at anywheresoftware.b4j.serial.Serial$1.read(Serial.java:165)
at anywheresoftware.b4j.serial.Serial$1.read(Serial.java:157)
at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AIN.run(AsyncStreams.java:216)
at java.base/java.lang.Thread.run(Thread.java:834)
java.lang.RuntimeException: java.lang.NegativeArraySizeException: -1
at anywheresoftware.b4j.serial.Serial$1.read(Serial.java:172)
at anywheresoftware.b4j.serial.Serial$1.read(Serial.java:157)
at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AIN.run(AsyncStreams.java:216)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.NegativeArraySizeException: -1
at jssc.SerialNativeInterface.readBytes(Native Method)
at jssc.SerialPort.readBytes(SerialPort.java:437)
at anywheresoftware.b4j.serial.Serial$1.read(Serial.java:165)
... 3 more
error: (NegativeArraySizeException) java.lang.NegativeArraySizeException: -1

Any suggestions will be gratefully accepted :)
 

DonManfred

Expert
Licensed User
Longtime User
And the relevant code is?
 
Upvote 0

emexes

Expert
Licensed User
It looks like you're tryng to read bytes from an empty buffer

but as @DonManfred points out, it'd be a heck lot easier for us to help if we could see the subroutine where this error occurs 🍻
 
Upvote 0

Duncan williamson

Member
Licensed User
Longtime User
It looks like you're tryng to read bytes from an empty buffer

but as @DonManfred points out, it'd be a heck lot easier for us to help if we could see the subroutine where this error occurs 🍻
My apologies....
I have attached a cut down version of my project ... All it is doing at the moment is sending a string to the modem which returns the signal strength.
if the modem is not plugged into the relevant USB port when the project starts then the error is captured.. if however the modem is unplugged or looses power after that then I cannot capture the error and the project falls over... this happens as soon as the port is unplugged, it does not have to be sending or receiving data..
 

Attachments

  • netmon.zip
    45.9 KB · Views: 165
Upvote 0

emexes

Expert
Licensed User
this happens as soon as the port is unplugged, it does not have to be sending or receiving data..
I am getting out of my depth here.

My only idea at the moment is that the error is occurring when the AsyncStream poll timer tick calls the Java serial interface to check for more data.

So a workaround might be to do the asynch side yourself, ie set up a 10-100 ms timer to poll the Java serial interface yourself, and wrap the serial poll call in a Try-Catch.

Or perhaps there is some way of capturing the error when it percolates upward to the B4J main message handler, using a Wait.
 
Upvote 0

Duncan williamson

Member
Licensed User
Longtime User
I am getting out of my depth here.

My only idea at the moment is that the error is occurring when the AsyncStream poll timer tick calls the Java serial interface to check for more data.

So a workaround might be to do the asynch side yourself, ie set up a 10-100 ms timer to poll the Java serial interface yourself, and wrap the serial poll call in a Try-Catch.

Or perhaps there is some way of capturing the error when it percolates upward to the B4J main message handler, using a Wait.
Hi
I must admit I am floundering around here.... but I think your suggestion is a good one, I will have a play around tonight and see what I can see..
 
Upvote 0

emexes

Expert
Licensed User
I must admit I am floundering around here.... but I think your suggestion is a good one, I will have a play around tonight and see what I can see..
At least you're not floundering alone 🍻

Speaking of which: I just realized I can probably reproduce the error here, and...

1594359612375.png


Voila!
 
Upvote 0

emexes

Expert
Licensed User
Curiously, I can't read the port with the regular (non-async) stream. Hmm. And there was mention of a timer being used there also, so: double-hmm.

On the bright side, if I close the asyncstream and port, and *then* yank the cable, there is no error.

I'll look at this again tonight.
 
Upvote 0

Chris2

Active Member
Licensed User
I can't help directly with your problem and this might be not be relevant, but the NegativeArraySizeException error message you're getting (or very similar) is very common with jSerial, but often doesn't cause the app to fall over -
https://www.b4x.com/android/forum/t...after-program-termination.108184/#post-676464 (posts 3 to 7)
.

I wonder if it's a red herring here?

Also, a while ago I had a problem with jSerial on a Raspberry PI that caused my app to crash. The cause was I think to do the the PI itself rather than jSerial, but a (slightly imperfect) work around I found in these forums was to have a second app running that periodically checked if the main app was running and restarted it if necessary.
 
Upvote 0

Duncan williamson

Member
Licensed User
Longtime User
I can't help directly with your problem and this might be not be relevant, but the NegativeArraySizeException error message you're getting (or very similar) is very common with jSerial, but often doesn't cause the app to fall over -
https://www.b4x.com/android/forum/t...after-program-termination.108184/#post-676464 (posts 3 to 7)
.

I wonder if it's a red herring here?

Also, a while ago I had a problem with jSerial on a Raspberry PI that caused my app to crash. The cause was I think to do the the PI itself rather than jSerial, but a (slightly imperfect) work around I found in these forums was to have a second app running that periodically checked if the main app was running and restarted it if necessary.
Thanks for the reply, The app does not fall over it just freezes....I would prefer to have just one app running if I can but a checking app is an option..
I have to demo this ability to monitor the network to a potential customer in the next couple of days so as an interim workaround I have rewritten it in VB.net however it is my aim to use only B4J in the long run.
The App also has network connection to an arduino Uno with a network shield which is used to monitor physical contact closures and this is working flawlessly , the cell modem im using ( a Sierra wireless Raven XE ) also has a network port, so I may investigate using that rather than the serial port ....
 
Upvote 0

Chris2

Active Member
Licensed User
At the risk of saying something silly, obvious, or irrelevant....

If you're connecting the Raven XE to a USB port rather than an old fashioned 9 pin serial port, I presume it's installing as a virtual comms port with the FTDI driver or similar?
If so, when the cable is pulled the virtual comms port will disappear.

So is the problem caused by having an open comms port disappearing, rather than you trying to talk to a device that is no longer connected/powered?

In the example netmon you posted, you're checking for & opening the serial port only during AppStart;
B4X:
Sub AppStart (Form1 As Form, Args() As String)

    Log(sp.ListPorts)   
        :
        :
    Try
        sp.Initialize("sp")
        sp.Open(SettingsMap.Get("comm"))
        sp.SetParams(115200, 8, 1, 0)
    Catch
        Log(LastException.Message)
    End Try
        :
        :
End Sub

Hence:
if the modem is not plugged into the relevant USB port when the project starts then the error is captured..

Could you instead check the comms port exists and open it only if it does just before each time you try to use it?
 
Upvote 0

Duncan williamson

Member
Licensed User
Longtime User
At the risk of saying something silly, obvious, or irrelevant....

If you're connecting the Raven XE to a USB port rather than an old fashioned 9 pin serial port, I presume it's installing as a virtual comms port with the FTDI driver or similar?
If so, when the cable is pulled the virtual comms port will disappear.

So is the problem caused by having an open comms port disappearing, rather than you trying to talk to a device that is no longer connected/powered?

In the example netmon you posted, you're checking for & opening the serial port only during AppStart;
B4X:
Sub AppStart (Form1 As Form, Args() As String)

    Log(sp.ListPorts)  
        :
        :
    Try
        sp.Initialize("sp")
        sp.Open(SettingsMap.Get("comm"))
        sp.SetParams(115200, 8, 1, 0)
    Catch
        Log(LastException.Message)
    End Try
        :
        :
End Sub

Hence:


Could you instead check the comms port exists and open it only if it does just before each time you try to use it?
Hi
yes everything you say is correct :)
I have taken another route, I finally found that AT commands can be sent via telnet to the modem, so I incorporated those ideas, the software now connects via telnet, sends commands and then closes the telnet connection ... and does all the relevant error checking at each step...
 
Upvote 0
Top