Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Commit

Permalink
added discovery configuration parameter and fixed JVM crash upon hand…
Browse files Browse the repository at this point in the history
…ler disposal

Signed-off-by: Kai Kreuzer <kai@openhab.org>
  • Loading branch information
kaikreuzer committed Feb 2, 2018
1 parent 7ddf6e1 commit e1a59b7
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
<context>serial-port</context>
<description>Serial Port</description>
</parameter>
<parameter name="discovery" type="boolean">
<label>Device Discovery</label>
<description>Whether this adapter actively participates in Bluetooth device discovery</description>
<advanced>true</advanced>
<default>true</default>
</parameter>
</config-description>
</bridge-type>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ public class BlueGigaAdapterConstants {
public static final String CONFIGURATION_PORT = "port";
public static final String PROPERTY_LINKLAYER = "linklayer";
public static final String PROPERTY_PROTOCOL = "protocol";
public static final String PROPERTY_DISCOVERY = "discovery";
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package org.eclipse.smarthome.binding.bluetooth.bluegiga.handler;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
Expand Down Expand Up @@ -134,6 +135,9 @@ public class BlueGigaBridgeHandler extends BaseBridgeHandler
// Our BT address
private BluetoothAddress address;

// internal flag for the discovery configuration
private boolean discoveryActive = true;

// Map of Bluetooth devices known to this bridge.
// This is all devices we have heard on the network - not just things bound to the bridge
private final Map<BluetoothAddress, BluetoothDevice> devices = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -164,81 +168,90 @@ public void handleCommand(ChannelUID channelUID, Command command) {

@Override
public void initialize() {
Object discovery = getConfig().get(BlueGigaAdapterConstants.PROPERTY_DISCOVERY);
if (discovery != null && discovery.toString().equalsIgnoreCase(Boolean.FALSE.toString())) {
discoveryActive = false;
logger.debug("Deactivated discovery participation.");
}

final String portId = (String) getConfig().get(BlueGigaAdapterConstants.CONFIGURATION_PORT);

if (portId == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Serial port must be configured!");
return;
}
openSerialPort(portId, 115200);
bgHandler = new BlueGigaSerialHandler(inputStream, outputStream);
// Create and send the reset command to the dongle
bgHandler.addEventListener(this);
bgHandler.addHandlerListener(this);

updateStatus(ThingStatus.UNKNOWN);

scheduler.submit(() -> {
// Stop any procedures that are running
bgStopProcedure();

// Close all transactions
BlueGigaCommand command; // = new BlueGigaResetCommand();
command = new BlueGigaGetConnectionsCommand();
BlueGigaGetConnectionsResponse connectionsResponse = (BlueGigaGetConnectionsResponse) bgHandler
.sendTransaction(command);
if (connectionsResponse != null) {
maxConnections = connectionsResponse.getMaxconn();
}

// Close all connections so we start from a known position
for (int connection = 0; connection < maxConnections; connection++) {
bgDisconnect(connection);
}

// Get our Bluetooth address
command = new BlueGigaAddressGetCommand();
BlueGigaAddressGetResponse addressResponse = (BlueGigaAddressGetResponse) bgHandler
.sendTransaction(command);
if (addressResponse != null) {
address = new BluetoothAddress(addressResponse.getAddress());
updateStatus(ThingStatus.ONLINE);
} else {
updateStatus(ThingStatus.OFFLINE);
}

command = new BlueGigaGetInfoCommand();
BlueGigaGetInfoResponse infoResponse = (BlueGigaGetInfoResponse) bgHandler.sendTransaction(command);

// Set mode to non-discoverable etc.
// Not doing this will cause connection failures later
bgSetMode();

// Start passive scan
bgStartScanning(false, passiveScanInterval, passiveScanWindow);

Map<String, String> properties = editProperties();
properties.put(BluetoothBindingConstants.PROPERTY_MAXCONNECTIONS, Integer.toString(maxConnections));
properties.put(Thing.PROPERTY_FIRMWARE_VERSION,
String.format("%d.%d", infoResponse.getMajor(), infoResponse.getMinor()));
properties.put(Thing.PROPERTY_HARDWARE_VERSION, Integer.toString(infoResponse.getHardware()));
properties.put(BlueGigaAdapterConstants.PROPERTY_PROTOCOL,
Integer.toString(infoResponse.getProtocolVersion()));
properties.put(BlueGigaAdapterConstants.PROPERTY_LINKLAYER, Integer.toString(infoResponse.getLlVersion()));
updateProperties(properties);
});
if (openSerialPort(portId, 115200)) {
bgHandler = new BlueGigaSerialHandler(inputStream, outputStream);
// Create and send the reset command to the dongle
bgHandler.addEventListener(this);
bgHandler.addHandlerListener(this);

updateStatus(ThingStatus.UNKNOWN);

scheduler.submit(() -> {
// Stop any procedures that are running
bgStopProcedure();

// Close all transactions
BlueGigaCommand command; // = new BlueGigaResetCommand();
command = new BlueGigaGetConnectionsCommand();
BlueGigaGetConnectionsResponse connectionsResponse = (BlueGigaGetConnectionsResponse) bgHandler
.sendTransaction(command);
if (connectionsResponse != null) {
maxConnections = connectionsResponse.getMaxconn();
}

// Close all connections so we start from a known position
for (int connection = 0; connection < maxConnections; connection++) {
bgDisconnect(connection);
}

// Get our Bluetooth address
command = new BlueGigaAddressGetCommand();
BlueGigaAddressGetResponse addressResponse = (BlueGigaAddressGetResponse) bgHandler
.sendTransaction(command);
if (addressResponse != null) {
address = new BluetoothAddress(addressResponse.getAddress());
updateStatus(ThingStatus.ONLINE);
} else {
updateStatus(ThingStatus.OFFLINE);
}

command = new BlueGigaGetInfoCommand();
BlueGigaGetInfoResponse infoResponse = (BlueGigaGetInfoResponse) bgHandler.sendTransaction(command);

// Set mode to non-discoverable etc.
// Not doing this will cause connection failures later
bgSetMode();

// Start passive scan
bgStartScanning(false, passiveScanInterval, passiveScanWindow);

Map<String, String> properties = editProperties();
properties.put(BluetoothBindingConstants.PROPERTY_MAXCONNECTIONS, Integer.toString(maxConnections));
properties.put(Thing.PROPERTY_FIRMWARE_VERSION,
String.format("%d.%d", infoResponse.getMajor(), infoResponse.getMinor()));
properties.put(Thing.PROPERTY_HARDWARE_VERSION, Integer.toString(infoResponse.getHardware()));
properties.put(BlueGigaAdapterConstants.PROPERTY_PROTOCOL,
Integer.toString(infoResponse.getProtocolVersion()));
properties.put(BlueGigaAdapterConstants.PROPERTY_LINKLAYER,
Integer.toString(infoResponse.getLlVersion()));
updateProperties(properties);
});
}
}

@Override
public void dispose() {
if (bgHandler != null) {
bgHandler.removeEventListener(this);
bgHandler.removeHandlerListener(this);
bgHandler.close();
}
closeSerialPort();
}

private void openSerialPort(final String serialPortName, int baudRate) {
private boolean openSerialPort(final String serialPortName, int baudRate) {
logger.debug("Connecting to serial port '{}'", serialPortName);
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName);
Expand All @@ -258,47 +271,47 @@ private void openSerialPort(final String serialPortName, int baudRate) {
logger.info("Connected to serial port '{}'.", serialPortName);
} catch (NoSuchPortException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Port does not exist");
return;
return false;
} catch (PortInUseException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
"Serial Error: Port in use");
return;
return false;
} catch (UnsupportedCommOperationException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
"Serial Error: Unsupported operation");
return;
return false;
}

try {
inputStream = serialPort.getInputStream();
inputStream = new BufferedInputStream(serialPort.getInputStream());
outputStream = serialPort.getOutputStream();
} catch (IOException e) {
logger.error("Error getting serial streams", e);
return false;
}

return;
return true;
}

private void closeSerialPort() {
try {
if (serialPort != null) {
serialPort.enableReceiveTimeout(1);

inputStream.close();
if (serialPort != null) {
try {
serialPort.disableReceiveTimeout();
serialPort.removeEventListener();
outputStream.flush();
outputStream.close();

inputStream.close();
} catch (Exception e) {
logger.error("Error closing serial port.", e);
} finally {
serialPort.close();

logger.debug("Closed serial port closed.", serialPort.getName());

logger.debug("Closed serial port {}.", serialPort.getName());
serialPort = null;
inputStream = null;
outputStream = null;
}
} catch (Exception e) {
logger.error("Error closing serial port.", e);
}

}

@SuppressWarnings({ "unused", "null" })
Expand Down Expand Up @@ -450,8 +463,10 @@ public boolean bgDisconnect(int connectionHandle) {
* Device discovered. This simply passes the discover information to the discovery service for processing.
*/
public void deviceDiscovered(BluetoothDevice device) {
for (BluetoothDiscoveryListener listener : discoveryListeners) {
listener.deviceDiscovered(device);
if (discoveryActive) {
for (BluetoothDiscoveryListener listener : discoveryListeners) {
listener.deviceDiscovered(device);
}
}
}

Expand Down

0 comments on commit e1a59b7

Please sign in to comment.