2017-03-07 59 views
0

您好,我在一個服務中運行RxAndroidBle。 我將其設置爲自動連接,因爲設備每5分鐘喚醒一次並嘗試將數據發送到配對設備。我還設置了通知來獲取數據。 它可以工作,但在每次斷開連接時,我都會收到通知錯誤和寫入錯誤。RxAndroidBle在寫入和通知特徵上的錯誤

03-07 12:37:03.600 31014-31014/com.lady.viktoria.lightdrip D/BluetoothGatt: close() 
03-07 12:37:03.600 31014-31014/com.lady.viktoria.lightdrip D/BluetoothGatt: unregisterApp() - mClientIf=6 
03-07 12:37:03.604 31014-31014/com.lady.viktoria.lightdrip D/BluetoothGatt: connect() - device: B4:99:4C:67:5E:67, auto: true 
03-07 12:37:03.604 31014-31014/com.lady.viktoria.lightdrip D/BluetoothGatt: registerApp() 
03-07 12:37:03.604 31014-31014/com.lady.viktoria.lightdrip D/BluetoothGatt: registerApp() - UUID=1a9155ae-aa9c-465e-aacd-3c535c3d32a8 
03-07 12:37:03.607 31014-31026/com.lady.viktoria.lightdrip D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6 
03-07 12:37:03.610 31014-31027/com.lady.viktoria.lightdrip D/BluetoothGatt: setCharacteristicNotification() - uuid: 0000ffe1-0000-1000-8000-00805f9b34fb enable: false 
03-07 12:37:03.610 31014-31014/com.lady.viktoria.lightdrip V/CgmBleService: Notifications error: BleGattException{macAddress=B4:99:4C:67:5E:67, status=8 (0x08 -> https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/android-5.1.0_r1/stack/include/gatt_api.h), bleGattOperationType=BleGattOperation{description='CONNECTION_STATE'}} 
03-07 12:37:03.612 31014-31014/com.lady.viktoria.lightdrip V/CgmBleService: Write error: BleGattException{macAddress=B4:99:4C:67:5E:67, status=8 (0x08 -> https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/android-5.1.0_r1/stack/include/gatt_api.h), bleGattOperationType=BleGattOperation{description='CONNECTION_STATE'}} 
03-07 12:41:41.296 31014-7238/com.lady.viktoria.lightdrip D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=B4:99:4C:67:5E:67 
03-07 12:41:41.304 31014-31093/com.lady.viktoria.lightdrip V/CgmBleService: Hey, connection has been established! 
03-07 12:41:41.314 31014-31014/com.lady.viktoria.lightdrip D/BluetoothGatt: discoverServices() - device: B4:99:4C:67:5E:67 
03-07 12:41:41.889 31014-7239/com.lady.viktoria.lightdrip D/BluetoothGatt: onSearchComplete() = Device=B4:99:4C:67:5E:67 Status=0 
03-07 12:41:41.900 31014-31093/com.lady.viktoria.lightdrip D/BluetoothGatt: setCharacteristicNotification() - uuid: 0000ffe1-0000-1000-8000-00805f9b34fb enable: true 
03-07 12:41:41.941 31014-31014/com.lady.viktoria.lightdrip V/CgmBleService: Notifications has been set up 
03-07 12:41:46.748 31014-31014/com.lady.viktoria.lightdrip V/CgmBleService: Change: 1500300000002E000000D63CC12B680000000000 
03-07 12:41:46.753 31014-31014/com.lady.viktoria.lightdrip I/CgmBleService: Received Data packet 
03-07 12:41:46.763 31014-31014/com.lady.viktoria.lightdrip D/GlucoseRecord: create: No calibration yet 
03-07 12:41:46.772 31014-31014/com.lady.viktoria.lightdrip I/GlucoseRecord: calculateAgeAdjustedRawValue: RAW VALUE ADJUSTMENT FROM:0.048 TO: 0.06792021355263159 
03-07 12:41:46.781 31014-31014/com.lady.viktoria.lightdrip V/GlucoseRecord: glucoseRecord json: {"id":128,"a":0.0,"ageAdjustedRawValue":0.06792021355263159,"b":0.0,"c":0.0,"calculatedValue":0.0,"calculatedValueSlope":0.0,"calibrationFlag":false,"calibration_id":0,"filteredData":0.046,"ra":0.0,"rawData":0.048,"rb":0.0,"rc":0.0,"sensor_id":2,"synced":false,"timeSinceSensorStarted":1.2766377E7,"timestamp":1.488886906748E12} 
03-07 12:41:46.782 31014-31014/com.lady.viktoria.lightdrip V/CgmBleService: Change: 01 
03-07 12:41:46.782 31014-31014/com.lady.viktoria.lightdrip D/CgmBleService: Sending Acknowledge Packet, to put wixel to sleep 
03-07 12:41:46.791 31014-31014/com.lady.viktoria.lightdrip V/CgmBleService: Write success 
03-07 12:42:01.144 31014-31027/com.lady.viktoria.lightdrip D/BluetoothGatt: onClientConnectionState() - status=8 clientIf=6 device=B4:99:4C:67:5E:67 
03-07 12:42:01.147 31014-31027/com.lady.viktoria.lightdrip V/CgmBleService: Connection Failure 
03-07 12:42:01.148 31014-31014/com.lady.viktoria.lightdrip D/BluetoothManager: getConnectionState() 
03-07 12:42:01.148 31014-31014/com.lady.viktoria.lightdrip D/BluetoothManager: getConnectedDevices 
03-07 12:42:01.153 31014-31014/com.lady.viktoria.lightdrip D/BluetoothGatt: close() 
03-07 12:42:01.153 31014-31014/com.lady.viktoria.lightdrip D/BluetoothGatt: unregisterApp() - mClientIf=6 
03-07 12:42:01.161 31014-31014/com.lady.viktoria.lightdrip D/BluetoothGatt: connect() - device: B4:99:4C:67:5E:67, auto: true 
public class CgmBleService extends Service { 
private final static String TAG = CgmBleService.class.getSimpleName(); 

public final static UUID UUID_BG_MEASUREMENT = UUID.fromString(GattAttributes.HM_RX_TX); 
public final static String ACTION_BLE_CONNECTED = "ACTION_BLE_CONNECTED"; 
public final static String ACTION_BLE_DISCONNECTED = "ACTION_BLE_DISCONNECTED"; 
public final static String ACTION_BLE_DATA_AVAILABLE = "ACTION_BLE_DATA_AVAILABLE"; 
public final static String EXTRA_BLE_DATA = "EXTRA_BLE_DATA"; 
public final static String BEACON_SNACKBAR = "BEACON_SNACKBAR"; 

private RxBleClient rxBleClient; 
private RxBleDevice bleDevice; 
private AppPreferences mTrayPreferences; 
private PublishSubject<Void> disconnectTriggerSubject = PublishSubject.create(); 
private Observable<RxBleConnection> connectionObservable; 
Handler handler; 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    super.onStartCommand(intent, flags, startId); 

    handler = new Handler(); 
    startJobScheduler(); 

    // get mac address from selected wixelbridge 
    mTrayPreferences = new AppPreferences(this); 
    final String BTDeviceAddress = mTrayPreferences.getString("BT_MAC_Address", "00:00:00:00:00:00"); 

    //init rxBleClient 
    rxBleClient = RxBleClient.create(this); 
    bleDevice = rxBleClient.getBleDevice(BTDeviceAddress); 
    // logging for RxBleClient 
    RxBleClient.setLogLevel(RxBleLog.INFO); 
    connectionObservable = prepareConnectionObservable(); 
    connect(); 

    return START_STICKY; 
} 

private Observable<RxBleConnection> prepareConnectionObservable() { 
    return bleDevice 
      .establishConnection(true) 
      .takeUntil(disconnectTriggerSubject) 
      //.compose(bindUntilEvent(PAUSE) 
      .doOnUnsubscribe(this::clearSubscription) 
      .compose(new ConnectionSharingAdapter()); 
} 

public void connect() { 
    if (isConnected()) { 
     triggerDisconnect(); 
     broadcastUpdate(ACTION_BLE_CONNECTED); 
    } else { 
     connectionObservable.subscribe(this::onConnectionReceived, this::onConnectionFailure); 
     broadcastUpdate(ACTION_BLE_DISCONNECTED); 
    } 
} 

public void writeCharacteristic(final ByteBuffer byteBuffer) { 
    byte[] bytearray = byteBuffer.array(); 
    if (isConnected()) { 
     connectionObservable 
       .flatMap(rxBleConnection -> rxBleConnection 
         .writeCharacteristic(UUID_BG_MEASUREMENT, bytearray)) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(bytes -> onWriteSuccess(), this::onWriteFailure); 
    } 
} 

public void writeNotificationCharacteristic() { 
    if (isConnected()) { 
     connectionObservable 
       .flatMap(rxBleConnection -> rxBleConnection.setupNotification(UUID_BG_MEASUREMENT)) 
       .doOnNext(notificationObservable -> runOnUiThread(this::notificationHasBeenSetUp)) 
       .flatMap(notificationObservable -> notificationObservable) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(this::onNotificationReceived, this::onNotificationSetupFailure); 
    } 
} 

private void runOnUiThread(Runnable runnable) { 
    handler.post(runnable); 
} 

private boolean isConnected() { 
    return bleDevice.getConnectionState() == RxBleConnection.RxBleConnectionState.CONNECTED; 
} 

private void clearSubscription() { 
    updateUI(); 
} 

private void triggerDisconnect() { 
    disconnectTriggerSubject.onNext(null); 
} 

private void updateUI() { 
    // connectButton.setText(isConnected() ? getString(R.string.disconnect) : getString(R.string.connect)); 
    // readButton.setEnabled(isConnected()); 
    // writeButton.setEnabled(isConnected()); 
    // notifyButton.setEnabled(isConnected()); 
} 



private void onConnectionFailure(Throwable throwable) { 
    //noinspection ConstantConditions 
    Log.v(TAG, "Connection Failure"); 
    connect(); 
} 

private void onConnectionReceived(RxBleConnection connection) { 
    //noinspection ConstantConditions 
    Log.v(TAG, "Hey, connection has been established!"); 
     writeNotificationCharacteristic(); 
} 

private void onWriteSuccess() { 
    //noinspection ConstantConditions 
    Log.v(TAG, "Write success"); 
} 

private void onWriteFailure(Throwable throwable) { 
    //noinspection ConstantConditions 
    Log.v(TAG, "Write error: " + throwable); 
} 

private void onNotificationReceived(byte[] bytes) { 
    //noinspection ConstantConditions 
    Log.v(TAG, "Change: " + ConvertHexString.bytesToHex(bytes)); 
    long timestamp = new Date().getTime(); 
    int packatlength = bytes[0]; 
    if (packatlength >= 2) { 
     if (CheckTransmitterID(bytes, bytes.length)) { 
      TransmitterRecord.create(bytes, bytes.length, timestamp); 
     } else { 
      broadcastUpdate(BEACON_SNACKBAR); 
     } 
    } else if (packatlength <= 1) { 
     writeAcknowledgePacket(); 
    } 
} 

private void onNotificationSetupFailure(Throwable throwable) { 
    //noinspection ConstantConditions 
    Log.v(TAG, "Notifications error: " + throwable); 
} 

private void notificationHasBeenSetUp() { 
    //noinspection ConstantConditions 
    Log.v(TAG, "Notifications has been set up"); 
} 

public boolean CheckTransmitterID(byte[] packet, int len) { 
    int DexSrc; 
    int TransmitterID; 
    ByteBuffer tmpBuffer; 
    final String TxId = mTrayPreferences.getString("Transmitter_Id", "00000"); 
    TransmitterID = ConvertTxID.convertSrc(TxId); 

    tmpBuffer = ByteBuffer.allocate(len); 
    tmpBuffer.order(ByteOrder.LITTLE_ENDIAN); 
    tmpBuffer.put(packet, 0, len); 

    if (packet[0] == 7) { 
     Log.i(TAG, "Received Beacon packet."); 
     broadcastUpdate(BEACON_SNACKBAR); 
     writeTxIdPacket(TransmitterID); 
     return false; 
    } else if (packet[0] >= 21 && packet[1] == 0) { 
     Log.i(TAG, "Received Data packet"); 
     DexSrc = tmpBuffer.getInt(12); 
     TransmitterID = ConvertTxID.convertSrc(TxId); 
     if (Integer.compare(DexSrc, TransmitterID) != 0) { 
      writeTxIdPacket(TransmitterID); 
      return false; 
     } else { 
      return true; 
     } 
    } 
    return false; 
} 

private void writeTxIdPacket(int TransmitterID) { 
    Log.v(TAG, "try to set transmitter ID"); 
    ByteBuffer txidMessage = ByteBuffer.allocate(6); 
    txidMessage.order(ByteOrder.LITTLE_ENDIAN); 
    txidMessage.put(0, (byte) 0x06); 
    txidMessage.put(1, (byte) 0x01); 
    txidMessage.putInt(2, TransmitterID); 
    writeCharacteristic(txidMessage); 
} 

private void writeAcknowledgePacket() { 
    Log.d(TAG, "Sending Acknowledge Packet, to put wixel to sleep"); 
    ByteBuffer ackMessage = ByteBuffer.allocate(2); 
    ackMessage.put(0, (byte) 0x02); 
    ackMessage.put(1, (byte) 0xF0); 
    writeCharacteristic(ackMessage); 
} 

private void broadcastUpdate(final String action) { 
    final Intent intent = new Intent(action); 
    sendBroadcast(intent); 
} 

public void startJobScheduler() { 
    final long REFRESH_INTERVAL = 15 * 60 * 1000; 
    ComponentName serviceComponent = new ComponentName(this, SchedulerJobService.class); 
    JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent); 
    builder.setRequiresDeviceIdle(false); 
    builder.setRequiresCharging(false); 
    builder.setPeriodic(REFRESH_INTERVAL); 
    //builder.setPersisted(true); 
    JobScheduler jobScheduler = (JobScheduler) this.getSystemService(Context.JOB_SCHEDULER_SERVICE); 
    int result = jobScheduler.schedule(builder.build()); 
    if (result == JobScheduler.RESULT_SUCCESS) Log.d(TAG, "Job scheduled successfully!"); 
} 

public void stopJobScheduler() { 
    JobScheduler jobScheduler = (JobScheduler) this.getSystemService(Context.JOB_SCHEDULER_SERVICE); 
    jobScheduler.cancel(0); 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    Intent broadcastIntent = new Intent("com.lady.viktoria.lightdrip.services.RestartCgmBleService"); 
    sendBroadcast(broadcastIntent); 
    stopJobScheduler(); 
} 

@Nullable 
@Override 
public IBinder onBind(Intent intent) { 
    return null; 
}} 

回答

0

感謝@s_noopy ,所以我必須做一些事情是這樣的:

Subscription writeNotificationSubscription; 
Subscription writeCharacteristicSubscription; 

public void writeCharacteristic(final ByteBuffer byteBuffer) { 
     byte[] bytearray = byteBuffer.array(); 
     if (isConnected()) { 
      writeCharacteristicSubscription = connectionObservable 
        .flatMap(rxBleConnection -> rxBleConnection 
          .writeCharacteristic(UUID_BG_MEASUREMENT, bytearray)) 
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(bytes -> onWriteSuccess(), this::onWriteFailure); 
     } 
    } 

private void onConnectionFailure(Throwable throwable) { 
     //noinspection ConstantConditions 
     Log.v(TAG, "Connection Failure"); 
     writeCharacteristicSubscription.unsubscribe(); 
     writeNotificationSubscription.unsubscribe(); 
     connect(); 
    } 
+0

好像現在正在工作:-)只有在服務啓動時首次連接時出現此錯誤。 – LadyViktoria

0

這可能是用戶仍然訂閱當一個獨立的斷開事件發生有關RxBleConnection對象一些觀測。由於圖書館通常沒有單獨的訂閱流程 - 與您的情況完全相同 - 它需要將有關斷開連接的信息發送給所有訂閱者。這就是爲什麼你兩次得到相同的錯誤。

+0

沒有它不是相同的錯誤。有2個不同的錯誤。 一個是設置特性和寫入特性。 – LadyViktoria

+0

看起來您在每個用戶身上都看到了完全相同的錯誤,這些錯誤在您的情況下編寫和通知了相同的連接。當連接斷開時 - 都獲得了這些信息。你能解釋一下你的問題還是重新措辭? –

+0

問題是如果這是正常的,而不是我的代碼問題。 我的理解是,我訂閱了兩個事件(成功和失敗)。連接關閉後,將啓動失敗事件。 – LadyViktoria