我正在构建一个对蓝牙低功耗有特定要求的Android应用程序.
我需要写一个只写特性并在单独的通知特性上接收响应,我需要在很多很多活动中完成它.是否有Rx方式在第一个特征上发送请求,等待第二个请求的答案,然后继续另一个请求?
另外,为了分享我的RxAndroidBle实例,我想做一些BleManager Singleton,我会公开Observables,所以我可以在我的Presenter中轻松订阅它们.我只是想避免为每个活动复制连接逻辑并且(理想情况下)具有持久连接.这样我只能公开connectionObservable并订阅它,所以我可以轻松发送Write Requests并获取Notifications,但我相信有更好的方法可以做到.
这就是我现在所拥有的:
@Singleton
public class BleManager {
private PublishSubject<Void> disconnectTriggerSubject = PublishSubject.create();
private Observable<RxBleConnection> connectionObservable;
private boolean isConnected;
private final UUID CTRL_FROM_BRIDGE_UUID = UUID.fromString("someUUID");
private final UUID BLE_WRITE_CHARACTERISTIC_UUID = UUID.fromString("someOtherUUID");
private final RxBleClient bleClient;
private String mMacAddress;
private final Context context;
private RxBleDevice bleDevice;
@Inject
public BleManager(Context context, RxBleClient client) {
Timber.d("Constructing BleManager and injecting members");
this.context = context;
this.bleClient = client;
}
public void setMacAddress(String mMacAddress) {
this.mMacAddress = mMacAddress;
// Set the associated device …Run Code Online (Sandbox Code Playgroud) 我正在使用该RxAndroidBle库开发一个应用程序,该库大约每30秒定期执行BLE扫描,每分钟左右执行一些BLE操作。几个小时后(通常在5到24小时之间),扫描将停止工作。每次应该开始扫描时,我都会得到:
09-05 09:08:37.160 8160-8160/myapp D/BluetoothAdapter: startLeScan(): null
09-05 09:08:37.165 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.165 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.165 8160-8160/myapp D/BluetoothLeScanner: Start Scan
09-05 09:08:37.165 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.165 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.170 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.170 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.210 8160-12850/myapp D/BluetoothLeScanner: onClientRegistered() - status=133 clientIf=0
09-05 09:08:37.210 8160-12850/myapp D/BluetoothLeScanner: Registration failed, unregister clientIf = 0
09-05 09:08:37.215 8160-8160/myapp D/BluetoothLeScanner: Scan failed, reason app registration failed for UUID = 4c321920-a2b7-449a-bc24-ea4361f7a255
09-05 09:08:44.150 8160-8160/myapp …Run Code Online (Sandbox Code Playgroud) android bluetooth bluetooth-lowenergy android-bluetooth rxandroidble
BleGattException - 在第一次读写操作期间发生,有时它读取和写入正确但在重新连接ble设备后得到此异常...
if (bleManager.getMacAddress() != null && checkIsSameMac(peripheralModel.address) && bleManager.getConnectionSubscription() != null) {
bleManager.getConnectionSubscription().flatMap(RxBleConnection::discoverServices)
.observeOn(AndroidSchedulers.mainThread())
.first() // Disconnect automatically after discovery
.subscribe(swapScanResult -> {
Log.e("write and read", "discover success");
firstWriteCharacteristic(peripheralModel);
}, this::onConnectionFailure);
Run Code Online (Sandbox Code Playgroud) 我正在创建一个简单的应用程序,用于使用RxAndroidBle库与蓝牙设备进行连接(干得好!)。我有时遇到的情况是,当我连接到设备时,收到状态为133的Gatt错误。我知道它可能会发生,所以我想做的就是在发生该错误时重试所有内容。没问题,我可以使用retryWhen()运算符轻松地做到这一点,但是我还有另一个要求-如果连接失败,流必须在30秒后终止。我曾经timeout()这样做,但是问题是当我重试时,计时器再次启动。
因此,问题是如何将timeout()运算符与retryWhen()结合使用,以便我可以重试某些特定错误,但保持计数器继续运行。
我对合并可观察变量有一些想法,或者有一些单独的可观察变量,它们将在超时期限后检查连接状态,但是我想知道是否可以在单个可观察变量中进行此操作。
到目前为止,我的代码如下所示:
public Observable<ConnectingViewState> connectToDevice(String macAddress) {
final RxBleDevice rxBleDevice = rxBleClient.getBleDevice(macAddress);
return rxBleDevice.establishConnection(false)
.subscribeOn(Schedulers.io())
.map(rxBleConnection -> new ConnectingViewState.ConnectedViewState(rxBleConnection))
.cast(ConnectingViewState.class)
.timeout(40, TimeUnit.SECONDS)
.startWith(new ConnectingViewState.ConnectingInProgressViewState())
.retryWhen(errors -> errors.flatMap(error -> {
if (isDefaultGattError(error)) {
return Observable.just(new Object());
} else {
return Observable.error(error);
}
}
))
.onErrorReturn(throwable -> new ConnectingViewState.ErrorState(throwable));
}
Run Code Online (Sandbox Code Playgroud) 一部 Android 手机 (N5X 6.0.1) 正在运行 BLE 服务器,另一部 (N5X O) 正在订阅。可以启用特征通知,但是,在写入描述符部分,我始终得到 133。
Server.java
private void createServer() {
bluetoothGattServer = bluetoothManager.openGattServer(this, serverCallback);
BluetoothGattService service = new BluetoothGattService(Constants.SERVICE,
BluetoothGattService.SERVICE_TYPE_PRIMARY);
characteristic =
new BluetoothGattCharacteristic(Constants.CHARACTERISTIC,
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);
// public static UUID DESCRIPTOR = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
characteristic.addDescriptor(new BluetoothGattDescriptor(Constants.DESCRIPTOR,
BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE));
characteristic.setWriteType(
BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
service.addCharacteristic(characteristic);
bluetoothGattServer.addService(service);
}
private BluetoothGattServerCallback serverCallback = new BluetoothGattServerCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
Log.d(TAG, "onConnectionStateChange " + device.getName() + " " …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用在 Android 手机和使用 Android Things 的 Raspberry Pi 上运行的 rxBleAndroid 与 BLE 数据记录器/传感器进行通信。
但是,我目前遇到了一个问题,我的应用程序从未收到最多大约 5 个通知。
我已经验证 BLE 设备实际上已成功发送所有预期的通知。我已经通过 nRF Connect 应用程序做到了这一点,一切都按预期进行。
当我通过 nRF Connect 应用程序执行此操作时,这些是我采取的步骤:
通过 RxAndroidBle 执行此操作时,我怀疑可能是 .subscribe() 设置得不够快。
有没有办法做setupNotification(),然后编写特征来告诉设备开始发送通知?
这是我当前的代码:
rxBleClient = RxBleClient.create(this);
RxBleDevice device = rxBleClient.getBleDevice(mac_address);
device.establishConnection(false)
.flatMap(rxBleConnection -> rxBleConnection.writeCharacteristic(pword_uuid, pword)
.flatMap(ignored1 -> rxBleConnection.writeCharacteristic(mode_uuid, mode))
.flatMap(ignored2 -> rxBleConnection.setupNotification(log_uuid))
)
.flatMap(notificationObservable -> notificationObservable)
.subscribe(
bytes -> {
System.out.println(">>> data from device " + bytesToHex(bytes));
},
throwable -> {
System.out.println("error");
System.out.println(throwable);
});
Run Code Online (Sandbox Code Playgroud) 我正在尝试读/写这些特征:
现在,我正在尝试阅读AA01*
我正在使用这个库来做到这一点.
这是我的代码:
private void connectToSensorTag(RxBleDevice rxBleDevice) {
rxBleDevice.establishConnection(getApplicationContext(), false)
.doOnError(new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
int i = 0;
}
})
.flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(UUID.fromString("AA01*")))
.subscribe(new Subscriber<byte[]>() {
@Override
public void onCompleted() {
int i = 0;
}
@Override
public void onError(Throwable e) {
int i = 0;
}
@Override
public void onNext(byte[] bytes) {
int i = 0;
}
});
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
java.lang.IllegalArgumentException:无效的UUID:AA01*
我也尝试过这个类似问题的解决方案,但没有任何效果.同样的错误.
我需要ble在未连接到我的设备时永久扫描广告以找到它并知道何时连接到它(特定产品)。此扫描在前台服务中实现以匹配 8.0 先决条件。
为了节省一些电池,我想定期扫描(同时尊重 Android 7 的启动量/时间限制)。我看到 2 个不同的实现:
我正在使用RxAndroidBle库来扫描设备,然后连接到一个特定的设备并读取4 GATT特征。
我可以通过以下代码读取一个特性(电池电量):
scanSubscription = rxBleClient.scanBleDevices(
new ScanSettings.Builder()
.build()
)
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(
scanResult -> {
if(scanResult.getBleDevice().getName() != null){
if(scanResult.getBleDevice().getName().equals("NODE 1")){
Log.e("BLE SCAN", "SUCCESS");
Log.e("BLE SCAN", scanResult.getBleDevice().getName());
Log.e("BLE SCAN", scanResult.getBleDevice().getMacAddress());
scanSubscription.unsubscribe();
RxBleDevice device = scanResult.getBleDevice();
subscription = device.establishConnection(false) // <-- autoConnect flag
.flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb")))
.subscribe(
characteristicValue -> {
Log.e("Characteristic", characteristicValue[0]+"");
},
throwable -> {
Log.e("Error", throwable.getMessage());
}
);
}
}
}
)
.subscribe();
Run Code Online (Sandbox Code Playgroud)
我可以使用来阅读两个:
.flatMap(rxBleConnection -> Observable.combineLatest( // use the same connection and combine latest emissions
rxBleConnection.readCharacteristic(aUUID),
rxBleConnection.readCharacteristic(bUUID),
Pair::new
)) …Run Code Online (Sandbox Code Playgroud)