Reconnect Serial Port on Processing - java

I'm using processing and I'm reading inputs from Arduino with a serial port but connection drop may occur, in this case how to I reopen this connection?

You can catch RuntimeExceptions thrown by Serial.java, which generally indicate the serial port is no longer available. Within that catch block, then, you can start polling the serial port; once it allows you to reinstantiate your Serial instance, the port is again available (e.g. the USB cable is plugged back in) and you're back in the game.
Serial serial;
boolean serialInited;
void setup () {
initSerial();
}
void draw () {
if (serialInited) {
// serial is up and running
try {
byte b = serial.read();
// fun with serial here...
} catch (RuntimeException e) {
// serial port closed :(
serialInited = false;
}
} else {
// serial port is not available. bang on it until it is.
initSerial();
}
}
void initSerial () {
try {
serial = new Serial(this, Serial.list()[0], BAUD_RATE);
serialInited = true;
} catch (RuntimeException e) {
if (e.getMessage().contains("<init>")) {
System.out.println("port in use, trying again later...");
serialInited = false;
}
}
}
Rather than attempting to reconnect every frame, you might instead want to use a counter that limits the frequency of reconnection attempts. (e.g. count to 10, try again, repeat as needed.) Shouldn't matter that much, but dunno...banging that hard on the serial port may have unexpected side effects due to something I know little about.

In the Arduino IDE, you would have to close the Serial port monitor and then go back to [Tools] -> [Serial Port] to re-select your serial port.
This is because when you disconnect the cable, you are removing the serial device you were previously using. Linux handles this better than windows, but either way, it plays havoc with the serial monitor.
Instead of removing the USB cable, you should press the reset button on the board to restart your program.
Also, keep in mind that many Arduinos have an Auto-Reset on Serial communication "feature". I posted directions to a work-around here.

Related

Can't detect disconnect without extra readLine() loop

I am developing a program that uses sockets and currently I have a function in my code that checks for a heartbeat from the client every second.
private void userLoop() { // checks for incoming data from client
Timer t = new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
try {
socketIn.read(); // check for heartbeat from client
String userInput;
while ((userInput = br.readLine()) != null) {
}
} catch (Exception e) {
ControlPanel.model.removeElement(getUsername());
ControlPanel.append(getUsername() + " has disconnected.");
}
}
}, 1000);
}
When a client closes the game via the X button, shutting off their computer, logging out, whatever it may be, I get the message "'username' has disconnected". This is exactly what I want, however, it only works with the while loop in the code. The while loop essentially does nothing and I have no idea why it doesn't work with out.
If I remove the while loop and I disconnect using my client nothing gets printed out server sided.
String userInput;
while ((userInput = br.readLine()) != null) {
}
The above is essentially the dead code that does nothing but without it my program doesn't work the way it should..
Why is the code needed and how can I remove it and still make my program work correctly?
In this case, your while loop is essentially stalling your program until you no longer receive an input string. It's not dead code; it is just your way of installing a wait.
Otherwise, based on my understanding in the Timer class, it only waits one second, which might be too short of a timespan for what you're waiting to capture.
I fixed my problem by changing everything in the try block with
br.readLine();
There's a saying I've heard about exception handling: "Exceptions should only be used for exceptional situations." A client disconnecting from a server is not exceptional.
Now that I have that off my chest, let's move on. According to this other question,
socket.getInputSteam.read() does not throw when I close the socket from the client
it sounds like the read call won't throw if you're closing things properly on the client side.
The problem is that when the remote socket is closed, read() does not throw an Exception, it just returns -1 to signal the end of the stream.
The following should work without needing to call readLine():
try {
int ret = socketIn.read(); // check for heartbeat from client
if (ret == -1) {
// Remote side closed gracefully
clientDisconnected();
}
} catch (SocketTimeoutException e) {
// Timeout -- handle as required
handleTimeout();
} catch (IOException e) {
// Connection lost due to I/O error
clientDisconnected()
}

How do I detect when a serial port has been closed by the device in java?

I'm currently using RXTX to handle serial communication in my java program and I have successfully been able to connect/disconnect and read/write.
However I haven't be able to figure out if there is a way in RXTX to detect if a device disconnects on it's end. How would you detect this event without polling the serial ports? Since if it disconnects and reconnect between polls it wouldn't be detected but still cause errors when the serial port is used.
If it isn't possible in RXTX are there any libraries that would be recommend that can detect a disconnect event?
Clarification: The device is connected over USB and registers as a serial device. The device may disconnect when it either resets or turns off. When it resets the serial port is momentarily closed invalidation the connection RXTX created.
Thanks for any help
I have the same problem: I was trying to know when the device was unplugged from the USB port.
Then, I found out that every time I unplugged the device from the USB port, it gets a java.io.IOException from the serialEvent. Take a look at my serialEvent code below:
#Override
public void serialEvent(SerialPortEvent evt) {
if(this.getConectado()){
if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE)
{
try {
byte singleData = (byte)input.read();
if (singleData == START_DELIMITER)
{
singleData = (byte)input.read();
if(singleData == (byte)0x00)
{
singleData = (byte)input.read(); //get the length
byte[] buffer = new byte[singleData+4];
for(byte i=0x0;i<singleData;i++)
buffer[i+3] = (byte)input.read();
buffer[buffer.length-1] = (byte)input.read();
buffer[0] = START_DELIMITER;
buffer[1] = 0x00;
buffer[2] = singleData; //length
this.addNaLista(buffer);
}
}
} catch (IOException ex) {
Logger.getLogger(Comunicador.class.getName()).log(Level.SEVERE, null, ex);
/* do something here */
//System.exit(1);
}
}
}
}
Even if I am not receiving data at that moment, I still get the java.io.IOException; here is the exception trace:
Jun 21, 2014 10:57:19 AM inovale.serial.Comunicador serialEvent
SEVERE: null
java.io.IOException: No error in readByte
at gnu.io.RXTXPort.readByte(Native Method)
at gnu.io.RXTXPort$SerialInputStream.read(RXTXPort.java:1250)
at inovale.serial.Comunicador.serialEvent(Comunicador.java:336)
at gnu.io.RXTXPort.sendEvent(RXTXPort.java:732)
at gnu.io.RXTXPort.eventLoop(Native Method)
at gnu.io.RXTXPort$MonitorThread.run(RXTXPort.java:1575)
The only events I am using is:
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
This is the way I see to detect a disconnect (physically) event.

BufferedReader skipping random characters when reading from USB

I'm using a BufferedReader to read data from an USB gateway which periodically receives ZigBee network frames from an Arduino device.
This is what the frame is supposed to look like:
~f�}3�#v<-,R#}3�#v<--mac:0013A20040763C2D -H:-25.80 -T:22.58 -L:2.6451 -N:100.00 -D:0.0290 -B:35
But instead, it's always missing some characters near the end of the MAC address, like so:
~f�}3�#v<-,R#}3�#v<--mac:0013A2004076D -H:-25.80 -T:22.58 -L:2.6451 -N:100.00 -D:0.0290 -B:35
Or
~f�}3�#v<-,R#}3�#v<--mac:0013A2004076C2:-25.80 -T:22.58 -L:2.6451 -N:100.00 -D:0.0290 -B:35
The garbage at the beginning is low-level network header info, I guess.
I'm on Ubuntu, and the frames show perfectly fine when reading from a terminal, using
cat /dev/ttyUSB0
The code I use to read from the USB port looks like this. It runs in its own Thread.
public void run() {
Boolean keepRunning = true;
BufferedReader br = new BufferedReader(new InputStreamReader(portReader.getInputStream()));
String line;
while (keepRunning) {
try {
while ((line = br.readLine()) != null) {
handleData(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
I'm using RXTXcomm.jar, available here http://rxtx.qbang.org/wiki/index.php/Main_Page
This is where I open the port.
while (!connected && !timedOut) {
System.out.print("\n\nConnecting to " + portName);
//Open Ports
CommPort commPort = portIdentifier.open(this.getClass()
.getName(), 9600);
//TODO Should we rule out other kinds?
if (commPort instanceof SerialPort) {
//Pass the open port
SerialPort serialPort = (SerialPort) commPort;
serialPort.enableReceiveTimeout(15000);
//Configure the port communication interface
serialPort.setSerialPortParams(bauds,
SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
//Open a stream and read from the port
inputStream = serialPort.getInputStream();
int portBuffer = inputStream.read();
//Check if there is something in the buffer, which
//means that a connection was established
if (portBuffer > -1) {
connected = true;
} else {
System.err.println("Connection to " + portName
+ " timed out");
serialPort.close();
inputStream.close();
timedOut = true;
}
} else {
System.err
.println("Error: Only serial ports are handled by this application.");
}
}
Any ideas on what could be going wrong?
well, I'm not sure if that was the problem, but you shouldn't cat on the serial port char device, as it won't setup the serial device properly (with the correct speed reading, parity etc.. and unbuffered). Always use instead screen /dev/ttyUSB0 SPEED, or python -m serial.tools.miniterm or minicom.
The garbage you're talking about that you prints out is indeed the frame data. You can find in the XBee manuals how it is built (the ~ character marking the beginning of a new frame in API mode, followed by the frame type, length, content and CRC). Given the CRC you can check whether the frame is correctly read, if there are no missing bits.
I wrote a XBee datagram parser in C++:
https://github.com/guyzmo/polluxnzcity/blob/master/PolluxGateway/src/xbee/xbee_communicator.C
and participated in one in C:
https://github.com/guyzmo/xbee-comm/blob/master/src/lib/xb_buffer.c
that you may use for inspiration to get things right.
And finally, I had really often contacts problems between the XBee and the board (making all incoming datagrams erroneous etc..). You may want to power cycle and/or replug the xbee dongle each time the data is getting wrong (hence the need of checking the incoming datagrams).

Java Exception - Socket is closed, reliable udp help?

I'm currently using a Java implementation of the Reliable UDP protocol, found [here][1]. The project has absolutely no tutorials so I have found it really hard to identify problems.
I have set up a client and server. The server runs on localhost:1234 and the client runs on localhost:1235. The server is first established, and loops listening for connections.
I then have set it to send a packet to the server. When a packet is sent, the server calls handlePacket() -
DataInputStream i = new DataInputStream(client.getSocket().getInputStream());
short packetID = i.readShort();
i = null;
switch(packetID){
case 3:
Packeta packeta = new Packeta(client);
break;
}
} catch (IOException e) {
e.printStackTrace();
}
I'm currently using a debugging with a small dummy class called Packeta. When the constructor is called, it reads from a stream and the logs to the console. However, always when constructing, it hangs for 10 seconds, before producing the error -
java.net.SocketException: Socket is closed ....
at
lessur.engine.net.packets.Packeta.(Packeta.java:15)
The constructor for Packeta -
public Packeta(LessurConnectedNode c) {
super((short)3, c);
try {
/*LINE 15*/ Logger.getLogger("adsfas").info("X was "+c.getSocket().getInputStream().read());
} catch (IOException e) {
e.printStackTrace();
}
}
It has something todo with the input streams. I don't know what is wrong, but from reading other threads, it might be todo with having multiple inputstreams. I'm lost on this, please help.
The problem was, I was passing the server to the socket listener, before the socket was fully initialized. FIXED!

Best way to recover a server from a client's disconnect

I've written a tcp server in Java. It spawns worker instances (Runnable) and listens for incoming tcp connection. Upon connection from a client, it will take in data from the client and does its own processing.
Of late, I noticed that upon client disconnection, the entire server will crash with error java.net.SocketException: Connection reset when the client disconnects or quits. This was when I realised I hadn't tested the tcp server thoroughly for all instances of failure.
I looked into the code and noticed that the tcp server will crash at this line while((bytesRead.... -1) in the worker instance
final int BUFFSIZE = 65535;
int bytesRead;
byte[] buffer = new byte[BUFFSIZE];
din = new BufferedInputStream(clientSocket.getInputStream());
while ((bytesRead = din.read(buffer)) != -1) { //tcp server crashes at this line if client quits or disconnects.
// worker does its job.
}
I've been pondering about the best way to close worker instance without causing a crash on the tcp server. I don't have access to the client source code to modify anything on their end.
Any thoughts?
Bregs
Yakult121
Network I/O should be done within a try/catch block if you want to handle exceptions.
This line should throw an IOException if the connection is closed. Just make sure to catch the IOException and return from the run() method of your Runnable when it occurs. This will stop the thread handling this client connection.
You must have done something incorrectly if it craches the whole server, though. This probably means you don't have a thread per client connection, but rather a single thread handling the clients sequentially, one at a time. Post the server code for more information.
figured out the problem. Writing down what i did for any person looking to solve the same problem.
private boolean isStopped = false;
while (!isStopped()) {
try {
while ((bytesRead = din.read(buffer)) != -1) {
// worker does its job.
}
}
catch (IOException ex) {
System.out.println("Exception called! Most likely due to client disconnect!");
stop();
}
}
public boolean isStopped() {
return this.isStopped;
}
public synchronized void stop(){
this.isStopped = true;
}

Categories