开发低功耗蓝牙4.0血压计连接与收发数据

来源:互联网 发布:鸟哥linux基础篇 pdf 编辑:程序博客网 时间:2024/05/01 10:04

最近在开发鱼跃YE680A蓝牙血压计,获取测量到的血压和心率数据,之前也做有一个爱奥乐蓝牙血压计的,连接流程是一样的,在收发数据时有一些区别,下面做一些笔记:

一、整体的可定义三个类,一个Bluetooth服务的,用于连接,一个包含各类UUID的,用于收发数据,最后一个封装工具类,给调用者调用。
1. 先说连接吧,判断是不是支持蓝牙功能,是否打开蓝牙和请求打开蓝牙涉及到的,代码详细可能没贴出来了,网上一搜大把的。

    private BluetoothAdapter mBluetoothAdapter;    private BluetoothLeScanner mBluetoothLeScanner;    private boolean isScanning; // 是否正在搜索    private void initBluetooth() {        BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);        mBluetoothAdapter = bluetoothManager.getAdapter();        if(mBluetoothAdapter == null) {            app.showToast(R.string.msg_bluetooth_no_support);            return;        } else {            if(!mBluetoothAdapter.isEnabled()) {                requestOpenBluetooth(); // 请求打开蓝牙            }            mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();        }    }    /**     * 开始搜索设备     * @param scan     */    public void scanLeDevice(boolean scan) {        if(mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {            requestOpenBluetooth(); // 请求打开蓝牙            return;        } else if(mBluetoothAdapter == null || mBluetoothLeScanner == null) {            MyLg.e("scanLeDevice", "mBluetoothLeScanner == null");            return;        }        if(scan) {            if(!isScanning) {                mBluetoothLeScanner.startScan(mScanCallback); // 开始搜索设备            }            isScanning = true;        } else {            mBluetoothLeScanner.stopScan(mScanCallback);            isScanning = false;        }    }

下面是扫描设备时的回调:

private ScanCallback mScanCallback = new ScanCallback() {        @Override        public void onBatchScanResults(List<ScanResult> results) {            super.onBatchScanResults(results);        }        @Override        public void onScanFailed(int errorCode) {            super.onScanFailed(errorCode);            MyLg.e("onScanFailed", "onScanFailed");        }        @Override        public void onScanResult(int callbackType, ScanResult result) {            super.onScanResult(callbackType, result);            String deviceName = result.getDevice().getName(); // 搜索到的设备名称            if(!TextUtils.isEmpty(deviceName)) {                if(deviceName.equals(DEVICE_NAME1)) { // 连接爱奥乐蓝牙血压计                    mDeviceAddress = result.getDevice().getAddress(); // 蓝牙血压计地址                    boolean isBind = bindService(); // 连接绑定服务                    MyLg.d("onScanResult", "isBind=" + isBind);                    scanLeDevice(false); // 停止扫描                } else if(deviceName.equals(DEVICE_NAME2)) { // 连接鱼跃蓝牙血压计                    mDeviceAddress = result.getDevice().getAddress(); // 蓝牙血压计地址                    boolean isBind = bindService(); // 连接绑定服务                    MyLg.d("onScanResult", "isBind=" + isBind);                    scanLeDevice(false); // 停止扫描                }            }        }    };    /**     * 开启后台服务,需要在获取到设备地址后才可连接     */    private boolean bindService() {        Intent serIntent = new Intent(mContext, BluetoothLeService.class);        isBindService = mContext.bindService(serIntent, mServiceConnection, Context.BIND_AUTO_CREATE);        return isBindService;    }

上面连接绑定服务时就用到了BluetoothLeService这个类,主要是连接,贴出代码。

private final ServiceConnection mServiceConnection = new ServiceConnection() {        // 服务绑定成功就会回调        @Override        public void onServiceConnected(ComponentName componentName,                                       IBinder service) {            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();            if (!mBluetoothLeService.initialize()) {                MyLg.e("onServiceConnected", "Unable to initialize Bluetooth");            }            // 传入设备地址,这里就开始连接            if (mBluetoothLeService.connect(mDeviceAddress)) {                MyLg.e("onServiceConnected", "mDeviceAddress=" + mDeviceAddress);                mBluetoothGatt = mBluetoothLeService.getGatt();            }        }        @Override        public void onServiceDisconnected(ComponentName componentName) {            MyLg.e("onServiceDisconnected", "componentName=" + componentName);            mBluetoothLeService = null;        }    };/** * 连接操作 */public boolean connect(final String address) {        if (mBluetoothAdapter == null || address == null) {            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");            return false;        }        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);        if (device == null) {            Log.w(TAG, "Device not found.  Unable to connect.");            return false;        }        // We want to directly connect to the device, so we are setting the        // autoConnect        // parameter to false.        mBluetoothGatt = device.connectGatt(this, false, mGattCallback); // 这里有个连接状态的回调mGattCallback        Log.e(TAG, "Trying to create a new connection.");        mBluetoothDeviceAddress = address;        mConnectionState = STATE_CONNECTING;        return true;    }// 连接后状态回调private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {        @Override        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {            String intentAction;            if (newState == BluetoothProfile.STATE_CONNECTED) {                boolean discover = mBluetoothGatt.discoverServices(); // 搜索发现可用服务                Log.e(TAG, "连接成功>>discoverServeices=" + discover);            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {                Log.e(TAG, "83失败");            }        }        /**         * 可用服务时回调         */        @Override        public void onServicesDiscovered(BluetoothGatt gatt, int status) {            MyLg.e("onServicesDiscovered", "status=" + status);            if (status == BluetoothGatt.GATT_SUCCESS) {                boolean notify = SampleGattAttributes.notify(gatt); // 这里就涉及到收发数据了,可以发命令给蓝牙设备,也可以单单notify,indicate监听回传的数据                Log.e(TAG, "98notify>>>" + notify);            } else {                Log.e(TAG, "onServicesDiscovered received: " + status);            }        }        @Override        public void onCharacteristicRead(BluetoothGatt gatt,                BluetoothGattCharacteristic characteristic, int status) {            Log.e(TAG, "onCharacteristicRead()");            if (status == BluetoothGatt.GATT_SUCCESS) {                broadcastUpdate(ACTION_DATA_AVAILABLE, EXTRA_READ_DATA, characteristic);            } else {                Log.e(TAG, "onCharacteristicRead() - status = " + status);            }        }        /**         * 下面是数据接收的回调         */        @Override        public void onCharacteristicChanged(BluetoothGatt gatt,                BluetoothGattCharacteristic characteristic) {            byte[] value = characteristic.getValue(); // 数据            Log.e(TAG, "127=" + value.length);            broadcastUpdate(ACTION_DATA_AVAILABLE, EXTRA_NOTIFY_DATA, characteristic);        }    };

最后就是收发数据的类,这里比较重要了,有一些需要注意。

/**     * 向蓝牙设备发送命令     * @param gatt     * @param data 要发送的字节命令     * @return     */    public static boolean sendMessage(BluetoothGatt gatt, byte[] data) {        Log.e("TAG_sendMessage", "sending start");        if (gatt == null || data.length == 0)            return false;        BluetoothGattService service = gatt.getService(UUID.fromString(GATT_SERVICE_PRIMARY2)); // 这个是对应的蓝牙设备哪个功能的Primary Service UUID        if (service == null) {//          sendDataByte(gatt); // 若为空重新发命令            return false;        }        BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(CHARACTERISTIC_WRITEABLE2)); // 这个是对应的蓝牙设备写操作的write service UUID        if (characteristic == null) {//          sendMessage(gatt, data); // 若为空重新发命令            return false;        }        characteristic.setValue(data); // 设置发送的命令        characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); // 命令类型        boolean succ = gatt.writeCharacteristic(characteristic); // 向蓝牙设备发送命令了        Log.e("TAG", "writeCharacteristic_succ=" + succ);        return succ;    }

上面这是要发送命令的,下面这种是notify或indicate就可以在onCharacteristicChanged直接监听回传的数据了

/**     * notify或indicate     * @param gatt     * @return     */    public static boolean notify(BluetoothGatt gatt) {        if (gatt == null) {            return false;        }        BluetoothGattService service = gatt.getService(UUID.fromString(GATT_SERVICE_PRIMARY2)); // 这个一样的,是对应的蓝牙设备哪个功能的Primary Service UUID        if (service == null) {            return false;        }//      BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(CHARACTERISTIC_NOTIFY2)); // 这是notify的UUID//      Log.e("TAG_notify", "notify_characteristic=" + characteristic);        BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(CHARACTERISTIC_INDICATE)); // 这是indicate的UUID        Log.e("TAG_notify", "indicate_characteristic=" + characteristic);        if (characteristic != null) {            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG)); // config的UUID            descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); // 这里就根据上面是notify还是indicate的UUID,设置对应的值(还有BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE等)            gatt.writeDescriptor(descriptor);        }        return gatt.setCharacteristicNotification(characteristic, true); // 这样就可以监听蓝牙设备回传的数据,该如何处理解析自己看着办咯(每个蓝牙设备都有协议,解析规则等)    }

到这里已经大功告成,代码量确实有点多,有点乱(纯属手打,自己开发记的笔记),但是重要的注释我都写出来了,相信你有耐心看肯定能懂,当然你若知道了这个流程,不用仔细看也知道思路了。

原创粉丝点击