[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:
pali 2021-02-15 19:08:14 +02:00 committed by GitHub
parent 928859ab86
commit 71dbf2ed1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 29 deletions

View File

@ -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;
} }
} }

View File

@ -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;

View File

@ -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.");