更新记录

1.0.4(2025-05-25)

  1. 优化代码

1.0.3(2025-05-25)

  1. 优化

1.0.2(2025-05-24)

  1. 修复iOS在高版本HB的编译兼容性问题
查看更多

平台兼容性

uni-app

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - - 4.4 12 -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟
× × × × × × - × × × ×

uni-app x

Chrome Safari Android iOS 鸿蒙 微信小程序
- - 5.0 12 - ×

蓝牙外围设备从设备广播servicecharacteristic通讯

功能

  1. 广播蓝牙数据,可以广播蓝牙名、serviceUuid、serviceDataUuid、serviceData、发射功率、厂家参数(ID和数据)、广播功率、是否可连接、持续时间
  2. 蓝牙数据通讯,增加删除service,characteristic读写

蓝牙分为中心设备(Central、Master、主设备、客户端)和外围设备(Peripheral、Slave、从设备、服务端) 手机做为客户端可以连接多个蓝牙设备,所以手机又可以叫中心设备(Central),蓝牙设备叫外围设备(Peripheral)。 例如:通过手机蓝牙开启共享单车,手机称为中心设备,共享单车称为外围设备

本插件是外围设备(Peripheral、Slave、从设备、服务端)

中心设备蓝牙请使用插件https://ext.dcloud.net.cn/plugin?name=wrs-uts-bluetoothcenter

集成步骤

接口


import {
    UTSBluetoohSlave
} from "@/uni_modules/wrs-uts-bluetoothslave"
let slave = new UTSBluetoohSlave()
  • 设置回调

slave.setCallback((resp) => {
    this.showMsg(JSON.stringify(resp))
    let opt = resp.opt
    switch (opt) {
        // 广播开启成功
        case "onStartSuccess": {
            this.showMsg("广播成功")
            // 广播成功后添加service,添加了service这样客户端蓝牙才能连接通讯
            this.addService()
        }
        break;
        // 广播失败
        case "onStartFailure": {
            // 1: ADVERTISE_FAILED_DATA_TOO_LARGE
            // 2: ADVERTISE_FAILED_TOO_MANY_ADVERTISERS
            // 3: ADVERTISE_FAILED_ALREADY_STARTED
            // 4: ADVERTISE_FAILED_INTERNAL_ERROR
            // 5: ADVERTISE_FAILED_FEATURE_UNSUPPORTED
            // 18: 广播数据包太大,不同手机品牌支持的大小不一样
            // 如果有其他错误码,可以百度搜索"android AdvertiseCallback onStartFailure ${errorCode}"
            let errorCode = resp.errorCode
            this.showMsg("广播失败:" + JSON.stringify(resp))
        }
        break;
        // 蓝牙连接状态变化
        case "onConnectionStateChange": {
            var status = resp.status;
            var newState = resp
                .newState; // 0: STATE_DISCONNECTED 1: STATE_CONNECTING 2: STATE_CONNECTED 3: STATE_DISCONNECTING
            if (status == 0) { // 成功
                if (newState == 2) { // 连接成功
                    this.showMsg("收到新蓝牙连接成功 name:" + resp.device.name + " mac:" + resp.device
                        .address)
                } else if (newState == 0) { // 断开连接
                    this.showMsg("蓝牙断开连接")
                } else if (newState == 1) { // 连接中
                    this.showMsg("蓝牙连接中")
                } else if (newState == 3) { // 断开中
                    this.showMsg("蓝牙断开中")
                }
            } else { // 出错
                this.showMsg("蓝牙出错")
            }
        }
        break;
        case "onServiceAdded": {
            var status = resp.status;
            if (status == 0) { // 添加成功

            } else { // 添加失败

            }
        }
        break;
        // 收到客户端特征值读取请求
        case "onCharacteristicReadRequest": {
            this.showMsg("收到客户端特征值读取请求")
            let params = {}
            params.status = 0
            params.address = resp.device.address
            params.requestId = resp.requestId
            params.offset = resp.offset
            params.value = resp.characteristic.value
            let suc = slave.sendResponse(params)
            if (suc) {
                this.showMsg("发送响应数据成功:" + params.value)
            } else {
                this.showMsg("发送响应数据失败")
            }
        }
        break;
        // 收到客户端特征值写入数据,即:收到对方发来的蓝牙数据
        case "onCharacteristicWriteRequest": {
            this.showMsg("收到对方发来的蓝牙数据:" + JSON.stringify(resp))
            // {
            //  "characteristic": {
            //      "properties": 26,
            //      "value": [2, 6, -1],
            //      "uuid": "0000ff11-0000-1000-8000-00805f9b34fb",
            //      "permissions": 17,
            //      "writeType": 2,
            //      "instanceId": 43
            //  },
            //  "preparedWrite": false,
            //  "offset": 0,
            //  "device": {
            //      "bluetoothClass": {
            //          "majorDeviceClass": 0
            //      },
            //      "address": "46:82:6D:75:9A:EA",
            //      "type": 0,
            //      "bondState": 10
            //  },
            //  "requestId": 2,
            //  "value": [2],
            //  "responseNeeded": true,
            //  "opt": "onCharacteristicWriteRequest"
            // }
            // 
            let responseNeeded = resp.responseNeeded
            if (responseNeeded) {
                let params = {}
                params.address = resp.device.address
                params.requestId = resp.requestId
                params.status = 0 // 0: GATT_SUCCESS
                params.offset = resp.offset
                params.value = resp.value
                // 响应客户端,即:告诉对方蓝牙这边已经收到数据了
                let respSuc = slave.sendResponse(params)
                if (!respSuc) {
                    this.showMsg("sendResponse失败")
                } else {
                    this.showMsg("响应客户端:" + params.value)
                }
            }
            // 这里模拟数据处理业务,处理完成后发送处理结果给对方蓝牙,即:发数据客户端
            setTimeout(() => {
                let sendParams = {}
                sendParams.address = resp.device.address
                sendParams.serviceUuid = this.UUID_SERVICE
                sendParams.characteristicUuid = resp.characteristic.uuid
                sendParams.value = [0x01, 0x02, 0xFF]
                slave.sendData(sendParams)
                this.showMsg("发送数据给对方:"+ sendParams.value)
            }, 2000);
        }
        break;
        // 收到客户端描述读取请求,仅支持Android
        case "onDescriptorReadRequest": {
            this.showMsg("收到客户端描述读取请求")
            let params = {}
            params.address = resp.device.address
            params.requestId = resp.requestId
            params.offset = resp.offset
            params.status = 0
            params.value = resp.characteristic.value
            let suc = slave.sendResponse(params)
            if (suc) {
                this.showMsg("发送响应数据成功")
            } else {
                this.showMsg("发送响应数据失败")
            }
        }
        break;
        // 收到描述写入数据,仅支持Android
        case "onDescriptorWriteRequest": {
            this.showMsg("收到描述写入数据")
            let params = {}
            params.status = 0
            params.address = resp.device.address
            params.requestId = resp.requestId
            params.offset = resp.offset
            params.value = resp.characteristic.value
            let suc = slave.sendResponse(params)
            if (suc) {
                this.showMsg("发送响应数据成功")
            } else {
                this.showMsg("发送响应数据失败")
            }
        }
        break;
        // 仅支持Android
        case "onExecuteWrite": {

        }
        break;
        // 仅支持Android
        case "onNotificationSent": {

        }
        break;
        // 仅支持Android
        case "onMtuChanged": {

        }
        break;
        case "onPhyUpdate": {
            // 仅支持Android
        }
        break;
        // 仅支持Android
        case "onPhyRead": {

        }
        break;
        default:
            break;
    }
})
  • 初始化蓝牙

var params = {};
if (this.isAndroid) {

} else {
    params.CBCentralManagerOptionShowPowerAlertKey = true;
}
// 初始化,仅支持iOS
slave.initBluetooth(params);
  • 广播蓝牙 android的蓝牙广播数据包大小不同机型大小不一样 广播结果在回调接口里slave.setCallback((resp) => {}) => onStartSuccess、onStartFailure

// ios仅支持localName和advertiseData.serviceUuid
let params = {}
// 仅支持ios,ios需要将localName蓝牙名放到广播里,不然扫描不到蓝牙名
params.localName = this.name
// 仅支持Android,设置广播模式,以控制广播的功率和延迟
// 0: ADVERTISE_MODE_LOW_POWER
// 1: ADVERTISE_MODE_BALANCED
// 2: ADVERTISE_MODE_LOW_LATENCY
params.advertiseMode = 2
//仅支持Android,发射功率级别
// 0: ADVERTISE_TX_POWER_ULTRA_LOW
// 1: ADVERTISE_TX_POWER_MEDIUM
// 2: ADVERTISE_TX_POWER_MEDIUM
// 3: ADVERTISE_TX_POWER_HIGH
params.txPowerLevel = 3
// 仅支持Android,设置是否可以连接
params.connectable = true
params.advertiseData = {
    // includeDeviceName: true, // 仅支持Android
    // includeTxPowerLevel: true, // 仅支持Android
    // serviceUuid: [this.UUID_SERVICE],// 支持iOS和Android
    manufacturerData: [{ // 仅支持Android
        id: 1,
        data: [0x01, 0x22]
    }],

    // serviceData:[ // 仅支持Android
    //  {
    //      uuid: this.UUID_SERVICE,
    //      data: [0x01, 0x22]
    //  },
    //  {
    //      uuid: this.UUID_SERVICE2,
    //      data: [0x01, 0x22]
    //  }
    // ]
}
// 仅支持Android,
// params.scanResponse = {
//  includeDeviceName: true,
//  includeTxPowerLevel: true,
//  manufacturerData: [{
//      id: 1,
//      data: [0x01, 0x22]
//  }]
// }
slave.startAdvertising(params)
  • 停止广播

slave.stopAdvertising()
  • 开启从设备蓝牙服务,服务启动后添加service和characteristic,仅支持Android

let suc = slave.openGattServer()
  • 清除service

slave.clearServices()
  • 添加service

// android、ios属性 properties
// 1: PROPERTY_BROADCAST
// 2: PROPERTY_READ
// 4: PROPERTY_WRITE_NO_RESPONSE
// 8: PROPERTY_WRITE
// 16: PROPERTY_NOTIFY
// 32: PROPERTY_INDICATE
// 64: PROPERTY_SIGNED_WRITE
// 128: PROPERTY_EXTENDED_PROPS

var permissions = 0x01 | 0x10;
var value = null;
if (this.isAndroid) {
    // 权限permissions
    // android permissions: 
    // 1: PERMISSION_READ
    // 2: PERMISSION_READ_ENCRYPTED
    // 4: PERMISSION_READ_ENCRYPTED_MITM
    // 16: PERMISSION_WRITE
    // 32: PERMISSION_WRITE_ENCRYPTED
    // 64: PERMISSION_WRITE_ENCRYPTED_MITM
    // 128: PERMISSION_WRITE_SIGNED
    // 256:PERMISSION_WRITE_SIGNED_MITM
    permissions = 0x01 | 0x10;
    value = [0x02, 0x06, 0xFF]
    // descriptors = [{ // 描述
    //  uuid: this.NotificationDescriptorUUID,
    //  permissions: 0x01 |
    //      0x10, // 仅对Android生效,0x01: PERMISSION_READ 0x10:PERMISSION_WRITE
    //  value: [0x02, 0x06, 0xFF]
    // }];
} else {
    // ios permissions:
    // 0x01: CBAttributePermissionsReadable
    // 0x02: CBAttributePermissionsWriteable
    // 0x04: CBAttributePermissionsReadEncryptionRequired
    // 0x08: CBAttributePermissionsWriteEncryptionRequired
    permissions = 0x01 | 0x02;
}

let services = []
services.push({
    uuid: this.UUID_SERVICE, // service的UUID
    type: 0, // 0: SERVICE_TYPE_PRIMARY 1: SERVICE_TYPE_SECONDARY
    characteristics: [{ // 读写特征
            uuid: this.UUID_CHARACTERISTIC,
            properties: 0x08 |
            0x10, // 0x08: PROPERTY_WRITE 0x10: PROPERTY_NOTIFY 0x02: PROPERTY_READ
            permissions: permissions,
            value: value // ios下,如果要给characteristic只能是只读状态下才能赋值

        }
        // { // 只读特征
        //  uuid: this.UUID_CHARACTERISTIC2,
        //  properties: 0x02, // 0x08: PROPERTY_WRITE 0x10: PROPERTY_NOTIFY 0x02: PROPERTY_READ
        //  permissions: 0x01, // 0x10: PERMISSION_WRITE 0x01: PERMISSION_READ
        //  value: [0x01, 0x06, 0xFF]
        // }
    ]
})
let suc = slave.addService(services)
if (!suc) {
    this.showMsg("addService 失败")
} else {
    this.showMsg("addService 成功")
}

隐私、权限声明

1. 本插件需要申请的系统权限列表:

蓝牙、定位、读写

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问