[bluetooth.bluegiga] Introduced better initialization functionality (#10148)
* [bluetooth.bluegiga] Introduced better initialization functionality + other improvements * [bluetooth.bluegiga] Review change * [bluetooth.bluegiga] Fixed typo Signed-off-by: Pauli Anttila <pauli.anttila@gmail.com>
This commit is contained in:
parent
928859ab86
commit
71dbf2ed1b
|
@ -24,6 +24,7 @@ import java.util.concurrent.CancellationException;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CompletionException;
|
import java.util.concurrent.CompletionException;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
@ -158,6 +159,7 @@ public class BlueGigaBridgeHandler extends AbstractBluetoothBridgeHandler<BlueGi
|
||||||
|
|
||||||
private @Nullable ScheduledFuture<?> removeInactiveDevicesTask;
|
private @Nullable ScheduledFuture<?> removeInactiveDevicesTask;
|
||||||
private @Nullable ScheduledFuture<?> discoveryTask;
|
private @Nullable ScheduledFuture<?> discoveryTask;
|
||||||
|
private @Nullable ScheduledFuture<?> initTask;
|
||||||
|
|
||||||
private @Nullable Future<?> passiveScanIdleTimer;
|
private @Nullable Future<?> passiveScanIdleTimer;
|
||||||
|
|
||||||
|
@ -168,15 +170,40 @@ public class BlueGigaBridgeHandler extends AbstractBluetoothBridgeHandler<BlueGi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
logger.info("Initializing BlueGiga");
|
|
||||||
super.initialize();
|
super.initialize();
|
||||||
Optional<BlueGigaConfiguration> cfg = Optional.of(getConfigAs(BlueGigaConfiguration.class));
|
|
||||||
updateStatus(ThingStatus.UNKNOWN);
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
if (initTask == null) {
|
||||||
|
initTask = scheduler.scheduleWithFixedDelay(this::checkInit, 0, 10, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkInit() {
|
||||||
|
boolean init = false;
|
||||||
|
try {
|
||||||
|
if (!serialHandler.get().isAlive()) {
|
||||||
|
logger.debug("BLE serial handler seems to be dead, reinitilize");
|
||||||
|
stop();
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init) {
|
||||||
|
logger.debug("Initialize BlueGiga");
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void start() {
|
||||||
|
Optional<BlueGigaConfiguration> cfg = Optional.of(getConfigAs(BlueGigaConfiguration.class));
|
||||||
if (cfg.isPresent()) {
|
if (cfg.isPresent()) {
|
||||||
|
initComplete = false;
|
||||||
configuration = cfg.get();
|
configuration = cfg.get();
|
||||||
serialPortFuture = RetryFuture.callWithRetry(() -> {
|
serialPortFuture = RetryFuture.callWithRetry(() -> {
|
||||||
var localFuture = serialPortFuture;
|
var localFuture = serialPortFuture;
|
||||||
logger.debug("Initialize BlueGiga");
|
|
||||||
logger.debug("Using configuration: {}", configuration);
|
logger.debug("Using configuration: {}", configuration);
|
||||||
|
|
||||||
String serialPortName = configuration.port;
|
String serialPortName = configuration.port;
|
||||||
|
@ -288,13 +315,16 @@ public class BlueGigaBridgeHandler extends AbstractBluetoothBridgeHandler<BlueGi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
logger.info("Disposing BlueGiga");
|
if (initTask != null) {
|
||||||
|
initTask.cancel(true);
|
||||||
|
initTask = null;
|
||||||
|
}
|
||||||
stop();
|
stop();
|
||||||
stopScheduledTasks();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stop() {
|
private void stop() {
|
||||||
|
logger.info("Stop BlueGiga");
|
||||||
transactionManager.thenAccept(tman -> {
|
transactionManager.thenAccept(tman -> {
|
||||||
tman.removeEventListener(this);
|
tman.removeEventListener(this);
|
||||||
tman.close();
|
tman.close();
|
||||||
|
@ -309,6 +339,7 @@ public class BlueGigaBridgeHandler extends AbstractBluetoothBridgeHandler<BlueGi
|
||||||
|
|
||||||
serialPortFuture.thenAccept(this::closeSerialPort);
|
serialPortFuture.thenAccept(this::closeSerialPort);
|
||||||
serialPortFuture.cancel(false);
|
serialPortFuture.cancel(false);
|
||||||
|
stopScheduledTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void schedulePassiveScan() {
|
private void schedulePassiveScan() {
|
||||||
|
@ -764,8 +795,7 @@ public class BlueGigaBridgeHandler extends AbstractBluetoothBridgeHandler<BlueGi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bluegigaClosed(Exception reason) {
|
public void bluegigaClosed(Exception reason) {
|
||||||
logger.debug("BlueGiga connection closed, request reinitialization");
|
logger.debug("BlueGiga connection closed, request reinitialization, reason: {}", reason.getMessage());
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, reason.getMessage());
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, reason.getMessage());
|
||||||
initComplete = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ class BlueGigaResponsePackets {
|
||||||
return bleFrame;
|
return bleFrame;
|
||||||
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
|
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
|
||||||
| IllegalArgumentException | InvocationTargetException e) {
|
| IllegalArgumentException | InvocationTargetException e) {
|
||||||
logger.error("Error instantiating BLE class", e);
|
logger.debug("Error instantiating BLE class", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -67,6 +67,8 @@ public class BlueGigaSerialHandler {
|
||||||
parserThread = createBlueGigaBLEHandler(uid);
|
parserThread = createBlueGigaBLEHandler(uid);
|
||||||
parserThread.setUncaughtExceptionHandler((t, th) -> {
|
parserThread.setUncaughtExceptionHandler((t, th) -> {
|
||||||
logger.warn("BluegigaSerialHandler terminating due to unhandled error", th);
|
logger.warn("BluegigaSerialHandler terminating due to unhandled error", th);
|
||||||
|
notifyEventListeners(new BlueGigaException(
|
||||||
|
"BluegigaSerialHandler terminating due to unhandled error, reason " + th.getMessage()));
|
||||||
});
|
});
|
||||||
parserThread.setDaemon(true);
|
parserThread.setDaemon(true);
|
||||||
parserThread.start();
|
parserThread.start();
|
||||||
|
@ -238,7 +240,6 @@ public class BlueGigaSerialHandler {
|
||||||
private void inboundMessageHandlerLoop() {
|
private void inboundMessageHandlerLoop() {
|
||||||
final int[] framecheckParams = { 0x00, 0x7F, 0xC0, 0xF8, 0xE0 };
|
final int[] framecheckParams = { 0x00, 0x7F, 0xC0, 0xF8, 0xE0 };
|
||||||
|
|
||||||
int exceptionCnt = 0;
|
|
||||||
logger.trace("BlueGiga BLE thread started");
|
logger.trace("BlueGiga BLE thread started");
|
||||||
int[] inputBuffer = new int[BLE_MAX_LENGTH];
|
int[] inputBuffer = new int[BLE_MAX_LENGTH];
|
||||||
int inputCount = 0;
|
int inputCount = 0;
|
||||||
|
@ -260,9 +261,8 @@ public class BlueGigaSerialHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputCount < 4) {
|
if (inputCount < 4) {
|
||||||
// The BGAPI protocol has no packet framing, and no error detection, so we do a few
|
// The BGAPI protocol has no packet framing and no error detection, so we do a few
|
||||||
// sanity checks on the header to try and allow resyncronisation should there be an
|
// sanity checks on the header to try and allow resynchronisation.
|
||||||
// error.
|
|
||||||
// Byte 0: Check technology type is bluetooth and high length is 0
|
// Byte 0: Check technology type is bluetooth and high length is 0
|
||||||
// Byte 1: Check length is less than 64 bytes
|
// Byte 1: Check length is less than 64 bytes
|
||||||
// Byte 2: Check class ID is less than 8
|
// Byte 2: Check class ID is less than 8
|
||||||
|
@ -278,21 +278,22 @@ public class BlueGigaSerialHandler {
|
||||||
} else if (inputCount == 4) {
|
} else if (inputCount == 4) {
|
||||||
// Process the header to get the length
|
// Process the header to get the length
|
||||||
inputLength = inputBuffer[1] + (inputBuffer[0] & 0x02 << 8) + 4;
|
inputLength = inputBuffer[1] + (inputBuffer[0] & 0x02 << 8) + 4;
|
||||||
if (inputLength > 64) {
|
if (inputLength > BLE_MAX_LENGTH) {
|
||||||
logger.debug("BLE length larger than 64 bytes ({})", inputLength);
|
logger.debug("Received illegal BLE packet, length larger than max {} bytes ({})",
|
||||||
|
BLE_MAX_LENGTH, inputLength);
|
||||||
if (inputStream.markSupported()) {
|
if (inputStream.markSupported()) {
|
||||||
inputStream.reset();
|
inputStream.reset();
|
||||||
}
|
}
|
||||||
inputCount = 0;
|
inputCount = 0;
|
||||||
|
inputLength = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
} else if (inputCount == inputLength) {
|
||||||
if (inputCount == inputLength) {
|
// End of packet reached - process
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("BLE RX: {}", printHex(inputBuffer, inputLength));
|
logger.trace("BLE RX: {}", printHex(inputBuffer, inputLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of packet reached - process
|
|
||||||
BlueGigaResponse responsePacket = BlueGigaResponsePackets.getPacket(inputBuffer);
|
BlueGigaResponse responsePacket = BlueGigaResponsePackets.getPacket(inputBuffer);
|
||||||
|
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
|
@ -300,24 +301,16 @@ public class BlueGigaSerialHandler {
|
||||||
}
|
}
|
||||||
if (responsePacket != null) {
|
if (responsePacket != null) {
|
||||||
notifyEventListeners(responsePacket);
|
notifyEventListeners(responsePacket);
|
||||||
|
} else {
|
||||||
|
logger.debug("Unknown packet received: {}", printHex(inputBuffer, inputLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
inputCount = 0;
|
inputCount = 0;
|
||||||
exceptionCnt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.debug("BlueGiga BLE IOException: ", e);
|
|
||||||
|
|
||||||
if (exceptionCnt++ > 10) {
|
|
||||||
logger.error("BlueGiga BLE exception count exceeded, closing handler");
|
|
||||||
close = true;
|
|
||||||
notifyEventListeners(e);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.debug("BlueGiga BLE Exception, closing handler", e);
|
logger.trace("BlueGiga BLE Exception: ", e);
|
||||||
close = true;
|
close = true;
|
||||||
notifyEventListeners(e);
|
notifyEventListeners(new BlueGigaException("BlueGiga BLE Exception, reason " + e.getMessage(), e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug("BlueGiga BLE exited.");
|
logger.debug("BlueGiga BLE exited.");
|
||||||
|
|
Loading…
Reference in New Issue