uniapp 微信小程序蓝牙业务

//CRC蓝牙校验
var crc16 = function(buffer) {
	var crc = 0x0000;
	var odd;
	for (var i = 0; i < buffer.length; i++) {
		crc ^= (buffer[i] << 8)
		for (var j = 0; j < 8; j++) {
			odd = crc & 0x8000;
			crc = crc << 1;
			if (odd) {
				crc = crc ^ 0x1021
			}
		}
	}
	var hi = ((crc & 0xFF00) >> 8); //高位置
	var lo = (crc & 0x00FF); //低位置
	var crcArr = []
	crcArr.push(hi)
	crcArr.push(lo)
	crc &= 0xFFFF
	return crcToString(crcArr, true)
};

//转为大写String
function crcToString(arr, isReverse) {
	if (typeof isReverse == 'undefined') {
		isReverse = true;
	}
	var hi = arr[0],
		lo = arr[1];
	return padLeft((isReverse ? hi + lo * 0x100 : hi * 0x100 + lo).toString(16).toUpperCase(), 4, '0');
};

var padLeft = function(s, w, pc) {
	if (pc == undefined) {
		pc = '0';
	}
	for (var i = 0, c = w - s.length; i < c; i++) {
		s = pc + s;
	}
	return s;
};

//十六进制字符串转字节数组
function hexString2Bytes(str) {
	var pos = 0;
	var len = str.length;
	if (len % 2 != 0) {
		return null;
	}
	len /= 2;
	var arrBytes = new Array();
	for (var i = 0; i < len; i++) {
		var s = str.substr(pos, 2);
		var v = parseInt(s, 16);
		arrBytes.push(v);
		pos += 2;
	}
	return arrBytes;
}

function buf2hex(buffer) {
	return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('')
}

function buf2string(buffer) {
	var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x)
	var str = ''
	for (var i = 0; i < arr.length; i++) {
		str += String.fromCharCode(arr[i])
	}
	return str
}

//字符串转ArrayBuffer
function hexStringToArrayBuffer(str) {
	if (!str) {
		return new ArrayBuffer(0);
	}
	var buffer = new ArrayBuffer(20);
	let dataView = new DataView(buffer)
	let ind = 0;
	for (var i = 0; i < str.length; i += 2) {
		let code = parseInt(str.substr(i, 2), 16)
		dataView.setUint8(ind, code)
		ind++
	}
	return buffer;
}

function randomString(e) {
	let randomStr = '';
	e = e || 32;
	var t = "123456789",
		a = t.length,
		n = "";
	for (var i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a));
	randomStr = n
	console.log('当前随机数:' + randomStr);
	return n
}

function zeroString(num) {
	num = num || 32;
	var n = "";
	for (var i = 0; i < num; i++) n += '0';
	return n
}

data() {
		return {
			searching: false, //当前是否在搜索蓝牙
			currentBleDeviceName: 'JJ21040000', //当前连接的蓝牙设备名称 线上版本加a
			connectedBleDevice: {
				connectStatus: '连接中', //连接状态
				batPrecent: '获取中' //当前连接的蓝牙设备
			},
			currentBleDevice: null, //当前使用的蓝牙设备
			connected: false, //当前是否连接蓝牙设备
			devicesList: [], //当前搜索到的蓝牙设备
			currentBleDeviceMac: '000000000421', //当前设备mac
		}
	},

	onLoad() {
		//监听蓝牙适配器状态变化事件
		wx.onBluetoothAdapterStateChange(function(res) {
			console.log("监听蓝牙res: ", res);
			that.searching = res.discovering

			if (!res.available) {
				that.searching = res.false
			}
		})

		//监听寻找到新设备的事件
		wx.onBluetoothDeviceFound(function(devices) {
			console.log('devices', devices)
			//剔除重复设备,兼容不同设备API的不同返回值
			var isnotexist = true
			if (devices.deviceId) {
				if (devices.advertisData) {
					devices.advertisData = buf2hex(devices.advertisData)
				} else {
					devices.advertisData = ''
				}
				for (var i = 0; i < that.devicesList.length; i++) {
					if (devices.deviceId == that.devicesList[i].deviceId) {
						isnotexist = false
					}
				}
				if (isnotexist) {
					that.devicesList.push(devices)
				}
				if (isnotexist && that.currentBleDeviceName == devices.devices[0].localName) {

					that.currentBleDevice = devices.devices[0]

					that.currentBleDevice.mac = that.currentBleDevice.advertisData.slice(4, 16)

					console.log('currentBleDevice', that.currentBleDevice)

					that.connectBleDevice()

				}
			} else if (devices.devices) {
				if (devices.devices[0].advertisData) {
					devices.devices[0].advertisData = buf2hex(devices.devices[0].advertisData)
				} else {
					devices.devices[0].advertisData = ''
				}
				for (var i = 0; i < that.devicesList.length; i++) {
					if (devices.devices[0].deviceId == that.devicesList[i].deviceId) {
						isnotexist = false
					}
				}
				if (isnotexist && devices.devices[0].localName) {
					that.devicesList.push(devices.devices[0])
				}
				if (isnotexist && that.currentBleDeviceName == devices.devices[0].localName) {

					that.currentBleDevice = devices.devices[0]

					that.currentBleDevice.mac = that.currentBleDevice.advertisData.slice(4, 16)

					console.log('currentBleDevice', that.currentBleDevice)

					that.connectBleDevice()

				}
			} else if (devices[0]) {
				if (devices[0].advertisData) {
					devices[0].advertisData = buf2hex(devices[0].advertisData)
				} else {
					devices[0].advertisData = ''
				}
				for (var i = 0; i < devices_list.length; i++) {
					if (devices[0].deviceId == that.devicesList[i].deviceId) {
						isnotexist = false
					}
				}
				if (isnotexist) {
					that.devicesList.push(devices[0])
				}
				if (isnotexist && that.currentBleDeviceName == devices.devices[0].localName) {

					that.currentBleDevice = devices.devices[0]

					that.currentBleDevice.mac = that.currentBleDevice.advertisData.slice(4, 16)

					console.log('currentBleDevice', that.currentBleDevice)

					that.connectBleDevice()

				}
			}


			// //匹配连接指定设备
			// for (var i = 0; i < that.devicesList.length; i++) {
			// 	if (that.currentBleDeviceName == that.devicesList[i].localName) {
			// 		that.currentBleDevice = that.devicesList[i]
			// 	}
			// }

			// if (that.currentBleDevice != null && that.currentBleDevice.localName != undefined) {
			// 	var arrayMac = that.currentBleDevice.advertisData.slice(4, 16);
			// 	that.currentBleDevice.mac = arrayMac

			// 	console.log('currentBleDevice', that.currentBleDevice)

			// 	that.connectBleDevice()
			// }

		})

		//小程序切后台断开蓝牙
		wx.onAppHide(function(res) {
			// wx.closeBLEConnection({
			// 	deviceId: that.currentBleDevice.deviceId,
			// 	success(res) {
			// 		console.log(res)
			// 	}
			// })
		})



		//监听低功耗蓝牙连接状态的改变事件
		wx.onBLEConnectionStateChange(function(res) {
			console.log(res.connected)
			that.connected = res.connected
		})

		//监听低功耗蓝牙设备的特征值变化事件
		wx.onBLECharacteristicValueChange(function(res) {
			console.log('notify接收到数据:')
			console.log(res)
			if (res.characteristicId.indexOf('F502') != -1) {
				var arrayBuffer = res.value
				var hexArray = Array.prototype.slice.call(new Uint8Array(arrayBuffer)).map(function(item,
					index, ary) {
					return (parseInt(item)).toString(16);
				})
				var type = hexArray[0] + hexArray[1]
				switch (type) {
					case '11':
						that.handshakeNotify(hexArray)
						break;
					case '12':
						that.checkBleDeviceNotify(hexArray)
						break;
					case '411':
						that.batteryStatusNotify(hexArray)
						break;
					case '312':
						that.unlockBleDeviceNotify(hexArray)
						break;
					default:
						console.log(hexArray)
				}

			}
		})

	}

methods: {
	//搜索蓝牙
	searchBle() {
		var that = this
		if (!that.searching) {
			//关闭蓝牙模块
			wx.closeBluetoothAdapter({
				complete: function(res) {
					wx.openBluetoothAdapter({
						success: function(res) {
							//获取本机蓝牙适配器状态
							wx.getBluetoothAdapterState({
								success: function(res) {}
							})
							//开始搜寻附近的蓝牙外围设备
							wx.startBluetoothDevicesDiscovery({
								allowDuplicatesKey: false,
								success: function(res) {
									that.searching = true
									that.devicesList = []
								}
							})
						},
						fail: function(res) {
							wx.showModal({
								title: '提示',
								content: '请检查手机蓝牙是否打开',
								showCancel: false,
								success: function(res) {
									that.searching = false
								}
							})
						}
					})
				}
			})
		} else {
			//停止搜寻附近的蓝牙外围设备
			wx.stopBluetoothDevicesDiscovery({
				success: function(res) {
					that.searching = false
				}
			})
		}
	},

	//连接蓝牙
	connectBleDevice() {
		var that = this
		//停止搜寻附近的蓝牙外围设备
		wx.stopBluetoothDevicesDiscovery({
			success: function(res) {
				console.log(res)
				that.searching = false
			}
		})

		//连接低功耗蓝牙设备
		wx.createBLEConnection({
			deviceId: that.currentBleDevice.deviceId,
			success: function(res) {
				that.getBleServices()
			},
			fail: function(res) {
				wx.showModal({
					title: '提示',
					content: '连接失败',
					showCancel: false
				})
			}
		})
	},

	//获取蓝牙设备所有服务(service)
	getBleServices() {
		var that = this
		var buffer = new ArrayBuffer(that.currentBleDevice.deviceId)

		//获取蓝牙设备所有服务(service)
		wx.getBLEDeviceServices({
			deviceId: that.currentBleDevice.deviceId,
			success: function(res) {
				console.log('services', res.services)
				that.services = res.services

				//获取蓝牙设备某个服务中所有特征值(characteristic)
				wx.getBLEDeviceCharacteristics({
					deviceId: that.currentBleDevice.deviceId,
					serviceId: res.services[1].uuid,
					success: function(res) {
						console.log('characteristics', res.characteristics)
						that.characteristics = res.characteristics

						//启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值
						wx.notifyBLECharacteristicValueChange({
							state: true,
							deviceId: that.currentBleDevice.deviceId,
							serviceId: that.services[1].uuid,
							characteristicId: that.characteristics[1].uuid,
							success: function(res) {
								that.handshake()
							}
						})
					}
				})
			}
		})
	},

	//发送arrayBuffer指令
	sendBleCommand: function(arrayBuffer) {
		var that = this
		if (that.connected) {
			console.log('deviceId: ' + that.currentBleDevice.deviceId)
			console.log('serviceId: ' + that.services[1].uuid)
			console.log('characteristicId: ' + that.characteristics[0].uuid)
			//向低功耗蓝牙设备特征值中写入二进制数据
			wx.writeBLECharacteristicValue({
				deviceId: that.currentBleDevice.deviceId,
				serviceId: that.services[1].uuid,
				characteristicId: that.characteristics[0].uuid,
				value: arrayBuffer,
				success: function(res) {
					console.log(res)
					console.log('发送成功')
				},
				fail: function(res) {
					console.log('fail')
					console.log(res)
				}
			})
		} else {
			wx.showModal({
				title: '提示',
				content: '蓝牙已断开',
				showCancel: false,
				success: function(res) {
					that.searching = false
				}
			})
		}
	},

	//电池电量
	batteryStatusNotify(hexArray) {
		this.connectedBleDevice.batPrecent = (parseInt(hexArray[7], 16) * 20) + '%'
	},

	//握手指令
	handshake() {
		var command = '0101' + randomString() + '0000'
		console.log('命令内容: ' + command)
		var arrayBuffer = hexStringToArrayBuffer(command)
		console.log('转换arrayBuffer: ', arrayBuffer)

		this.sendBleCommand(arrayBuffer)
	},
	//握手指令回调
	handshakeNotify(hexArray) {
		// wx.showToast({
		// 	title: '握手成功',
		// 	icon: 'success',
		// 	duration: 1000
		// })

		this.checkBleDevice()
	},

	//检验指令
	checkBleDevice() {
		var that = this
		var buffer = new ArrayBuffer(20);
		var dataView = new DataView(buffer)
		// console.log('随机字符串', randomStr)			
		var beginCommand = '0102'
		var endCommand = '0000'
		var ind = 0;

		for (var i = 0; i < beginCommand.length; i += 2) {
			let code = parseInt(beginCommand.substr(i, 2), 16)
			dataView.setUint8(ind, code)
			ind++
		}

		for (var i = 0; i < randomStr.length; i += 2) {
			let code = randomStr.substr(i, 2)
			var str = code + that.currentBleDevice.mac
			const byteData = hexString2Bytes(str)
			let tempCrc = crc16(byteData)
			// console.log('计算crc的hex值', tempCrc)
			// console.log('计算crc的高位值', tempCrc.slice(2, 4))			
			dataView.setUint8(ind, parseInt(tempCrc.slice(2, 4), 16))

			ind++
		}

		for (var i = 0; i < endCommand.length; i += 2) {
			let code = parseInt(endCommand.substr(i, 2), 16)
			dataView.setUint8(ind, code)
			ind++
		}
		console.log('转换arrayBuffer: ', buffer)
		this.sendBleCommand(buffer)
	},

	//检验指令回调
	checkBleDeviceNotify(hexArray) {
		console.log(hexArray)
		if ('1' == hexArray[2]) {
			this.connectedBleDevice.connectStatus = '已连接'
			wx.showToast({
				title: '连接成功',
				icon: 'success',
				duration: 1000
			})
		} else {
			wx.showToast({
				title: '连接失败',
				icon: 'fail',
				duration: 1000
			})
		}

	},

	//开锁指令 传入仓位 num
	unlockBleDevice(code) {
		console.log("code: ", code);

		if (code == undefined) {
			code = '00'
		} else {
			code = code + ''
			if (code.length == 1) {
				code = '0' + code
			}
		}

		console.log("仓位code: ", code);

		var command = '0312' + code + zeroString(34)

		console.log('命令内容: ' + command)
		var arrayBuffer = hexStringToArrayBuffer(command)
		console.log('转换arrayBuffer: ', arrayBuffer)

		this.sendBleCommand(arrayBuffer)

	},

	//开锁指令回调
	unlockBleDeviceNotify(hexArray) {
		console.log(hexArray)
		if ('1' == hexArray[2]) {
			wx.showToast({
				title: '开锁成功',
				icon: 'success',
				duration: 1000
			})
		} else {
			wx.showToast({
				title: '开锁失败',
				icon: 'fail',
				duration: 1000
			})
		}
	},
}

你可能感兴趣的:(uniapp 微信小程序蓝牙业务)