Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added RSSI info and implementation for readRSSI() into Android aspect of plugin #221

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,12 +342,18 @@ Function `list` lists the paired Bluetooth devices. The success callback is cal
Example list passed to success callback. See [BluetoothDevice](http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getName\(\)) and [BluetoothClass#getDeviceClass](http://developer.android.com/reference/android/bluetooth/BluetoothClass.html#getDeviceClass\(\)).

[{
"class": 276,
"classMinor": 276,
"classMajor": 1276,
"rssi": -75,
"type": "Classic",
"id": "10:BF:48:CB:00:00",
"address": "10:BF:48:CB:00:00",
"name": "Nexus 7"
}, {
"class": 7936,
"classMinor": 7936,
"classMajor": 5276,
"rssi": -32,
"type": "BLE",
"id": "00:06:66:4D:00:00",
"address": "00:06:66:4D:00:00",
"name": "RN42"
Expand Down Expand Up @@ -546,17 +552,23 @@ Function `discoverUnpaired` discovers unpaired Bluetooth devices. The success ca
Example list passed to success callback.

[{
"class": 276,
"classMinor": 276,
"classMajor": 1276,
"rssi": -75,
"type": "Classic",
"id": "10:BF:48:CB:00:00",
"address": "10:BF:48:CB:00:00",
"name": "Nexus 7"
}, {
"class": 7936,
"classMinor": 7936,
"classMajor": 5276,
"rssi": -32,
"type": "BLE",
"id": "00:06:66:4D:00:00",
"address": "00:06:66:4D:00:00",
"name": "RN42"
}]

The discovery process takes a while to happen. You can register notify callback with [setDeviceDiscoveredListener](#setdevicediscoveredlistener).
You may also want to show a progress indicator while waiting for the discover proces to finish, and the sucess callback to be invoked.

Expand Down Expand Up @@ -592,12 +604,15 @@ There can be only one registered callback.
Example object passed to notify callback.

{
"class": 276,
"classMinor": 276,
"classMajor": 1276,
"rssi": -75,
"type": "Classic",
"id": "10:BF:48:CB:00:00",
"address": "10:BF:48:CB:00:00",
"name": "Nexus 7"
}

#### iOS & Windows Phone

See [discoverUnpaired](#discoverunpaired).
Expand Down
124 changes: 117 additions & 7 deletions src/android/com/megster/cordova/BluetoothSerial.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,16 @@ public class BluetoothSerial extends CordovaPlugin {
private static final String SET_NAME = "setName";
private static final String SET_DISCOVERABLE = "setDiscoverable";

// Add support for readRSSI
private static final String READ_RSSI = "readRSSI";

// callbacks
private CallbackContext connectCallback;
private CallbackContext dataAvailableCallback;
private CallbackContext rawDataAvailableCallback;
private CallbackContext enableBluetoothCallback;
private CallbackContext deviceDiscoveredCallback;

private BluetoothAdapter bluetoothAdapter;
private BluetoothSerialService bluetoothSerialService;

Expand All @@ -72,15 +75,32 @@ public class BluetoothSerial extends CordovaPlugin {
public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5;
public static final int MESSAGE_READ_RAW = 6;


public static final int MESSAGE_DEVICE_ADDRESS = 7;

// Device types
public static final int DEVICE_TYPE_UNKNOWN = 0;
public static final int DEVICE_TYPE_CLASSIC = 1;
public static final int DEVICE_TYPE_LE = 2;
public static final int DEVICE_TYPE_DUAL = 3;

// Key names received from the BluetoothChatService Handler
public static final String DEVICE_NAME = "device_name";
public static final String TOAST = "toast";

public static final String DEVICE_ADDRESS = "device_address";

StringBuffer buffer = new StringBuffer();
private String delimiter;
private static final int REQUEST_ENABLE_BLUETOOTH = 1;


// ???
//private static final int REQUEST_CONNECT_DEVICE = 1;
//private static final int REQUEST_ENABLE_BT = 2;

private String mConnectedName = null;
private String mConnectedAddress = null;

@Override
public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {

Expand Down Expand Up @@ -228,6 +248,11 @@ public boolean execute(String action, CordovaArgs args, CallbackContext callback
discoverIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, discoverableDuration);
cordova.getActivity().startActivity(discoverIntent);

} else if (action.equals(READ_RSSI)) {

boolean secure = true;
readRssi(args, secure, callbackContext);

} else {
validAction = false;

Expand All @@ -246,15 +271,15 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (enableBluetoothCallback != null) {
enableBluetoothCallback.success();
}
} else {
} else {
Log.d(TAG, "User did *NOT* enable Bluetooth");
if (enableBluetoothCallback != null) {
enableBluetoothCallback.error("User did not enable Bluetooth");
}
}

enableBluetoothCallback = null;
}
}
}

@Override
Expand Down Expand Up @@ -287,8 +312,9 @@ public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
try {
JSONObject o = deviceToJSON(device);
JSONObject o = deviceToJSON(device, rssi);
unpairedDevices.put(o);
if (ddc != null) {
PluginResult res = new PluginResult(PluginResult.Status.OK, o);
Expand All @@ -302,6 +328,7 @@ public void onReceive(Context context, Intent intent) {
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
callbackContext.success(unpairedDevices);
cordova.getActivity().unregisterReceiver(this);
bluetoothAdapter.cancelDiscovery();
}
}
};
Expand All @@ -313,17 +340,93 @@ public void onReceive(Context context, Intent intent) {
}

private JSONObject deviceToJSON(BluetoothDevice device) throws JSONException {
return deviceToJSON(device, (short)0);
}

private JSONObject deviceToJSON(BluetoothDevice device, short rssi) throws JSONException {
JSONObject json = new JSONObject();
String deviceType;
switch (device.getType())
{
case DEVICE_TYPE_CLASSIC: deviceType = "Classic";
break;
case DEVICE_TYPE_LE: deviceType = "BLE";
break;
case DEVICE_TYPE_DUAL: deviceType = "Dual";
break;
default: deviceType = "Unknown";
break;
}

json.put("name", device.getName());
json.put("address", device.getAddress());
json.put("id", device.getAddress());
json.put("type", deviceType);
if (device.getBluetoothClass() != null) {
json.put("class", device.getBluetoothClass().getDeviceClass());
json.put("classMajor", device.getBluetoothClass().getMajorDeviceClass());
json.put("classMinor", device.getBluetoothClass().getDeviceClass());
}
json.put("rssi", Integer.toString((int)rssi, 10));
return json;
}

private void readRssi(CordovaArgs args, boolean secure, final CallbackContext callbackContext) throws JSONException {
String macAddress = null;
BluetoothDevice device = null;

if (args.isNull(0)) {
if (mConnectedAddress != null) {
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice deviceBT : bondedDevices) {
if (mConnectedAddress.equals(deviceBT.getAddress())) {
macAddress = deviceBT.getAddress();
device = deviceBT;
}
}
} else
callbackContext.error("Read RSSI devices not connected");
} else {
macAddress = args.getString(0);
device = bluetoothAdapter.getRemoteDevice(macAddress);
}

final BroadcastReceiver connectReceiver = new BroadcastReceiver() {

private JSONArray rssiDevices = new JSONArray();

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
BluetoothDevice deviceBT = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Doesn't seem to work... always returns -32768 for RSSI
short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
try {
JSONObject o = deviceToJSON(deviceBT, rssi);
rssiDevices.put(o);
} catch (JSONException e) {
// This shouldn't happen, log and ignore
Log.e(TAG, "Problem converting device to JSON", e);
}
callbackContext.success(rssiDevices);
cordova.getActivity().unregisterReceiver(this);
}
}
};

Activity activity = cordova.getActivity();
activity.registerReceiver(connectReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));

if (device != null) {
connectCallback = callbackContext;
bluetoothSerialService.connect(device, secure);
} else {
callbackContext.error("Read RSSI could not connect to " + macAddress);
}
}

private void connect(CordovaArgs args, boolean secure, CallbackContext callbackContext) throws JSONException {

String macAddress = args.getString(0);
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(macAddress);

Expand Down Expand Up @@ -377,6 +480,8 @@ public void handleMessage(Message msg) {
break;
case BluetoothSerialService.STATE_NONE:
Log.i(TAG, "BluetoothSerialService.STATE_NONE");
mConnectedName = null;
mConnectedAddress = null;
break;
}
break;
Expand All @@ -387,6 +492,11 @@ public void handleMessage(Message msg) {
break;
case MESSAGE_DEVICE_NAME:
Log.i(TAG, msg.getData().getString(DEVICE_NAME));
mConnectedName = msg.getData().getString(DEVICE_NAME);
break;
case MESSAGE_DEVICE_ADDRESS:
Log.i(TAG, msg.getData().getString(DEVICE_ADDRESS));
mConnectedAddress = msg.getData().getString(DEVICE_ADDRESS);
break;
case MESSAGE_TOAST:
String message = msg.getData().getString(TOAST);
Expand Down
13 changes: 10 additions & 3 deletions src/android/com/megster/cordova/BluetoothSerialService.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class BluetoothSerialService {
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;

// Constants that indicate the current connection state
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_LISTEN = 1; // now listening for incoming connections
Expand All @@ -73,7 +73,7 @@ public BluetoothSerialService(Handler handler) {
private synchronized void setState(int state) {
if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
mState = state;

// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(BluetoothSerial.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
Expand All @@ -83,7 +83,7 @@ private synchronized void setState(int state) {
public synchronized int getState() {
return mState;
}

/**
* Start the chat service. Specifically start AcceptThread to begin a
* session in listening (server) mode. Called by the Activity onResume() */
Expand Down Expand Up @@ -168,6 +168,13 @@ public synchronized void connected(BluetoothSocket socket, BluetoothDevice devic
bundle.putString(BluetoothSerial.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);

// Send the MAC address of the connected device back to the UI Activity
Message msg2 = mHandler.obtainMessage(BluetoothSerial.MESSAGE_DEVICE_ADDRESS);
Bundle bundle2 = new Bundle();
bundle2.putString(BluetoothSerial.DEVICE_ADDRESS, device.getAddress());
msg2.setData(bundle2);
mHandler.sendMessage(msg2);

setState(STATE_CONNECTED);
}
Expand Down
9 changes: 7 additions & 2 deletions www/bluetoothSerial.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,13 @@ module.exports = {
},

// reads the RSSI of the *connected* peripherial
readRSSI: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "readRSSI", []);
//readRSSI: function (success, failure) {
// cordova.exec(success, failure, "BluetoothSerial", "readRSSI", []);
//},

// address is optional for Android but prefered... iOS reads *connected* device and doesn't need address
readRSSI: function (macAddress, success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "readRSSI", [macAddress]);
},

showBluetoothSettings: function (success, failure) {
Expand Down