SerialListener.java
/*
* Copyright © 2016 Greg Chabala
*
* This file is part of brick-control-lab.
*
* brick-control-lab is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* brick-control-lab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with brick-control-lab. If not, see http://www.gnu.org/licenses/.
*/
package org.chabala.brick.controllab;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
/**
* Handles serial events.
*/
class SerialListener implements SerialPortEventListener {
private final Logger log = LoggerFactory.getLogger(getClass());
private final SerialPort serialPort;
private final InputManager inputManager;
private final boolean ignoreBadHandshake;
private boolean handshakeSeen = false;
private CountDownLatch handshakeLatch = new CountDownLatch(1);
private StringBuilder handshakeBuilder = new StringBuilder();
SerialListener(SerialPort serialPort, InputManager inputManager) {
this.serialPort = serialPort;
this.inputManager = inputManager;
ignoreBadHandshake = Boolean.valueOf(
System.getProperty("brick-control-lab.ignoreBadHandshake", "false"));
}
@Override
public boolean isHandshakeSeen() {
boolean returnedEarly = false;
try {
returnedEarly = handshakeLatch.await(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
Thread.currentThread().interrupt();
}
return handshakeSeen || returnedEarly;
}
private void setHandshakeSeen() {
handshakeSeen = true;
handshakeLatch.countDown();
handshakeBuilder = null;
}
/** {@inheritDoc} */
@Override
public void serialEventRXCHAR(int availableBytes) {
if (!handshakeSeen) {
processHandshake(availableBytes);
} else {
if (availableBytes >= Protocol.FRAME_SIZE) {
try {
byte[] buffer = serialPort.readBytes(Protocol.FRAME_SIZE);
inputManager.processInputSensors(buffer);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
}
private void processHandshake(int availableBytes) {
try {
while (!handshakeSeen && availableBytes > 0) {
availableBytes--;
handshakeBuilder.append(new String(serialPort.readBytes(1), ISO_8859_1));
if (handshakeBuilder.length() >= Protocol.HANDSHAKE_RESPONSE.length()) {
String handshake = handshakeBuilder.toString();
if (handshake.endsWith(Protocol.HANDSHAKE_RESPONSE)) {
log.info("RX <- {}", handshake);
setHandshakeSeen();
} else {
log.error("Bad handshake: {}", handshake);
if (ignoreBadHandshake) {
setHandshakeSeen();
} else {
serialPort.close();
return;
}
}
}
}
if (!handshakeSeen) {
log.debug("Current handshake: {}", handshakeBuilder);
}
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}