I am trying to create a class which sends and receives commands via serial port. Sadly the whenComplete is never called. I also tried to log the response and in the callback it is correct but when I try to get the variable in execute, it is completely different and looks like some random bytes. I tried to use the Latch to get the callback data. Is there any better way?
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Device {
private static final String port = "/dev/ttyS0";
private static final int baud = 9600;
private SerialHelper2 serialPort;
private final int timeout = 500;
private CountDownLatch responseLatch;
private String response;
public Device() {
}
public boolean open() {
this.serialPort = new SerialHelper2(port, baud) {
@Override
protected void onDataReceived(final byte[] data) {
Device.this.response = new String(data).trim();
Serial.out.println(Device.this.response); // Output is correct
Device.this.responseLatch.countDown();
}
};
try {
this.serialPort.open();
return this.serialPort.isOpen();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public CompletableFuture<String> execute(String cmd) {
// reset latch
Device.this.responseLatch = new CountDownLatch(1);
return CompletableFuture.supplyAsync(() -> {
Device.this.serialPort.sendHex(cmd);
try {
if (responseLatch.await(Device.this.timeout, TimeUnit.MILLISECONDS)) {
Serial.out.println(Device.this.response); // Complete garbage. Looks like some wrong memory access?
return Device.this.response;
} else { // Timeout exceeded
throw new TimeoutException(String.format("Command '%s' timed out after %d ms", cmd, Device.this.timeout));
}
} catch (Exception e) {
throw new IllegalStateException(e);
}
});
}
public CompletableFuture<Boolean> init() {
return this.execute("REQ")
.thenApply(res -> res.equalsIgnoreCase("RES"));
}
}
Somewhere I call:
device.init()
.whenComplete((result, ex) -> {
if (null != ex) {
Serial.out.println("Failed")
} else {
Serial.out.println("Device initialization " + (result ? "succeeded" : "failed"));
}
});