AWTK 的低功耗蓝牙 (BLE) 插件开发笔记

AWTK 的低功耗蓝牙 (BLE) 插件开发笔记

BLE 插件的实现还是挺麻烦的,过年期间断断续续的写了 4 天。除了代码量本身不小外 (1500 行+500 行 java),主要还是对 BLE 开发不熟。看了一些资料,这里记个笔记,供新手参考:

发送数据

发送数据通过写 Characteristic 的值来实现,写 Characteristic 的过程分为两步:

  • 先设置 Value。
  • 调用 writeCharacteristic 发送数据。

之前没有调用 writeCharacteristic,数据怎么也发不出去,后来看文档才知道。

            String address = json.getString("address");
            String uuid = json.getString("uuid");
            String data = json.getString("data");
            String type = json.getString("type");

            BluetoothGatt conn = this.findConnectionByAddr(address);
            if (conn != null) {
                BluetoothGattCharacteristic c = findCharacteristic(conn.getServices(), uuid);
                if (c != null) {
                    if (type.equals("hex")) {
                        c.setValue(hexToByteArray(data));
                    } else {
                        c.setValue(data);
                    }
                    conn.writeCharacteristic(c);
                    PluginManager.writeSuccess(this.callerInfo, this.action);
                } else {
                    PluginManager.writeFailure(this.callerInfo, this.action, "not found BluetoothGattCharacteristic");
                }
            } else {
                PluginManager.writeFailure(this.callerInfo, this.action, "please connect device first");
            }
        } catch (JSONException e) {
            PluginManager.writeFailure(this.callerInfo, this.action, "bad parameters");
        }

接收数据

接收数据一般是监听 Characteristic 变化事件,而不是读取 Characteristic。需要重载 onCharacteristicChanged:

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            Log.i("AWTK", "onCharacteristicChanged: " + characteristic.getUuid().toString());
            byte[] bytes = characteristic.getValue();
            String data = new String(bytes, StandardCharsets.UTF_8);
            String hex = byteArrayToHex(bytes);

            if (notifyReceiver != null) {
                try {
                    JSONObject json = new JSONObject();
                    json.put("type", "onCharacteristicChanged")
                            .put("address", gatt.getDevice().getAddress())
                            .put("uuid", characteristic.getUuid().toString())
                            .put("hex", hex)
                            .put("data", data);
                    PluginManager.writeResult(notifyReceiver, json.toString());
                } catch (JSONException e) {
                    Log.d("AWTK", e.toString());
                }
            }
        }

但是我在用 HC-42 测试时,onCharacteristicChanged 函数怎么也不触发。在网上查了一下,说要调用 setCharacteristicNotification 函数,然而调用了 setCharacteristicNotification 之后还是没有效果。

后来使用 HC-Bluetooth 提供的 apk 测试,发现工作正常的。由于没有找到这个 apk 的源码,把它反编译出来研究了一下。才知道还要去设置 Descriptor 来开启通知:

反编译的源码如下:

    public void setNotification(final BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic bluetoothGattCharacteristic, boolean z) {
        if (bluetoothGatt == null || bluetoothGattCharacteristic == null) {
            log("gatt == null || characteristic == null");
            return;
        }
        boolean characteristicNotification = bluetoothGatt.setCharacteristicNotification(bluetoothGattCharacteristic, z);
        Log.e("TAG", "setNotification: " + characteristicNotification);
        if (characteristicNotification) {
            for (final BluetoothGattDescriptor next : bluetoothGattCharacteristic.getDescriptors()) {
                if ((bluetoothGattCharacteristic.getProperties() & 16) != 0) {
                    next.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    log("路线 1");
                } else if ((bluetoothGattCharacteristic.getProperties() & 32) != 0) {
                    next.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                    log("路线 2");
                } else {
                    log("没有走");
                }
                this.mTimeHandler.postDelayed(new Runnable() {
                    public void run() {
                        bluetoothGatt.writeDescriptor(next);
                        BluetoothLeService bluetoothLeService = BluetoothLeService.this;
                        bluetoothLeService.log("监听的特征是:" + next.getUuid().toString());
                    }
                }, 1000);
            }
        }
    }

于是我也加了类似的代码:

        public void enableCharacteristicNotify(final BluetoothGatt gatt, BluetoothGattCharacteristic c, boolean enable) {
            boolean result = gatt.setCharacteristicNotification(c, enable);
            Log.v("AWTK", "enable notify for " + c.getUuid());
            if (result) {
                int properties = c.getProperties();
                for (final BluetoothGattDescriptor d : c.getDescriptors()) {
                    if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
                        d.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    } else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
                        d.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                    } else {
                        Log.v("AWTK", "bad");
                    }

                    mTimeHandler.postDelayed(new Runnable() {
                        public void run() {
                            gatt.writeDescriptor(d);
                        }
                    }, 1000);
                }
            }
        }

测试了一下,HC-42 收发数据正常了,不过不太确定其它模块是否有效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值