最近做的蓝牙(plus.bluetooth)项目整理

1,884 阅读3分钟

bluetooth

搜索蓝牙

// 开始搜索蓝牙
document.addEventListener('plusready', function() {
    plus.bluetooth.openBluetoothAdapter({
        success:function(e){
            console.log('open success: '+JSON.stringify(e));
            // 开始搜索附近的蓝牙设备
            startBluetoothDevicesDiscovery() 
        },
        fail:function(e){
            console.log('open failed: '+JSON.stringify(e));
        }
    });
})

// 开始搜索附近的蓝牙设备
function startBluetoothDevicesDiscovery(){
    plus.bluetooth.startBluetoothDevicesDiscovery({
        success:function(e){
            console.log('start discovery success: '+JSON.stringify(e));
            // 监听发现新设备
            onBluetoothDeviceFound();
            
            setTimeout(function () {
                stopBluetoothDevicesDiscovery() // 停止搜寻附近的蓝牙外围设备
            },2000)

        },
        fail:function(e){
            console.log('start discovery failed: '+JSON.stringify(e));
        }
    });
}

// 监听发现新设备
function onBluetoothDeviceFound(){
    plus.bluetooth.onBluetoothDeviceFound(function(e){
        var devices = e.devices;
        console.log('device found: '+e.length);
        for(var i in devices){
            console.log(i+': '+JSON.stringify(devices[i]));
            // {"RSSI":-53,"advertisData":{},"deviceId":"3D340000-0000-1111-1DF8-1C0C9F9B630D","localName":"小米电视","name":"小米电视"}
            // advertisData:  *(ArrayBuffer 类型 )* 蓝牙设备的广播数据段中的ManufacturerData数据段
            // 根据广播包识别设备
            var adv = new Uint8Array(device.advertisData);
        }
    });
}
// 停止搜寻附近的蓝牙外围设备
function stopBluetoothDevicesDiscovery(){
    plus.bluetooth.stopBluetoothDevicesDiscovery({
        success: function (e) { 
        },
        fail: function (e) {
        },
        complete: function () {

        }
    });
}

// 获取固件版本号

根据广播包识别设备信息

var adv = new Uint8Array(device.advertisData);
// data = 65,70,74,0,3,133,65,1,35,0  返回十进制数

问题:已知数据133、65代表版本号(133、65并不是版本号,需要解析该数据获取真正的版本号),解析过后的数据由16bits表示,11~8表示主版本号,7~4表示次版本号,0~3表示修订版本号,那么如何解析该数据获取版本号?

浅析Uint8Array语法

var adv = new Uint8Array(device.advertisData);
// 65,70,74,0,3,133,65,1,35,0  


var v1 = adv[5] // 133
var v2 = adv[6] // 65

// 转换成8位无符号整型数组
var uint8 = new Uint8Array([v1,v2])

// DataView从二进制ArrayBuffer对象中读取数		
var buffer = new DataView(uint8.buffer) 
var uint16 = buffer.getUint16() // 34113 返回无符号短整型16位数

// 转换成二进制
var va = uint16.toString(2) // 1000 0101 0100 0001

// 截取二进制
var sliceValue1 = va.slice(4, 8); // 0101
var sliceValue2 = va.slice(8, 12); // 0100
var sliceValue3 = va.slice(12); // 0001

// 转换成十进制
var version1 = parseInt(sliceValue1, 2); // 5
var version2 = parseInt(sliceValue2, 2); // 4
var version3 = parseInt(sliceValue3, 2); // 1

// 版本号为5-4-1

读取设备传过来的数据(监听低功耗蓝牙设备的特征值变化)

// 监听低功耗蓝牙设备的特征值变化
plus.bluetooth.onBLECharacteristicValueChange(function(e) {
    // e为 {"deviceId":"04:39:26:FE:00:C9","serviceId":"1113BBB4-2910-4C3E-A9A3-3979B76A6A60","characteristicId":"0000FFE5-0000-1000-0000-00805F9B3400","value":{}}

    // 获取数据
    var value = new Uint8Array(e.value); 
    // 53 48 51 11 05 05 05 09 80 26 35 80 26 35 80 26 35 00 00 00 00 AD 50

})

校验设备传过来的数据对不对

如何校验?

根据协议提供的校验公式进行数据校验。判断根据公式算出来的校验码是否等于数据传过来的校验码,如果不等于,该数据则不对,抛弃该数据。

校验公式为从 类型 开始到 数据 计算出和sum; checksum = ((0x100 - (sum&0xFF)) & 0xFF),校验代码如下:

var value = new Uint8Array(e.value); // value为设备传过来的值
// 53 48 51 11 05 05 05 09 80 26 35 80 26 35 80 26 35 00 00 00 00 AD 50
var sum = 0;
for (var i = 1; i < value.length - 2; i++) {
    sum += value[i];
}

var check = (0x100 - (sum & 0xff)) & 0xFF;
console.log("验证校验码:" + check.toString(16));

if (check != checkNum) {
    console.error("校验失败!!!!!!!!");
}

根据子指令获取相应的数据

已知数据中的第5位为子指令,第5到20位为该指令对应的数据data。比如说代表设备温度的子指令是十六进制数05,则data代表温度

var value = new Uint8Array(e.value); // value为设备传过来的值
// 53 48 51 11 05  05 05 09 80 26 35 80 26 35 80 26 35 00 00 00 00  AD 50

// 子指令  
var subInstruct = value[4]; // 05
// 数据
var data = value.slice(5, length + 5 - 1);
if(subInstruct.toString(16) == 5){
    var view = new DataView(value.buffer);
    console.log("加热片 1 目标温度:" + view.getUint8(5)); // 目标温度
    var bin = view.getUint16(3).toString(2).padStart(16, 0); // 示例:0000 0000 0011 0100
    console.log("当前温度:" + parseInt(bin.slice(8), 2)); // bit7~0:当前温度			
}

向蓝牙设备写入值

写入的值(writeBLECharacteristicValue)与设备传过来的值(onBLECharacteristicValueChange)格式一致。

// 数据格式: 头部 类型  指令 子指令+数据的长度 子指令 数据 校验码 尾部

// 拼装成固定格式数据
var temp = [0x53, 0x48, 0x51, data.length + 1, instruction]; 

if (data.length > 0) {
    for (var i = 0; i < data.length; i++) {
        temp.push(data[i]);
    }
}
var sum = 0;
for (var i = 1; i < temp.length; i++) {
    sum += temp[i];
}
check = (0x100 - (sum & 0xff)) & 0xFF;
temp.push(check) // 校验码
temp.push(0x50) // 尾部

console.log('写入:'+ JSON.stringify(temp)) 
plus.bluetooth.writeBLECharacteristicValue({
    deviceId: deviceId,
    serviceId: serviceId,
    characteristicId: characteristicId,
    value: new Uint8Array(temp),
    success: function(e) {
        console.log('write characteristics success');
    },
    fail: function(e) {
        console.log('write characteristics failed:'+JSON.stringify(e));
    }
});	

写入成功,值会从订阅(onBLECharacteristicValueChange)返回,继续校验数据,根据子指令获取数据data。