微信小程序蓝牙连接门锁真实有效代码

以前用小程序开发过蓝牙,项目遗憾没上线,打算把代码公布出来,帮到一些新手,此代码兼容ios和安卓


const tokenUtil = require('../../../utils/token.js')
const ips = require('../../../utils/ips.js')
const req = require('../../../utils/req.js')
function inArray(arr, key, val) {
for (let i = 0; i < arr.length; i++) {
if (arr[i][key] === val) {
return i;
}
}
return -1;
}
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
}
function base64_encode(str) { // 编码,配合encodeURIComponent使用
var c1, c2, c3;
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var i = 0, len = str.length, strin = '';
while (i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if (i == len) {
strin += base64EncodeChars.charAt(c1 >> 2);
strin += base64EncodeChars.charAt((c1 & 0x3) << 4);
strin += "==";
break;
}
c2 = str.charCodeAt(i++);
if (i == len) {
strin += base64EncodeChars.charAt(c1 >> 2);
strin += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
strin += base64EncodeChars.charAt((c2 & 0xF) << 2);
strin += "=";
break;
}
c3 = str.charCodeAt(i++);
strin += base64EncodeChars.charAt(c1 >> 2);
strin += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
strin += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
strin += base64EncodeChars.charAt(c3 & 0x3F)
}
return strin
}
Page({
data: {
imageURL: "/assets/images/searchgateway.png",
houseId: '',
dev_sn: '',
msg: '正在识别,请稍后',
//上行数据(发送给服务器的),
//下行数据(发送给蓝牙设备的)
upData: '',
downData: '',
//蓝牙模块处理数据
devices: [],
deviceId: "",
connected: false,
chs: [],
//蓝牙可读可写可noticefy
canWrite: false,
canNotify: false,
setInter0: "",
//蓝牙消息定时器
timestamp: 0,
temStr: '',
setInter: '',
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
var _this = this;
var houseId = options.houseId;
var wifissid = options.wifissid;
var wifiPassword = options.wifiPassword;
console.info("bluetoothgatewaysearch houseId :>>>" + houseId)
console.info("bluetoothgatewaysearch wifissid :>>>" + wifissid)
console.info("bluetoothgatewaysearch wifiPassword :>>>" + wifiPassword)
_this.setData({
houseId: houseId,
wifissid: wifissid,
wifiPassword: wifiPassword
})
// 调取接口获取下行数据
// 先关闭一下蓝牙设备
wx.closeBluetoothAdapter();
// 重新开始获取蓝牙设备
console.log(" ================start get bleDeves================")
this.openBluetoothAdapter();
// 循环函数,开始不停得遍历蓝牙设备列表,查询指定设备ID,如GN开头,并将设备信息存入设备列表
console.log(" ================start for bleDeves================")
},
getDownData: function() {
var _this = this;
var data = {
deviceSn: _this.data.deviceSn,
wifi_ssid: _this.data.wifissid,
wifi_password: _this.data.wifiPassword,
canWrite: false,
canNotify: false
};
//查询房间详情
req.requestToken(ips.GetGatewayNet, data).then((res) => {
if (res.code == 0) {
_this.setData({
downData: res.data.ble_data,
})
//链接蓝牙设备
_this.createBLEConnection();
//下发数据给蓝牙
_this.data.setInter0 = setInterval(function() {
//判断是否已经连接成功了蓝牙
console.log("===============================每隔500ms就判断是否已经设置好蓝牙================================")
if (_this.data.canWrite && _this.data.canNotify) {
clearInterval(_this.data.setInter0)
console.log("===============================clearInterval setInter0 ================================")
setTimeout(function() {
_this.sendDataToBle()
}, 500)
}
}, 200)
} else {
wx.showModal({
title: '系统提示',
content: res.msg,
})
return false;
}
}).catch((errMsg) => {
//错误提示信息
return false;
});
},
// 开启手机蓝牙适配
openBluetoothAdapter() {
var _this = this;
wx.openBluetoothAdapter({
success: (res) => {
_this.setData({
message: '蓝牙初始化成功,正在连接...',
})
_this.startBluetoothDevicesDiscovery()
},
fail: (res) => {
//console.log('res', JSON.stringify(res))
if (res.errCode === 10001) {
wx.showModal({
title: '系统提示',
content: '初始蓝牙失败,请开启蓝牙和定位功能!',
})
_this.setData({
message: '初始蓝牙失败,请开启蓝牙和定位功能',
})
//监听蓝牙适配器状态变化事件
wx.onBluetoothAdapterStateChange(function(res) {
console.log('onBluetoothAdapterStateChange', res)
if (res.available) {
_this.startBluetoothDevicesDiscovery()
}
})
}
},
complete: (res) => {
console.log("初始化蓝牙适配器完成")
}
})
},
// 获取本机蓝牙适配状态
getBluetoothAdapterState() {
wx.getBluetoothAdapterState({
success: (res) => {
console.log('getBluetoothAdapterState', res)
if (res.discovering) {
this.onBluetoothDeviceFound()
} else if (res.available) {
this.startBluetoothDevicesDiscovery()
}
}
})
},
// 开始搜索
startBluetoothDevicesDiscovery() {
if (this._discoveryStarted) {
return
}
this._discoveryStarted = true
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
interval: 0,
success: (res) => {
console.log('寻找新设备启动success,开始执行回调函数', res)
//寻找到新设备的事件的回调函数
this.onBluetoothDeviceFound()
// console.info("当前devices:" + this.data.devices)
},
fail: (res) => {
console.log('寻找新设备启动fail,开始执行回调函数', res)
},
complete: (res) => {
console.log('寻找新设备启动无论失败还是成功,都将执行此方法', res)
},
})
},
// 停止蓝牙搜索,搜索连接到设备后停止搜索
stopBluetoothDevicesDiscovery() {
wx.stopBluetoothDevicesDiscovery()
console.log('>>> 停止蓝牙搜索...');
},
// 寻找到新设备的事件的回调函数,循环函数
onBluetoothDeviceFound() {
var _this = this;
wx.onBluetoothDeviceFound((res) => {
res.devices.forEach(device => {
if (!device.name && !device.localName) {
return
}
//开始正则匹配蓝牙名字,搜索特定设备
var re = device.name.substring(0, 2);
// console.info("[re] ...." + JSON.stringify(re))
if (re == 'CW') {
const foundDevices = _this.data.devices
// console.info("[foundDevices] ...." + JSON.stringify(foundDevices))
const idx = inArray(foundDevices, 'deviceId', device.deviceId)
const data = {}
// 去重
if (idx === -1) {
data[`devices[${foundDevices.length}]`] = device
} else {
data[`devices[${idx}]`] = device
}
_this.setData(data)
}
})
})
// console.log(" devices >>>" + JSON.stringify(_this.data.devices))
},
// 开始连接低功耗蓝牙设备。
// 若小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,
// 可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需进行搜索操作。
createBLEConnection(e) {
var _this = this;
// const mac = "19:07:02:17:24:4C"
// const mac = "2755F278-6644-C1D2-0378-892B7B169A41"
const deviceId = _this.data.deviceId;
console.log("===>>>开始连接低功耗蓝牙,deviceId " + deviceId)
// const name = ds.name
wx.createBLEConnection({
deviceId,
success: (res) => {
this.setData({
message: '连接蓝牙成功,正在数据交互...',
connected: true,
deviceId: deviceId
})
//获取蓝牙设备所有服务(service)。
this.getBLEDeviceServices(deviceId)
// 该方法回调中可以用于处理连接意外断开等异常情况
wx.onBLEConnectionStateChange(function(res) {
console.log(`=========device ${res.deviceId} state has changed, connected: ${res.connected}=========`)
if (res.connected == false) {
_this.setData({
message: '操作超时,硬件设备已断开蓝牙...',
connected: false,
})
}
})
}
})
//关闭搜索蓝牙设备,因为太耗电
this.stopBluetoothDevicesDiscovery()
},
// 获取蓝牙设备所有服务(service)
getBLEDeviceServices(deviceId) {
var _this = this;
// console.log("===>>>开始获取蓝牙设备所有服务(service)")
wx.getBLEDeviceServices({
deviceId,
success: (res) => {
// console.log(">>> 当前蓝牙设备服务个数 " + res.services.length)
console.log("【当前蓝牙设备服务数据】" + JSON.stringify(res))
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary && res.services[i].uuid == "0000FFF0-0000-1000-8000-00805F9B34FB") {
console.log("【当前的UUID是:>>>>>>>>>>>>>>>>>>>】" + JSON.stringify(res))
_this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);
return
}
}
}
})
},
// 获取蓝牙设备某个服务中所有特征值(characteristic)。
getBLEDeviceCharacteristics(deviceId, serviceId) {
var _this = this;
wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
console.log('serviceId >>>' + serviceId + '获取特征值成功,返回数据 res >>>' + JSON.stringify(res))
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i]
console.info("===>>>开始遍历特征值,当前item :" + JSON.stringify(item))
//设备的特征值支持 读的特征值,就读取特征值的二进制数据值
if (item.properties.read) {
console.log("serviceId[" + serviceId + "], 第(" + i + ")特征值可 Read, 执行success ")
wx.readBLECharacteristicValue({
deviceId,
serviceId,
characteristicId: item.uuid,
})
}
//设备的特征值支持 写的特征值,就向低功耗蓝牙设备特征值中写入二进制数据
if (item.properties.write) {
console.log("serviceId[" + serviceId + "], 第(" + i + ")特征值可 Write, 执行success ")
_this.setData({
canWrite: true
})
this._deviceId = deviceId
this._serviceId = serviceId
this._characteristicId = item.uuid
}
//设备的特征值支持 notify 或者 indicate 才可以成功调用。
if (item.properties.notify || item.properties.indicate) {
console.log("serviceId[" + serviceId + "], 第(" + i + ")特征值可Notify, 执行success ")
_this.setData({
canNotify: true
})
wx.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId: item.uuid,
state: true,
success: function(res) {
console.log(">>>>>>>>>>启用 Notify功能成功,res " + JSON.stringify(res));
},
fail: function(res) {
console.log(">>>>>>>>>>启用Notify功能失败,res " + JSON.stringify(res));
}
})
}
}
// console.log('_this.data.canWrite123 >>>' + _this.data.canWrite)
// console.log('_this.data.canNotify123 >>>' + _this.data.canNotify)
},
fail(res) {
console.error('getBLEDeviceCharacteristics', JSON.stringify(res))
}
})
// 监听低功耗蓝牙设备的特征值变化事件。
// 必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification。
wx.onBLECharacteristicValueChange((characteristic) => {
if (!_this.data.canWrite || !_this.data.canNotify) {
return;
}
console.info("================================ ble characteristic value change ================================================================");
var nowTimetamps = new Date().getTime();
console.info("nowTimetamps > > > > > > > > > > > > > > > > > > > > > >" + nowTimetamps);
console.info("_this.data.timestamp > > > > > > > > > > > > > > > > > > > > > >" + _this.data.timestamp);
var oldTimetamps = 0;
//首次
if (_this.data.timestamp == 0) {
oldTimetamps = nowTimetamps;
} else {
oldTimetamps = _this.data.timestamp;
}
var diff = nowTimetamps - oldTimetamps;
var tem = ab2hex(characteristic.value);
console.info("diff tims > > > > > > > > > > > > > > > > > > > > > >" + diff + "ms");
//2包数据之间间隔大于500ms,则认为是2条不同得数据得
if (diff > 500) {
_this.setData({
upData: tem,
temStr: tem,
timestamp: nowTimetamps
})
_this.startSetTimeout();
} else {
//2包之间数据间隔小于500ms,则认为是同一条数据,分包接收了,先关掉定时发送器,然后进行数据累加
_this.endSetTimeout();
var temStr = _this.data.temStr;
var newTem = temStr + tem;
_this.setData({
upData: newTem,
temStr: newTem,
timestamp: nowTimetamps
})
//开启定时发送器
_this.startSetTimeout();
}
})
},
//监听蓝牙设备发送的消息定时器
startSetTimeout: function() {
var _this = this;
//将计时器赋值给setInter,过250ms将发送数据给服务器
_this.data.setInter = setTimeout(
function() {
console.log('【当前小程序收到网关需要发送至服务器的数据字节长度】 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >' + _this.data.temStr.length / 2);
console.log('【当前小程序收到网关需要发送至服务器的数据 temStr】 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >' + _this.data.temStr);
var fdStart = _this.data.temStr.indexOf("08");
if (fdStart != 0) {
console.log('【当前小程序收到网关数据为冗杂数据,程序中断,继续等待网关数据】 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >');
return false;
}
//上传数据给服务器
_this.uploadData();
//清空缓存和重置时间标识
_this.setData({
temStr: "",
timestamp: 0
})
}, 500);
},
//清除发送消息给服务器的定时器
endSetTimeout: function() {
var _this = this;
clearTimeout(_this.data.setInter)
console.log('clear setInter > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >');
},
// 将获取到的下行数据(页面初始化时获取到的数据包)
// 发送给蓝牙网关,由蓝牙网关自行处理逻辑
sendDataToBle() {
var _this = this;
var getData = _this.data.downData;
//按协议组装数据,并分包发送
var base64ToArrayBuffer = wx.base64ToArrayBuffer(getData)
let dataView = new DataView(base64ToArrayBuffer)
console.log(" send data to ble > -> -> -> -> -> -> -> -> -> -> -> -> > -> -> -> -> -> --> -> -> -> -> -> -> -> -> -> ->" + getData)
console.info("deviceId > -> -> -> -> -> -> -> -> -> -> -> -> > -> -> -> -> -> --> -> -> -> -> -> -> -> -> -> ->" + _this._deviceId)
console.info("serviceId > -> -> -> -> -> -> -> -> -> -> -> -> > -> -> -> -> -> --> -> -> -> -> -> -> -> -> -> ->" + _this._serviceId)
console.info("characteristicId > -> -> -> -> -> -> -> -> -> -> -> -> > -> -> -> -> -> --> -> -> -> -> -> -> -> -> -> ->" + _this._characteristicId)
for (var i = 0; i < base64ToArrayBuffer.length; i++) {
dataView.setUint8(i, base64ToArrayBuffer.charAt(i).charCodeAt())
}
let pos = 0;
let bytes = base64ToArrayBuffer.byteLength;
while (bytes > 0) {
let tmpBuffer;
if (bytes > 20) {
tmpBuffer = base64ToArrayBuffer.slice(pos, pos + 20);
pos += 20;
bytes -= 20;
} else {
tmpBuffer = base64ToArrayBuffer.slice(pos, pos + bytes);
pos += bytes;
bytes -= bytes;
}
setTimeout(
function () {
wx.writeBLECharacteristicValue({
deviceId: _this._deviceId,
serviceId: _this._serviceId,
characteristicId: _this._characteristicId,
value: tmpBuffer,
})
}, 100
)
}
},
//上行数据,将网关数据通过小程序,传输给服务器
uploadData: function () {
var _this = this;
var deviceSn = _this.data.deviceSn;
var ble_up_data = _this.data.upData;
var houseId = _this.data.houseId;
console.info("up deviceSn > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >" + deviceSn)
console.info("up ble_up_data > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >" + ble_up_data)
var data = {
deviceSn: deviceSn,
ble_data: ble_up_data
}
req.requestToken(ips.PostGatewayNet, data).then((res) => {
console.log("upload ble data res > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >" + JSON.stringify(res))
if (res.code == 0) {
_this.onUnload();
wx.navigateTo({
url: '../../../pages/device/bluetoothpost/bluetoothgatewayadd?deviceSn='+deviceSn +"&houseId="+houseId,
})
} else {
// wx.showModal({
// title: '系统信息',
// content: res.msg,
// })
return false;
}
}).catch((errMsg) => { });
},
// 关闭低功耗蓝牙连接
closeBLEConnection() {
wx.closeBLEConnection({
deviceId: this.data.deviceId
})
this.setData({
connected: false,
chs: [],
canWrite: false,
})
console.info("close BLEConnection > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >")
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function() {
clearInterval(this.data.setInter0)
this.endSetTimeout();
this.closeBLEConnection();
this.stopBluetoothDevicesDiscovery();
},
/**
* 用户点击链接蓝牙
*/
linkBle: function(e) {
var _this = this;
var bleName = e.target.dataset.devicesn.name;
var deviceSn = bleName.substring(2);
var deviceId = e.target.dataset.devicesn.deviceId;
_this.setData({
deviceSn: deviceSn,
deviceId: deviceId
})
//获取下行数据,并下发
_this.getDownData();
}
})

 

1.本站所有资源收集于互联网,仅用于学习和研究,若用于违法,与本站无关,仅限学习交流请勿用于商业用途。 2.会员在本站下载的VIP素材后,只拥有使用权,著作权归原作者及49资源网所有。 3.VIP素材,未经合法授权,会员不得以任何形式发布、传播、复制、转售该素材,否则一律封号处理。 4.如果素材损害你的权益,请联系客服删除。
49资源网 » 微信小程序蓝牙连接门锁真实有效代码

发表评论