小程序获取连接蓝牙设备所有特征值(getBLEDeviceCharacteristics)

2018年08月25日 10:10 | 14917次浏览 作者原创 版权保护

我们在上一章节讲解了小程序获取蓝牙设备所有service(getBLEDeviceServices),并且在此章节获取到了三个蓝牙设备服务,它们分别为"FEE7","FEE8","FEE9",三个都是简写,详情请移步上一章节,本章节着重说下蓝牙设备的特征值的获取,不过呢,好多读者在这里迷糊了,蓝牙设备的服务,蓝牙设备的特征值到底是个什么鬼东西,其实本作者也仅仅是个软件程序员,对于硬件不是很了解,故上网查了下,摘录了一部分,讲解的我认为还是比较明了的,具体如下:

之前说到蓝牙的连接过程,那蓝牙连接之后具体是如何传数据的呢。这里做一下简要说明。

蓝牙4.0是以参数来进行数据传输的,即服务端定好一个参数,客户端可以对这个参数进行读,写,通知等操作,这个东西我们称之为特征值(characteristic),

但一个参数不够我们用,比如我们这个特征值是电量的值,另一个特征值是设备读取的温度值。

那这时候会有多个特征值,并且我们还会对它们分类,分出来的类我们称之为服务(service)。

一个设备可以有多个服务,每一个服务可以包含多个特征值。为了方便操作,每个特征值都有他的属性,例如长度(size),权限(permission),值(value),描述(descriptor)。

如上面文字的解释说明,我们一般接入小程序的蓝牙智能设备必须具备读、写、通知三个属性,否则无法利用微信小程序对设备进行控制(向设备发送指令,向设备写入指令,微信小程序接收硬件返回的数据)。


获取蓝牙设备特征值接口getBLEDeviceCharacteristics官方文档如下

wx.getBLEDeviceCharacteristics(OBJECT)

获取蓝牙设备某个服务中的所有 characteristic(特征值)

OBJECT参数说明:

参数类型必填说明
deviceIdString蓝牙设备 id,参考 device 对象
serviceIdString蓝牙服务 uuid
successFunction成功则返回本机蓝牙适配器状态
failFunction接口调用失败的回调函数
completeFunction接口调用结束的回调函数(调用成功、失败都会执


success返回参数:

参数类型说明
characteristicsArray设备特征值列表
errMsgString成功:ok,错误:详细信息


characteristic对象

蓝牙设备characteristic(特征值)信息

参数类型说明
uuidString蓝牙设备特征值的 uuid
propertiesObject该特征值支持的操作类型


properties对象

参数类型说明
readBoolean该特征值是否支持 read 操作
writeBoolean该特征值是否支持 write 操作
notifyBoolean该特征值是否支持 notify 操作
indicateBoolean该特征值是否支持 indicate 操作


示例代码:

wx.getBLEDeviceCharacteristics({
  // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  deviceId: deviceId,
  // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取
  serviceId: serviceId,
  success: function (res) {
    console.log('device getBLEDeviceCharacteristics:', res.characteristics)
  }
})<!--V型知识库原创 www.vxzsk.com-->

Bug & Tip

tip:传入的serviceId需要在getBLEDeviceServices获取到

tip:iOS平台上后续对特征值的read、write、notify,由于系统需要获取特征值实例,传入的 serviceId 与 characteristicId 必须由 getBLEDeviceServices 与 getBLEDeviceCharacteristics 中获取到后才能使用。建议双平台统一在建立链接后先执行 getBLEDeviceServices 与 getBLEDeviceCharacteristics 后再进行与蓝牙设备的数据交互


根据官方文档编写实现代码

根据微信小程序官方文档,getBLEDeviceCharacteristics此接口需要两个必要参数,一个是连接设备的deviceId,另一个是蓝牙设备主服务的UUID,那么在这里我们分别解释下这两个参数。

deviceId:deviceId的获取我们在第5章节已经获取到了,如果是Android 上获取到的deviceId为设备 MAC 地址,iOS 上则为设备 uuid。因此deviceId不能硬编码到代码中,如果你仅仅是测试的话用安卓手机则也可以直接写成mac地址。

serviceId:就是我们在第9章节获取到的蓝牙设备UUID,但有个疑问,主服务的UUID并不是一个,有可能是多个,例如本人蓝牙设备获取到了三个,分别是FEE7,FEE8,FEE9,那么传入参数的时候该传那个呢?嘿嘿,本人也不知道,可以问下硬件厂商,如果问不到,那就把三个分别都测试下,那个能用,用那个,经过测试,具有读、写、通知的服务UUID为FEE7,接下来的示例代码也将传入的是FEE7,那么我们就实现FEE7下面的特征值有哪些吧。


1,打开微信小程序开发工具,编写lanya.wxml  实际上此页面类似于html页面一样,代码如下

<view class="content"><!--V型知识库原创 www.vxzsk.com-->
<view>日志信息:
<textarea style='border:1px solid #ccc'>
{{msg}}
</textarea>
</view>

<button type="primary" class="button" bindtap="lanya1">1初始化蓝牙适配器</button>
<button type="primary" class="button" bindtap="lanya2">2本机蓝牙适配状态</button>
<button type="primary" class="button" bindtap="lanya3">3搜索周边蓝牙设备</button>
<button type="primary" class="button" bindtap="lanya4">4获取所有周边蓝牙设备信息</button>
<block wx:for="{{devices}}" wx:key="{{test}}">
<button type="primary" class="button" id="{{item.deviceId}}" style='background-color:red' bindtap="connectTO">连接蓝牙设备{{item.name}}</button>
</block>
<button type="primary" class="button" bindtap="lanya5">5停止搜索周边蓝牙设备</button>
<button type="primary" class="button" bindtap="lanya6">6获取蓝牙设备所有service(服务)</button>
<button type="primary" class="button" bindtap="lanya7">7获取连接设备所有特征值</button>


</view>

如上面所示,第17行代码新增了名为获取连接设备所有特征值的按钮,且绑定了一个名为lanya7的js函数,此函数便是实现获取连接设备所有特征值的方法。

2、打开lanya.js文件,实现wx.getBLEDeviceCharacteristics(OBJECT)接口代码如下:

//获取连接设备的所有特征值  
lanya7: function () {
var that = this;
var myuuid = that.data.services[2].uuid //具有读写通知属性的服务uuid
wx.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId: that.data.connectedDeviceId,
// 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取
serviceId: myuuid,
success: function (res) {
for (var i = 0; i < res.characteristics.length; i++) {
console.log('特征值:' + res.characteristics[i].uuid)

}
console.log('device getBLEDeviceCharacteristics:', res.characteristics);

that.setData({
msg: JSON.stringify(res.characteristics),
})
},
fail: function () {
console.log("fail");
},
complete: function () {
console.log("complete");
}
})

}

如上述代码第4行,便是主服务UUID,由于本作者做了测试,测试结果FEE7具备读写通知条件,且在数组下标为2中,当然你如果知道值的话,可以直接硬编码写在这里。UUID获取请参考第9章节。

第7行为连接设备的deviceId,如果不清楚如何获得请分别参考第5章节。

从第11行代码开始循环设备的特征值。

3、启动硬件蓝牙设备(例如蓝牙打印机,蓝牙锁等),打开手机蓝牙,打开手机微信app,然后点击微信小程序开发工具头部的预览按钮,会出现一个二维码,用微信app扫描此二维码,加载小程序应用。

打开日志效果如下:

如上图所示,红的圈部分便是获取到的特征值,一共获取到了6个特征值,现在用户更有疑问了,到底用哪一个呢?其实官方文档已经给了判断方法,具有读、写、通知操作的属性特征值properties对象便能判断出来,不清楚的读者请看上面的官方文档properties对象,判断实现方法如下:

在循环特征值的for语句里面判断

for (var i = 0; i < res.characteristics.length; i++) {
console.log('特征值:' + res.characteristics[i].uuid)
if (res.characteristics[i].properties.notify) {
console.log("获取开启notify的ServicweId:", myuuid);
console.log("获取开启notify的CharacteristicsId:", res.characteristics[i].uuid);
that.setData({
notifyServicweId: myuuid,
notifyCharacteristicsId: res.characteristics[i].uuid,

})
}
if (res.characteristics[i].properties.write) {
console.log("获取开启write的ServicweId:", myuuid);
console.log("获取开启write的CharacteristicsId:", res.characteristics[i].uuid);
that.setData({
writeServicweId: myuuid,
writeCharacteristicsId: res.characteristics[i].uuid,
})
} else if (res.characteristics[i].properties.read) {
console.log("读read操作readServicweId:", myuuid);
console.log("读read操作:readCharacteristicsId", res.characteristics[i].uuid);
that.setData({
readServicweId: myuuid,
readCharacteristicsId: res.characteristics[i].uuid,
})

}
}


lanya.wxml源码

<view class="content">
<view>日志信息:
<textarea style='border:1px solid #ccc'>
{{msg}}
</textarea>
</view>

<button type="primary" class="button" bindtap="lanya1">1初始化蓝牙适配器</button>
<button type="primary" class="button" bindtap="lanya2">2本机蓝牙适配状态</button>
<button type="primary" class="button" bindtap="lanya3">3搜索周边蓝牙设备</button>
<button type="primary" class="button" bindtap="lanya4">4获取所有周边蓝牙设备信息</button>
<block wx:for="{{devices}}" wx:key="{{test}}">
<button type="primary" class="button" id="{{item.deviceId}}" style='background-color:red' bindtap="connectTO">连接蓝牙设备{{item.name}}</button>
</block>
<button type="primary" class="button" bindtap="lanya5">5停止搜索周边蓝牙设备</button>
<button type="primary" class="button" bindtap="lanya6">6获取蓝牙设备所有service(服务)</button>
<button type="primary" class="button" bindtap="lanya7">7获取连接设备所有特征值</button>

<!--V型知识库原创 www.vxzsk.com-->
</view>


lanya.js源码

// pages/lanya/lanya.js www.vxzsk.com V型知识库原创
Page({

/**
   * 页面的初始数据
   */
data: {
connectedDeviceId: "", //已连接设备uuid
services: "", // 连接设备的服务
characteristics: "",   // 连接设备的状态值
writeServicweId: "", // 可写服务uuid
writeCharacteristicsId: "",//可写特征值uuid
readServicweId: "", // 可读服务uuid
readCharacteristicsId: "",//可读特征值uuid
notifyServicweId: "", //通知服务UUid
},

/**
   * 生命周期函数--监听页面加载
   */
onLoad: function (options) {
},

/**
   * 生命周期函数--监听页面初次渲染完成
   */
onReady: function () {
},

/**
   * 生命周期函数--监听页面显示
   */
onShow: function () {
},

/**
   * 生命周期函数--监听页面隐藏
   */
onHide: function () {
},

/**
   * 生命周期函数--监听页面卸载
   */
onUnload: function () {
},

/**
   * 页面相关事件处理函数--监听用户下拉动作
   */
onPullDownRefresh: function () {
},

/**
   * 页面上拉触底事件的处理函数
   */
onReachBottom: function () {
},

/**
   * 用户点击右上角分享
   */
onShareAppMessage: function () {
},
// 初始化蓝牙适配器
lanya1: function () {
var that = this;
wx.openBluetoothAdapter({
success: function (res) {
console.log('初始化蓝牙适配器返回' + JSON.stringify(res))
//页面日志显示
that.setData({
msg: JSON.stringify(res)
})
},
fail:function(res){
console.log('初始化蓝牙适配器失败' + JSON.stringify(res))
}
})
},
// 本机蓝牙适配器状态
lanya2: function () {
var that = this;
wx.getBluetoothAdapterState({
success: function (res) {
//页面日志显示
that.setData({
msg: "本机蓝牙适配器状态" + "/" + JSON.stringify(res.errMsg) + "==是否可用:" +  res.available

})
},
fail:function(res){
//页面日志显示
that.setData({
msg: "本机蓝牙适配器状态" + "/" + JSON.stringify(res.errMsg) + "==是否可用:" + res.available


})

}
})
},
//搜索设备
lanya3: function () {
var that = this;
wx.startBluetoothDevicesDiscovery({
//services: ['FEE7'],
success: function (res) {
that.setData({
msg: "搜索设备" + JSON.stringify(res),
})
console.log('搜索设备返回' + JSON.stringify(res))
}
})
},
// 获取所有已发现的设备
lanya4: function () {
var that = this;
wx.getBluetoothDevices({
success: function (res) {
that.setData({
msg: "搜索设备" + JSON.stringify(res.devices),
devices: res.devices
})
console.log('搜到的蓝牙设备数目:' + res.devices.length)
console.log('获取到周边搜到的设备信息:' + JSON.stringify(res.devices))
}
})
},
//连接设备
connectTO: function (e) {
var that = this;
wx.createBLEConnection({
deviceId: e.currentTarget.id,
success: function (res) {
console.log('连接设备返回:'+res.errMsg);
that.setData({
connectedDeviceId: e.currentTarget.id,
msg: "已连接" + e.currentTarget.id + '==='+'连接设备返回:'+res.errMsg,
msg1: "",
})
},
fail: function () {
console.log("调用失败");
},
complete: function () {
console.log("调用结束");
}

})
console.log(that.data.connectedDeviceId);
},
//停止搜索周边设备
lanya5: function () {
var that = this;
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
that.setData({
msg: "停止搜索周边设备" + "/" + JSON.stringify(res.errMsg),
sousuo: res.discovering ? "在搜索。" : "未搜索。",
status: res.available ? "可用。" : "不可用。",
})
}
})
},
// 获取连接设备的service服务
lanya6: function () {
var that = this;
wx.getBLEDeviceServices({
// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId: that.data.connectedDeviceId,
success: function (res) {
console.log('device services:', JSON.stringify(res.services));
for(var i=0;i<res.services.length;i++){
console.log(i+"--UUID:------"+res.services[i].uuid)
//var servicesUuid = res.services[i].uuid
}
that.setData({
services: res.services,
msg: JSON.stringify(res.services),
})
}
})
},
//获取连接设备的所有特征值  
lanya7: function () {
var that = this;
var myuuid = that.data.services[2].uuid //具有读写通知属性的服务uuid
console.log('myuuid' + myuuid)
wx.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId: that.data.connectedDeviceId,
// 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取
serviceId: myuuid,
success: function (res) {
for (var i = 0; i < res.characteristics.length; i++) {
console.log('特征值:' + res.characteristics[i].uuid)
if (res.characteristics[i].properties.notify) {
console.log("获取开启notify的ServicweId:", myuuid);
console.log("获取开启notify的CharacteristicsId:", res.characteristics[i].uuid);
that.setData({
notifyServicweId: myuuid,
notifyCharacteristicsId: res.characteristics[i].uuid,

})
}
if (res.characteristics[i].properties.write) {
console.log("获取开启write的ServicweId:", myuuid);
console.log("获取开启write的CharacteristicsId:", res.characteristics[i].uuid);
that.setData({
writeServicweId: myuuid,
writeCharacteristicsId: res.characteristics[i].uuid,
})
} else if (res.characteristics[i].properties.read) {
console.log("读read操作readServicweId:", myuuid);
console.log("读read操作:readCharacteristicsId", res.characteristics[i].uuid);
that.setData({
readServicweId: myuuid,
readCharacteristicsId: res.characteristics[i].uuid,
})

}
}
console.log('device getBLEDeviceCharacteristics:', res.characteristics);

that.setData({
msg: JSON.stringify(res.characteristics),
})
},
fail: function () {
console.log("fail");
},
complete: function () {
console.log("complete");
}
})

}
})



小说《我是全球混乱的源头》
此文章本站原创,地址 https://www.vxzsk.com/1868.html   转载请注明出处!谢谢!

感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程