【问题标题】:Android BLE notifications for Glucose葡萄糖的 Android BLE 通知
【发布时间】:2014-07-28 07:06:34
【问题描述】:

我厌倦了使用 Android BLE SDK 与我的 Glucose 设备进行通信。 我需要 UUID 2a18 和 2a34 的 setCharacteristicNotification。我参考Android官方SDK如下:

http://developer.android.com/guide/topics/connectivity/bluetooth-le.html#notification

BluetoothGattCharacteristic charGM = 
mConnGatt.getService(UUID.fromString(BleUuid.SERVICE_GLUCOSE))
    .getCharacteristic(UUID.fromString(BleUuid.CHAR_GLUCOSE_MEASUREMENT_STRING));
mConnGatt.setCharacteristicNotification(charGM, enabled);
BluetoothGattDescriptor descGM = charGM.getDescriptor(UUID.fromString(BleUuid.CHAR_CLIENT_CHARACTERISTIC_CONFIG_STRING));
descGM.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mConnGatt.writeDescriptor(descGM);

但它甚至无法进入 onCharacteristicChanged 回调。

我的onCharacteristicChanged如下:

        public void onCharacteristicChanged(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic) {
        broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(getApplicationContext(),"onCharacteristicChanged",Toast.LENGTH_LONG).show();
                setProgressBarIndeterminateVisibility(false);
            };
        });
    }

如果我按如下方式设置电池电量通知,它就可以工作。

BluetoothGattCharacteristic charBarrery = 
    mConnGatt.getService(UUID.fromString(BleUuid.SERVICE_BATTERY))
        .getCharacteristic(UUID.fromString(BleUuid.CHAR_BATTERY_LEVEL_STRING));
mConnGatt.setCharacteristicNotification(charBarrery, enabled);
BluetoothGattDescriptor descBarrery = charBarrery.getDescriptor(UUID.fromString(BleUuid.CHAR_CLIENT_CHARACTERISTIC_CONFIG_STRING));
descBarrery.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mConnGatt.writeDescriptor(descBarrery);

我不知道电池和葡萄糖通知有什么不同。

如果有人知道我该怎么做,请帮助我。

补充:

当我使用电池服务时,我的logcat如下:

07-29 10:28:17.924: D/BluetoothGatt(947): setCharacteristicNotification() - uuid: 00002a19-0000-1000-8000-00805f9b34fb enable: true
07-29 10:28:17.924: D/BluetoothGatt(947): writeDescriptor() - uuid: 00002902-0000-1000-8000-00805f9b34fb
07-29 10:28:18.484: D/BluetoothGatt(947): onDescriptorWrite() - Device=B4:AB:2C:06:9E:F4 UUID=00002a19-0000-1000-8000-00805f9b34fb
07-29 10:28:18.604: D/BluetoothGatt(947): onNotify() - Device=B4:AB:2C:06:9E:F4 UUID=00002a19-0000-1000-8000-00805f9b34fb

但是当我使用 Glucose 时,我的 logcat 会丢失 onNotify(),如下所示:

07-29 10:31:23.729: D/BluetoothGatt(1763): setCharacteristicNotification() - uuid: 00002a18-0000-1000-8000-00805f9b34fb enable: true
07-29 10:31:23.729: D/BluetoothGatt(1763): writeDescriptor() - uuid: 00002902-0000-1000-8000-00805f9b34fb
07-29 10:31:24.324: D/BluetoothGatt(1763): onDescriptorWrite() - Device=B4:AB:2C:06:9E:F4 UUID=00002a18-0000-1000-8000-00805f9b34fb

我不知道为什么 logcat 会丢失 onNotify()...

附加(8/4):

感谢您的回复! 我尝试启用有关记录访问控制点特征的指示,但失败了.. 我的流程如下:

  1. 启用关于葡萄糖测量特征和葡萄糖测量上下文特征的通知 & 启用记录访问控制点特征的指示

        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        for (BluetoothGattService service : gatt.getServices()) {
            if ((service == null) || (service.getUuid() == null)) {
                continue;
            }
            if (BleUuid.SERVICE_GLUCOSE.equalsIgnoreCase(service
                    .getUuid().toString())) {
    
                BluetoothGattCharacteristic charGM = 
                        mConnGatt.getService(UUID.fromString(BleUuid.SERVICE_GLUCOSE))
                            .getCharacteristic(UUID.fromString(BleUuid.CHAR_GLUCOSE_MEASUREMENT_STRING));
                mConnGatt.setCharacteristicNotification(charGM, enabled);
                BluetoothGattDescriptor descGM = charGM.getDescriptor(UUID.fromString(BleUuid.CHAR_CLIENT_CHARACTERISTIC_CONFIG_STRING));
                descGM.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                mConnGatt.writeDescriptor(descGM);
    
                BluetoothGattCharacteristic charGMC = 
                    mConnGatt.getService(UUID.fromString(BleUuid.SERVICE_GLUCOSE))
                        .getCharacteristic(UUID.fromString(BleUuid.CHAR_GLUCOSE_MEASUREMENT_CONTEXT_STRING));
                mConnGatt.setCharacteristicNotification(charGMC, enabled);
                BluetoothGattDescriptor descGMC = charGMC.getDescriptor(UUID.fromString(BleUuid.CHAR_CLIENT_CHARACTERISTIC_CONFIG_STRING));
                descGMC.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                mConnGatt.writeDescriptor(descGMC);
    
                BluetoothGattCharacteristic charRACP = 
                    mConnGatt.getService(UUID.fromString(BleUuid.SERVICE_GLUCOSE))
                        .getCharacteristic(UUID.fromString(BleUuid.CHAR_RECORD_ACCESS_CONTROL_POINT_STRING));
                mConnGatt.setCharacteristicNotification(charRACP, enabled);
                BluetoothGattDescriptor descRACP = charRACP.getDescriptor(UUID.fromString(BleUuid.CHAR_CLIENT_CHARACTERISTIC_CONFIG_STRING));
                descRACP.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                mConnGatt.writeDescriptor(descRACP);
    
                BluetoothGattCharacteristic charBarrery = 
                        mConnGatt.getService(UUID.fromString(BleUuid.SERVICE_BATTERY))
                            .getCharacteristic(UUID.fromString(BleUuid.CHAR_BATTERY_LEVEL_STRING));
                mConnGatt.setCharacteristicNotification(charBarrery, enabled);
                BluetoothGattDescriptor descBarrery = charBarrery.getDescriptor(UUID.fromString(BleUuid.CHAR_CLIENT_CHARACTERISTIC_CONFIG_STRING));
                descBarrery.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                mConnGatt.writeDescriptor(descBarrery);
    
                runOnUiThread(new Runnable() {
                    public void run() {
                        btnUpdateData.setEnabled(true);
                    };
                });
            }
        }
    };
    
  2. 发送0x0101记录访问控制点

        case R.id.btnUpdateData:
        try{
            //***SEND 0x0101 TO RECORD ACCESS CONTROL POINT   
            BluetoothGattCharacteristic writeRACPchar = 
                    mConnGatt.getService(UUID.fromString(BleUuid.SERVICE_GLUCOSE))
                        .getCharacteristic(UUID.fromString(BleUuid.CHAR_RECORD_ACCESS_CONTROL_POINT_STRING));
            byte[] data = new byte[1];
            data[0] = (byte)0x0101;
            writeRACPchar.setValue(data);
            mConnGatt.writeCharacteristic(writeRACPchar);
        }catch(Exception e){
            e.printStackTrace();
        }
        break;
    
  3. 我的回调函数

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     BluetoothGattCharacteristic characteristic, 
                                     int status) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
    }
    
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic, int status) {
    };
    
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic) {
        broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
    }
    

&

    private void broadcastUpdate(final String action,
        final BluetoothGattCharacteristic characteristic) {
        final Intent intent = new Intent(action);
        if (BleUuid.CHAR_SERIAL_NUMBEAR_STRING
                .equalsIgnoreCase(characteristic.getUuid().toString())) {
            displayResult(characteristic.getStringValue(0));
        }else if(BleUuid.CHAR_MANUFACTURER_NAME_STRING
                .equalsIgnoreCase(characteristic.getUuid().toString())){
            displayResult(characteristic.getStringValue(0));
        } else if(BleUuid.CHAR_BATTERY_LEVEL_STRING
                .equalsIgnoreCase(characteristic.getUuid().toString())){
            final byte[] data = characteristic.getValue();
            String dataStr = "";
            dataStr = String.format("%02X", data[0]);
            int a = Integer.parseInt(dataStr, 16);
            String result = "battery level: " + Integer.toString(a)+ "%";
            displayResult(result);
        } else {
            // For all other profiles, writes the data formatted in HEX.
            final byte[] data = characteristic.getValue();
            if (data != null && data.length > 0) {
                final StringBuilder stringBuilder = new StringBuilder(data.length);
                for(byte byteChar : data)
                    stringBuilder.append(String.format("%02X ", byteChar));
                displayResult(stringBuilder.toString());
            }
        }
}

&

    private void displayResult(String result){
    adUpdateData.add(result);
    runOnUiThread(new Runnable() {
        public void run() {
            lvUpdateData.setAdapter(adUpdateData);
        };
    });
}

我正在尝试理解“GLS_SPEC”pdf... 我使用了 Nordic Semiconductor 的 Glucose Service 示例应用程序,它可以工作。 我尝试学习如何实现该功能。

我注意到 LogCat 上显示了一些类似“unregisterIRListener() 被调用”的日志,但我不确定是否与我的问题有关......

感谢阅读。

【问题讨论】:

  • 您使用哪种葡萄糖设备?

标签: android notifications bluetooth-lowenergy android-notifications


【解决方案1】:

葡萄糖和电池服务存在逻辑差异。当您通常启用电池电量通知时(取决于实施),设备会立即向您发送电池电量。这就是你在那里得到 onNotify 的原因。当然,在某些实现中,它仅在值更改或其他规则时通知您,但在您的情况下,它的行为看起来像这样。

葡萄糖服务的工作方式不同。在葡萄糖服务 (https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.glucose.xml) 中,您有 3 个强制性特征。让我们在这里跳过葡萄糖功能。 其中之一是葡萄糖测量,您可以在其中收到葡萄糖读数通知。您启用这些通知的实现是正确的,它将起作用。但是为了获得通知,您必须使用记录访问控制点特性来请求它们。它允许您获取所有葡萄糖读数,只有最新的,只有第一个,从设备中删除保存的读数等。例如,当您:

  1. 启用有关血糖测量特性的通知(就像您所做的那样)
  2. 启用记录访问控制点特征的指示
  3. 发送电子邮件0x0101 = 报告存储记录 |所有记录

您应该收到 N 条关于 Glucose Measurement char 的通知。接着是 RACP 字符的指示。值:0x06000101 =“报告存储记录”的响应 |成功。 如果没有读数保存在葡萄糖设备上,N 可以为 0。如果您正在使用 Nordic Semiconductor 的 Glucose Service 示例应用程序,您可以尝试按下按钮 0(?) 在板上生成新结果(最多 20 个)并再次请求。

阅读 GLS 文档:https://www.bluetooth.org/en-us/specification/adopted-specifications -> GLS -> PDF 了解有关葡萄糖服务和记录访问控制点格式的更多信息。

编辑

您写错了记录访问控制点值。这是工作代码:

case R.id.btnUpdateData:
    try{
        //***SEND 0x0101 TO RECORD ACCESS CONTROL POINT   
        BluetoothGattCharacteristic writeRACPchar = 
                mConnGatt.getService(UUID.fromString(BleUuid.SERVICE_GLUCOSE))
                    .getCharacteristic(UUID.fromString(BleUuid.CHAR_RECORD_ACCESS_CONTROL_POINT_STRING));
        byte[] data = new byte[2];
        data[0] = 0x01; // Report Stored records
        data[1] = 0x01; // All records
        writeRACPchar.setValue(data);

        // or:
        // byte[] data = new byte[2];
        // writeRACPchar.setValue(data);
        // writeRACPchar.setIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1, 0); // Report Stored records
        // writeRACPchar.setIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1, 1); // Read all (offset 1)
        mConnGatt.writeCharacteristic(writeRACPchar);
    }catch(Exception e){
        e.printStackTrace();
    }
    break;

你必须写 2 个字节,每个字节是 8 个但可以写成 2 位 HEX,f.e. 0xAB 读 0x01。值 0x0101 有 2 个字节,你可能没有

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2014-12-06
  • 2015-06-13
  • 1970-01-01
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多