准备工作:
1:需要一个蓝牙板子和串口软件(卖蓝牙板子的商家会提供),手机上需要蓝牙调试助手(为了测试蓝牙是否正常连接)
2:蓝牙板通过usb插入到电脑端
3:安装好串口调试工具并打开连接上蓝牙
4:打开手机蓝牙调试助手,连接上后进行读写操作,确认已正常连接通信
准备工作完结!
直接上代码
第一步:初始化蓝牙设备, onShow里面调用或者onLoad里面调用都可,看你的需求场景
initBlue () {
wx.openBluetoothAdapter({
success: (res) => {
wx.showToast({
title: '正在搜索蓝牙设备...',
icon: 'loading'
})
this.findBlue()
},
fail: (error) => {
wx.showToast({
title: '请开启蓝牙',
icon: 'fails',
duration: 1000
})
this.setData({ isTrigger: false })
}
})
},
第二步:搜索蓝牙设备
findBlue(){
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
interval: 0,
powerLevel: 'high',
success: (res) => {
this.getBlue()//3.0
},
complete: () => {
this.setData({ isTrigger: false })
}
})
},
第三步:拿到需要的蓝牙设备进行列表渲染
getBlue () {
wx.onBluetoothDeviceFound((devices) => {
if (devices.devices[0].name.includes('demo')) {
console.log(devices.devices[0].name, 'devices.devices[0].name')
// 添加有名字的蓝牙设备,并去重处理
this.setData({ bluetoolList: [...this.data.bluetoolList, devices.devices[0]].filter((obj, index, self) =>
index === self.findIndex((t) => (
t.name === obj.name
))) })
wx.stopBluetoothDevicesDiscovery() // 停止搜索
}
})
},
第四步:点击某个蓝牙设备进行连接
connetBluetooth(evt) {
wx.showToast({
title: '正在连接...',
icon: 'loading'
})
console.log(evt.currentTarget.dataset, '=========')
const { row } = evt.currentTarget.dataset
this.setData({ currentDeviceid: row.deviceId })
wx.setStorageSync('deviceId', row.deviceId)
wx.createBLEConnection({
deviceId: row.deviceId,
timeout: 5000,
success: (res) => {
console.log('connet success: ', res)
wx.stopBluetoothDevicesDiscovery()
this.getServiceUUid() // 连接的收就获取服务ID 用于后面获取特征值id(特征值id可以用来进行读、写、监听蓝牙操作)
},
fail: (error) => {
console.log('createBLEConnection error: ', error)
if (error.errCode === -1) { // 表示已经连接, 直接跳转到对应页面即可
wx.navigateTo({ url: '/pages/xxx/xxx' })
} else {
wx.showToast({
title: '连接失败',
icon: 'error',
timeout: 500,
complete: () => {
}
})
}
}
})
},
第五步:获取服务id,不同蓝牙设备,不同机型,获取的服务值不一样,根据你自己的蓝牙板子和机型来获取,一定要获取准确,错了就读写不了蓝牙设备
getServiceUUid() {
console.log('=====================getServiceUUid=======================')
let _this = this
wx.getBLEDeviceServices({
// 这里的 deviceid 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId: _this.data.currentDeviceid,
success: async (res) => {
console.log('res.services: ', res.services)
if (wx.getStorageSync('platform') === 'ios') {
// read
await _this.setData({ readServiceId: res.services[0].uuid })
await wx.setStorageSync('readServiceId', res.services[0].uuid)
// write true
await _this.setData({ writeServiceId: res.services[1].uuid })
await wx.setStorageSync('writeServiceId', res.services[1].uuid)
// notify
await _this.setData({ notifyServiceId: res.services[1].uuid })
await wx.setStorageSync('notifyServiceId', res.services[1].uuid)
await _this.getReadCharacteIdIos()
await _this.getWriteCharacteIdIos()
} else {
// read true
// _this.setData({ readServiceId: res.services[0].uuid })
await _this.setData({ readServiceId: res.services[2].uuid })
await wx.setStorageSync('readServiceId', res.services[2].uuid)
// 第一个 write: true;第二个 notify: true
await _this.setData({ writeServiceId: res.services[1].uuid })
await wx.setStorageSync('writeServiceId', res.services[1].uuid)
await _this.setData({ notifyServiceId: res.services[1].uuid })
await wx.setStorageSync('notifyServiceId', res.services[1].uuid)
// read true
// await _this.setData({ readServiceId: res.services[2].uuid })
// await wx.setStorageSync('readServiceId', res.services[2].uuid)
// indicate 安卓端监听不到蓝牙发送过来的回调
// await _this.setData({ notifyServiceId: res.services[3].uuid })
// await wx.setStorageSync('notifyServiceId', res.services[3].uuid)
await _this.getReadCharacteId()
// await _this.getNotifyCharacteId()
await _this.getWriteCharacteId()
}
}
})
},
第六步:获取特征值id,并保证在了本地(也可以挂在全局,方便另一个页面获取),跳转到对应页面,这里你可以封装一下,我这里做demo就没封装,五个方法,分别获取IOS端和安卓端的对应读写和监听的特征值,一定要根据蓝牙的板子获取对应正确的特征值(为true的才能进行后面的连接和读写操作),慢慢调试
// readServiceId
getReadCharacteId() {
let _this = this
wx.getBLEDeviceCharacteristics({
deviceId: _this.data.currentDeviceid,
serviceId: _this.data.readServiceId,
success: (res) => {
console.log('res.haracteristics read: ', res.characteristics)
for (let i = 0; i < res.characteristics.length; i++) {
let characteristic = res.characteristics[i]
// 检查特征值是否具有 read 属性为 false
if (characteristic.properties.read) {
// 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
_this.setData({ characteReadId: characteristic.uuid })
wx.setStorageSync('characteReadId', characteristic.uuid)
// break // 找到符合条件的特征值后,结束循环
}
}
},
fail: (error) => {
console.log('get read CharacteId error: ', error)
}
})
},
// use bluetool deviceId and uuid get characteId (特征值) writeServiceId
getWriteCharacteId () {
let _this = this
wx.getBLEDeviceCharacteristics({
deviceId: _this.data.currentDeviceid,
serviceId: _this.data.writeServiceId,
success: (res) => {
// 遍历特征值列表
console.log('res.characteristics write : ', res.characteristics)
for (let i = 0; i < res.characteristics.length; i++) {
let characteristic = res.characteristics[i]
// 检查特征值是否具有 read 属性为 false
if (characteristic.properties.write) {
// 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
_this.setData({
characteWriteId: characteristic.uuid
})
wx.setStorageSync('characteWriteId', characteristic.uuid)
// break // 找到符合条件的特征值后,结束循环
}
if (characteristic.properties.notify) {
_this.setData({ characteNotifyId: characteristic.uuid })
wx.setStorageSync('characteNotifyId', characteristic.uuid)
}
}
console.log('currentDeviceid: ', _this.data.currentDeviceid)
console.log('----------------------read--------------------')
console.log('readServiceId: ', _this.data.readServiceId)
console.log('characteReadId: ', _this.data.characteReadId)
console.log('----------------------write--------------------')
console.log('writeServiceId: ', _this.data.writeServiceId)
console.log('characteWriteId: ', _this.data.characteWriteId)
wx.navigateTo({
url: '/pages/action/action'
})
wx.hideToast()
},
fail: function (error) {
console.log("error reason: ", error)
}
})
},
// notifyServiceId
getNotifyCharacteId() {
let _this = this
wx.getBLEDeviceCharacteristics({
deviceId: _this.data.currentDeviceid,
serviceId: _this.data.notifyServiceId,
success: (res) => {
console.log('res.characteristics notify: ', res.characteristics)
for (let i = 0; i < res.characteristics.length; i++) {
let characteristic = res.characteristics[i]
// 检查特征值是否具有 read 属性为 false
if (characteristic.properties.indicate) {
// 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
_this.setData({ characteNotifyId: characteristic.uuid })
wx.setStorageSync('characteNotifyId', characteristic.uuid)
break // 找到符合条件的特征值后,结束循环
}
}
},
fail: (error) => {
console.log('get notify CharacteId error: ', error)
}
})
},
// ios read characteId
getReadCharacteIdIos() {
wx.getBLEDeviceCharacteristics({
deviceId: this.data.currentDeviceid,
serviceId: this.data.readServiceId,
success: (res) => {
// 遍历特征值列表
console.log('res.characteristics read : ', res.characteristics)
for (let i = 0; i < res.characteristics.length; i++) {
let characteristic = res.characteristics[i]
// 检查特征值是否具有 read 属性为 false
if (characteristic.properties.read) {
// 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
this.setData({
characteReadId: characteristic.uuid
})
wx.setStorageSync('characteReadId', characteristic.uuid)
break // 找到符合条件的特征值后,结束循环
}
}
}
})
},
// ios write characteId
getWriteCharacteIdIos() {
wx.getBLEDeviceCharacteristics({
deviceId: this.data.currentDeviceid,
serviceId: this.data.writeServiceId,
success: (res) => {
// 遍历特征值列表
console.log('res.characteristics write : ', res.characteristics)
for (let i = 0; i < res.characteristics.length; i++) {
let characteristic = res.characteristics[i]
// 检查特征值是否具有 read 属性为 false
if (characteristic.properties.write) {
// 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
this.setData({
characteWriteId: characteristic.uuid
})
wx.setStorageSync('characteWriteId', characteristic.uuid)
// break // 找到符合条件的特征值后,结束循环
}
if (characteristic.properties.notify) {
// 当找到 read 属性为 false 的特征值时,设置 writeId 为该特征值的 UUID
this.setData({
characteNotifyId: characteristic.uuid
})
wx.setStorageSync('characteNotifyId', characteristic.uuid)
}
wx.navigateTo({
url: '/pages/xxx/xxx'
})
wx.hideToast()
}
}
})
},
第七步:这时候已经跳转到对应页面了,在页面onLoad里开启监听,后面蓝牙发送设备到小程序可以实时监听到值
async onLoad(options) {
// 监听蓝牙发送到小程序的数据
await wx.onBLECharacteristicValueChange((res) => {
console.log('characteristicis: ', res.value)
console.log('转换后的值: ', this.ab2hex(res.value))
this.setData({ fromBlueToolsData: this.ab2hex(res.value) })
// this.setData({ fromBlueToolsData: res.value })
})
await wx.readBLECharacteristicValue({
deviceId: wx.getStorageSync('deviceId'),
serviceId: wx.getStorageSync('readServiceId'),
characteristicId: wx.getStorageSync('characteReadId'),
success: (res) => {
console.log('read data is: ', res)
},
fail: (error) => {
console.log('read error, error message is: ', error)
}
})
await wx.notifyBLECharacteristicValueChange({
state: true,
type: 'notification', // 根据你蓝牙的特征值来选择类型
deviceId: wx.getStorageSync('deviceId'),
serviceId: wx.getStorageSync('notifyServiceId'),
characteristicId: wx.getStorageSync('characteNotifyId'),
success: (res) => {
console.log('notify success, success message is: ', res)
},
fail: (error) => {
console.log('notify error, error message is: ', error)
this.setData({ fromBlueToolsData: '' })
}
})
},
// 16 进制到 10进制
ab2hex(buffer) {
let hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
},
第八步:测试读写,看蓝牙串口与小程序是否有通信
// 写入数据
writeTap() {
console.log('-----------------start write action----------------------------')
console.log('inputValue: ', this.data.inputValue)
let data = this.data.inputValue
if (data.length === 0) {
wx.showModal({ title: '提示', content: '请输入要发送的数据' })
return
}
wx.writeBLECharacteristicValue({
deviceId: wx.getStorageSync('deviceId'),
serviceId: wx.getStorageSync('writeServiceId'),
characteristicId: wx.getStorageSync('characteWriteId'),
value: this.string2buffer(data), // 数据转换发送
success (res) {
console.log('writeBLECharacteristicValue success', res)
this.setData({ inputValue: '' })
},
fail: (error) => {
console.log('write error, error message is: ', error)
}
})
},
string2buffer(hexString) {
hexString = hexString.replace(/^0x/, '');
const bytes = new Uint8Array(hexString.length / 2);
for (let i = 0; i < hexString.length; i += 2) {
bytes[i / 2] = parseInt(hexString.substring(i, i + 2), 16);
}
console.log('写入的buffer:', bytes.buffer)
return bytes.buffer;
},
// input输入值
onWriteInput(evt) {
const { value } = evt.detail
this.setData({ inputValue: value })
},
最终测试后在ios与安卓上能够与蓝牙串口进行正常通信,完结!