Skip to content

Commit

Permalink
feat(android, ios): add readRssi method to read RSSI value of a conne…
Browse files Browse the repository at this point in the history
…cted device
  • Loading branch information
pwespi committed Aug 27, 2021
1 parent 6e8e264 commit 4b3fc05
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 6 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Below is an index of all the methods available.
- [`createBond(...)`](#createbond)
- [`isBonded(...)`](#isbonded)
- [`disconnect(...)`](#disconnect)
- [`readRssi(...)`](#readrssi)
- [`read(...)`](#read)
- [`write(...)`](#write)
- [`writeWithoutResponse(...)`](#writewithoutresponse)
Expand Down Expand Up @@ -465,6 +466,22 @@ Disconnect from a peripheral BLE device. For an example, see [usage](#usage).

---

### readRssi(...)

```typescript
readRssi(deviceId: string) => Promise<number>
```

Read the RSSI value of a connected device.

| Param | Type | Description |
| -------------- | ------------------- | -------------------------------------------------------------------------------------------------------------- |
| **`deviceId`** | <code>string</code> | The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |

**Returns:** <code>Promise&lt;number&gt;</code>

---

### read(...)

```typescript
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,22 @@ class BluetoothLe : Plugin() {
}
}

@PluginMethod
fun readRssi(call: PluginCall) {
val device = getDevice(call) ?: return
device.readRssi { response ->
run {
if (response.success) {
val ret = JSObject()
ret.put("value", response.value)
call.resolve(ret)
} else {
call.reject(response.value)
}
}
}
}

@PluginMethod
fun read(call: PluginCall) {
val device = getDevice(call) ?: return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ class Device(
resolve("connect", "Connected.")
}

override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
super.onReadRemoteRssi(gatt, rssi, status)
val key = "readRssi"
if (status == BluetoothGatt.GATT_SUCCESS) {
resolve(key, rssi.toString())
} else {
reject(key, "Reading RSSI failed.")
}
}

override fun onCharacteristicRead(
gatt: BluetoothGatt,
characteristic: BluetoothGattCharacteristic,
Expand Down Expand Up @@ -264,6 +274,17 @@ class Device(
setTimeout(key, "Disconnection timeout.")
}

fun readRssi(callback: (CallbackResponse) -> Unit) {
val key = "readRssi"
callbackMap[key] = callback
val result = bluetoothGatt?.readRemoteRssi()
if (result != true) {
reject(key, "Reading RSSI failed.")
return
}
setTimeout(key, "Reading RSSI timeout.")
}

fun read(serviceUUID: UUID, characteristicUUID: UUID, callback: (CallbackResponse) -> Unit) {
val key = "read|$serviceUUID|$characteristicUUID"
callbackMap[key] = callback
Expand Down
17 changes: 17 additions & 0 deletions ios/Plugin/Device.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,23 @@ class Device: NSObject, CBPeripheralDelegate {
}
}

func readRssi(_ callback: @escaping Callback) {
let key = "readRssi"
self.callbackMap[key] = callback
print("Reading RSSI value")
self.peripheral.readRSSI()
self.setTimeout(key, "Reading RSSI timeout.")
}

func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
let key = "readRssi"
if error != nil {
self.reject(key, error!.localizedDescription)
return
}
self.resolve(key, RSSI.stringValue)
}

private func getCharacteristic(_ serviceUUID: CBUUID, _ characteristicUUID: CBUUID) -> CBCharacteristic? {
for service in peripheral.services ?? [] {
if service.uuid == serviceUUID {
Expand Down
1 change: 1 addition & 0 deletions ios/Plugin/Plugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
CAP_PLUGIN_METHOD(createBond, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(isBonded, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(disconnect, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(readRssi, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(read, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(write, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(writeWithoutResponse, CAPPluginReturnPromise);
Expand Down
14 changes: 14 additions & 0 deletions ios/Plugin/Plugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,20 @@ public class BluetoothLe: CAPPlugin {
})
}

@objc func readRssi(_ call: CAPPluginCall) {
guard self.getDeviceManager(call) != nil else { return }
guard let device = self.getDevice(call) else { return }
device.readRssi({(success, value) -> Void in
if success {
call.resolve([
"value": value
])
} else {
call.reject(value)
}
})
}

@objc func read(_ call: CAPPluginCall) {
guard self.getDeviceManager(call) != nil else { return }
guard let device = self.getDevice(call) else { return }
Expand Down
6 changes: 2 additions & 4 deletions ios/PluginTests/ConversionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,16 @@ class ConversionTests: XCTestCase {
XCTAssertEqual(cbuuidToString(CBUUID(string: "180D")), "0000180d-0000-1000-8000-00805f9b34fb")
XCTAssertEqual(cbuuidToString(CBUUID(string: "fb005c80-02e7-f387-1cad-8acd2d8df0c8")), "fb005c80-02e7-f387-1cad-8acd2d8df0c8")
}

func testCbuuidToStringUppercase() throws {
XCTAssertEqual(cbuuidToStringUppercase(CBUUID(string: "180D")), "0000180D-0000-1000-8000-00805F9B34FB")
XCTAssertEqual(cbuuidToStringUppercase(CBUUID(string: "fb005c80-02e7-f387-1cad-8acd2d8df0c8")), "FB005C80-02E7-F387-1CAD-8ACD2D8DF0C8")
}

func testOptionalStringConversion() throws {
let str: String? = "180D"
XCTAssertEqual("\(str)", "Optional(\"180D\")")
XCTAssertEqual("\(str!)", "180D")
}



}
14 changes: 14 additions & 0 deletions src/bleClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ export interface BleClientInterface {
*/
disconnect(deviceId: string): Promise<void>;

/**
* Read the RSSI value of a connected device.
* @param deviceId The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan))
*/
readRssi(deviceId: string): Promise<number>;

/**
* Read the value of a characteristic. For an example, see [usage](#usage).
* @param deviceId The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan))
Expand Down Expand Up @@ -307,6 +313,14 @@ class BleClientClass implements BleClientInterface {
});
}

async readRssi(deviceId: string): Promise<number> {
const value = await this.queue(async () => {
const result = await BluetoothLe.readRssi({ deviceId });
return parseFloat(result.value);
});
return value;
}

async read(deviceId: string, service: string, characteristic: string): Promise<DataView> {
service = validateUUID(service);
characteristic = validateUUID(characteristic);
Expand Down
5 changes: 5 additions & 0 deletions src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ export interface GetDevicesResult {
devices: BleDevice[];
}

export interface ReadRssiResult {
value: string;
}

export interface ReadResult {
/**
* android, ios: string
Expand Down Expand Up @@ -184,6 +188,7 @@ export interface BluetoothLePlugin {
createBond(options: DeviceIdOptions): Promise<void>;
isBonded(options: DeviceIdOptions): Promise<BooleanResult>;
disconnect(options: DeviceIdOptions): Promise<void>;
readRssi(options: DeviceIdOptions): Promise<ReadRssiResult>;
read(options: ReadOptions): Promise<ReadResult>;
write(options: WriteOptions): Promise<void>;
writeWithoutResponse(options: WriteOptions): Promise<void>;
Expand Down
9 changes: 7 additions & 2 deletions src/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
GetDevicesResult,
ReadOptions,
ReadResult,
ReadRssiResult,
RequestBleDeviceOptions,
ScanResultInternal,
WriteOptions,
Expand Down Expand Up @@ -158,11 +159,11 @@ export class BluetoothLeWeb extends WebPlugin implements BluetoothLePlugin {
BluetoothLe.notifyListeners(key, null);
}

async createBond(): Promise<void> {
async createBond(_options: DeviceIdOptions): Promise<void> {
throw new Error('Unavailable');
}

async isBonded(): Promise<BooleanResult> {
async isBonded(_options: DeviceIdOptions): Promise<BooleanResult> {
throw new Error('Unavailable');
}

Expand All @@ -175,6 +176,10 @@ export class BluetoothLeWeb extends WebPlugin implements BluetoothLePlugin {
return service?.getCharacteristic(options?.characteristic);
}

async readRssi(_options: DeviceIdOptions): Promise<ReadRssiResult> {
throw new Error('readRssi is not available on web');
}

async read(options: ReadOptions): Promise<ReadResult> {
const characteristic = await this.getCharacteristic(options);
const value = await characteristic?.readValue();
Expand Down

0 comments on commit 4b3fc05

Please sign in to comment.