uniapp连接蓝牙硬件及硬件数据传输(公用类封装,简单易用)

图片来自网络

1、定义相关业务状态

蓝牙连接设备前,首先会想到一些各种的状态,比如等待连接、搜索设备中、已连接、连接失败等等一系列的状态监听,所以这里先定义好相关状态,以便业务逻辑判断。

export const BLUE_STATE = {
    
    
	/**
	 * 蓝牙不可用
	 */
	UNAVAILABLE: {
    
    
		label: '请检查手机蓝牙是否开启',
		code: -1
	},
	/**
	 * 等待连接蓝牙
	 */
	READY: {
    
    
		label: '等待连接蓝牙',
		code: 10000
	},
	/**
	 * 等待连接蓝牙(重启蓝牙适配器)
	 */
	READYAGAIN: {
    
    
		label: '等待连接蓝牙',
		code: 10001
	},
	/**
	 * 正在搜索设备...
	 */
	SCANING: {
    
    
		label: '正在搜索设备...',
		code: 12000
	},
	/**
	 * 正在传输数据...
	 */
	TRANSMITDATA: {
    
    
		label: '正在传输数据...',
		code: 13000
	},
	/**
	 * 数据传输完成
	 */
	LOCKDATA: {
    
    
		label: '数据已锁定',
		code: 11000
	},
	/**
	 * 已连接蓝牙
	 */
	CONNECTSUCCESS: {
    
    
		label: '已连接蓝牙',
		code: 200
	},
	/**
	 * 写入特征已准备就绪
	 */
	WRITEREADY: {
    
    
		label: '写入特征已准备就绪',
		code: 201
	},
	/**
	 * 蓝牙连接已断开
	 */
	DISCONNECT: {
    
    
		label: '蓝牙连接已断开',
		code: 500
	},
	/**
	 * 连接失败, 请重试!
	 */
	CONNECTFAILED: {
    
    
		label: '连接失败, 请重试!',
		code: -2
	},
	/**
	 * 微信无位置权限
	 */
	NOLOCATIONPERMISSION: {
    
    
		label: '您关闭了微信位置权限,请前往手机设置页打开权限后重试',
		code: 10007
	},
	/**
	 * 当前系统版本过低,请升级后重试!
	 */
	VERSIONLOW: {
    
    
		label: '当前系统版本过低,请升级后重试!',
		code: 10009
	},
	/**
	 * 系统异常,请稍后重试!
	 */
	SYSTEMERROR: {
    
    
		label: '系统异常,请稍后重试!',
		code: 10008
	}
}

2、封装蓝牙控制器监听函数

可自行拓展监听器

export const BleController = {
    
    
	/**
	 * 蓝牙连接状态
	 */
	addConnectStateListen(callBack) {
    
    
		this.public.bleConnectStateCallBack = callBack
	},
	/**
	 * 传输数据监听
	 */
	addTransferDataListen(callBack) {
    
    
		this.public.bleProgressDataCallBack = callBack
	},
	/**
	 * 数据传输完成监听
	 */
	addLockDataListen(callBack) {
    
    
		this.public.bleLockDataCallBack = callBack
	},
	/**
	 * 写入特征值状态
	 */
	addWriteStateListen(callBack) {
    
    
		this.public.bleWriteStateCallBack = callBack
	},
	// 连接状态
	connectStateListen(params) {
    
    
		if (this.public.bleConnectStateCallBack) {
    
    
			this.public.bleConnectStateCallBack(params)
		}
	},
	// 数据传输中
	transferDataListen(params) {
    
    
		if (this.public.bleTransferDataCallBack) {
    
    
			this.public.bleTransferDataCallBack(params)
		}
	},
	// 测量完成
	lockDataListen(params) {
    
    
		if (this.public.bleLockDataCallBack) {
    
    
			this.public.bleLockDataCallBack(params)
		}
	},
	// 写入特征值状态
	writeStateListen(params) {
    
    
		if (this.public.bleWriteStateCallBack) {
    
    
			this.public.bleWriteStateCallBack(params)
		}
	},

	public: {
    
    
		bleConnectStateCallBack: null,
		bleTransferDataCallBack: null,
		bleLockDataCallBack: null,
		bleWriteStateCallBack: null,
	}
}

图片来自网络

3、封装蓝牙扫描&连接函数

整个流程比较长,具体API使用可查看uniapp官方文档

let bleControl = null
let bleConnectDeviceID = null
let currentDevice = {
    
    }
let writeData = {
    
    
	device: {
    
    }, 
	serviceID: '',
	characteristicID: ''
}
export const Blue = {
    
    
	/**
	 * 蓝牙连接状态:200-> 已连接;-1 ->未连接
	 */
	connectState: -1,
	
	// 开始蓝牙设备扫描
	start() {
    
    
		bleControl = BleProtocol
		this._lastLockData = ""
		if(bleConnectDeviceID) {
    
     // 设备已连接
			this.connectState = 200
			bleControl.connectStateListen(BLUE_STATE.CONNECTSUCCESS);
			return
		};
		bleControl.connectStateListen(BLUE_STATE.READY)
		// 打开蓝牙适配器
		uni.openBluetoothAdapter({
    
    
			success: (res) => {
    
    
				this.startBluetoothDevicesDiscovery()
			},
			fail: (res) => {
    
    
				console.error('打开蓝牙适配器失败:', res);
				if (res.errCode === 10001) {
    
    
					bleControl.connectStateListen(BLUE_STATE.UNAVAILABLE)
				}
				// Android 系统特有,系统版本低于 4.3 不支持 BLE
				if(res.errCode === 10009) {
    
    
					bleControl.connectStateListen(BLUE_STATE.VERSIONLOW)
				}
				if(res.errCode === 10008) {
    
    
					bleControl.connectStateListen(BLUE_STATE.SYSTEMERROR)
				}
			},
			complete: () => {
    
    
				// 监听蓝牙适配器状态
				uni.onBluetoothAdapterStateChange(res => {
    
    
					console.log('蓝牙适配器状态:', res);
					if (res.available) {
    
    
						this._isDiscovering = res.discovering
						bleControl.connectStateListen(BLUE_STATE.READYAGAIN)
						this.startBluetoothDevicesDiscovery()
					}else {
    
    
						// 蓝牙模块未开启
						bleControl.connectStateListen(BLUE_STATE.UNAVAILABLE)
					}
				})
			}
		})
	},

	// 关闭蓝牙连接,关闭状态监听,初始化状态
	stop() {
    
    
		if (bleConnectDeviceID) {
    
    
			uni.closeBLEConnection({
    
    
				deviceId: bleConnectDeviceID
			})
		}
		writeData = {
    
    }
		bleConnectDeviceID = null
		this.connectState = -1
		this._isDiscovering = false
		uni.closeBluetoothAdapter()
		uni.offBluetoothAdapterStateChange()
		uni.offBLEConnectionStateChange()
		uni.stopBluetoothDevicesDiscovery()
	},
	// 停止蓝牙扫描
	stopBluetoothDevicesDiscovery() {
    
    
		uni.stopBluetoothDevicesDiscovery()
	},
	// 开始蓝牙扫描
	startBluetoothDevicesDiscovery() {
    
    
		if (this._isDiscovering) return
		this._isDiscovering = true
		
		uni.startBluetoothDevicesDiscovery({
    
    
			allowDuplicatesKey: true,
			success: (res) => {
    
    
				bleControl.connectStateListen(BLUE_STATE.SCANING)
				this.onBluetoothDeviceFound()
			},
			fail: (res) => {
    
    
				console.log('位置失败--', res);
				if(res.errCode === -1 && (res.errno === 1509008 || res.errno === 1509009)) {
    
    
					this.stop()
					bleControl.connectStateListen(BLUE_STATE.NOLOCATIONPERMISSION)
				}
			}
		})
	},
	// 搜索附近设备
	onBluetoothDeviceFound() {
    
    
		uni.onBluetoothDeviceFound(res => {
    
    
			res.devices.forEach(device => {
    
    
				// device = {
    
    
				// 	RSSI: -50,
				// 	advertisData: ArrayBuffer(19),
				// 	advertisServiceUUIDs: Array(2),
				// 	connectable: true,
				// 	deviceId: "EE59532DF324-4SFSD-34635D-BB893-76SGSDFV",
				// 	localName: "shebeimingcheng",
				// 	name: "shebeimingcheng", 
				// }
				if (device.name !== 'shebeimingcheng') return
				
				let abHex = this.ab2hex(device.advertisData)
				let mac = this.ab2hex(device.advertisData.slice(2, 8), ':').toUpperCase()
				device.macAddr = mac
				// 根据自己的设备修改
				if (abHex.length == 38) {
    
    
					this.stopBluetoothDevicesDiscovery()
					this.createBLEConnection(device)
				}
			})
		})
	},
	// 创建蓝牙连接
	createBLEConnection(device) {
    
    
		if (bleConnectDeviceID == null) {
    
    
			bleConnectDeviceID = device.deviceId
			uni.createBLEConnection({
    
    
				deviceId: device.deviceId,
				success: res=> {
    
    
					currentDevice = device
					this.connectState = 200
					// 蓝牙连接成功,上报设备信息
					bleControl.connectStateListen({
    
    
						...BLUE_STATE.CONNECTSUCCESS,
						deviceInfo: {
    
    ...device}
					})
					this.getBLEDeviceServices(device)
					this.onBLEConnectionStateChange()
				},
				fail: (err)=> {
    
    
					bleControl.connectStateListen(BLUE_STATE.CONNECTFAILED)
				},
			})
		}
	},
	// 监听连接状态
	onBLEConnectionStateChange() {
    
    
		uni.onBLEConnectionStateChange(res => {
    
    
			console.log('蓝牙连接状态: ', res);
			if (!res.connected) {
    
    
				bleControl.connectStateListen(BLUE_STATE.DISCONNECT)
				this.stop()
			}
		});
	},
	// 获取设备服务
	getBLEDeviceServices(device) {
    
    
		uni.getBLEDeviceServices({
    
    
			deviceId: device.deviceId,
			success: res=> {
    
    
				for (let i = 0; i < res.services.length; i++) {
    
    
					let uuid = res.services[i].uuid
					if (uuid.indexOf("FFF0") == 0) {
    
    
						this.getBLEDeviceCharacteristics(device, uuid)
					}
				}
			},
		})
	},
	// 获取设备特征值
	getBLEDeviceCharacteristics(device, serviceID) {
    
    
		uni.getBLEDeviceCharacteristics({
    
    
			deviceId: device.deviceId,
			serviceId: serviceID,
			success: res=> {
    
    
				for (let i = 0; i < res.characteristics.length; i++) {
    
    
					let item = res.characteristics[i]
					// 该特征值是否支持 write 操作
					if (item.properties.write) {
    
     
						if (item.uuid.indexOf("FFF1") == 0) {
    
    
							writeData = {
    
    
								device: device, 
								serviceID: serviceID,
								characteristicID: item.uuid
							}
							bleControl.connectStateListen(BLUE_STATE.WRITEREADY);
						}
					}
					// 该特征值是否支持 notify或indicate 操作
					if (item.properties.notify || item.properties.indicate) {
    
     
						if (item.uuid.indexOf("FFF4") == 0) {
    
    
							this.notifyBLECharacteristicValueChange(device, serviceID, item.uuid);
						}
					}
				}
			}
		})
	},
	// 监听特征值变化(设备数据变化)
	notifyBLECharacteristicValueChange(device, serviceID, characteristicID) {
    
    
		uni.notifyBLECharacteristicValueChange({
    
    
			deviceId: device.deviceId,
			serviceId: serviceID,
			characteristicId: characteristicID,
			state: true,
			success: res=> {
    
    
				this.onBLECharacteristicValueChange()
			},
		})
	},


	onBLECharacteristicValueChange() {
    
    
		uni.onBLECharacteristicValueChange(res=> {
    
    
			let value = this.ab2hex(res.value)
			this.resolvingData(value)
		})
	},
	
	// 发送指令给设备
	sendOrder(byteArray) {
    
    
		let checksum = 0x00
		// byteArray = [FD, 03, 00, 01, 00]
		// 计算异或和
		for(let i = 0; i < byteArray.length - 1; i++) {
    
    
			checksum ^= `0x${
      
      byteArray[i]}`
		}
		this.deviceMode = mode
		let sumStr = checksum.toString(16).toLocaleUpperCase()
		let hex = byteArray.join('') + sumStr // FD03000100C4
		
		let typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function(h) {
    
    
			return parseInt(h, 16)
		}))
		
		let order = typedArray.buffer
		
		if(!writeData.device.deviceId){
    
    
			this.stop()
			return
		}
		
		this.writeBLECharacteristicValue(order, writeData.device, writeData.serviceID, writeData.characteristicID)
	},
	// 写入特征值
	writeBLECharacteristicValue(order, device, serviceID, characteristicID) {
    
    
		uni.writeBLECharacteristicValue({
    
    
			deviceId: device.deviceId,
			serviceId: serviceID,
			characteristicId: characteristicID,
			value: order,
			success: (res)=> {
    
    
				console.log("特征值写入成功 --", res)
				bleControl.writeStateListen({
    
    
					code: res.errCode === 0 ? 200 : -1,
				})
			},
			fail: (res)=> {
    
    
				console.log("特征值写入失败 --", res)
				bleControl.writeStateListen({
    
    
					code: -1,
				})
			}
		})
	},

	// ArrayBuffer转16进制字符串
	ab2hex(buffer, split='') {
    
    
		var hexArr = Array.prototype.map.call(new Uint8Array(buffer), function(bit) {
    
    
			return ('00' + bit.toString(16)).slice(-2)
		})
		return hexArr.join(split)
	},
	
	// TODO 根据自己实际业务解析数据
	resolvingData(res) {
    
    
		if (this._lastLockData == res) return
		this._lastLockData = res
		
		const valArr = []
		if (res.length >= 20) {
    
    
			for (let i = 0, len = 10; i < len; i++) {
    
    
				valArr[i] = res.substr(i * 2, 2)
			}
			// console.log(valArr);
		}
	},
}

4、业务组件使用蓝牙

Blue.start();

BleController.addConnectStateListen(state => {
    
    
	console.log('蓝牙连接状态', state.code);
});

BleController.addTransferDataListen(info => {
    
    
	console.log('数据传输中', info);
});

BleController.addWriteStateListen(res => {
    
    
	console.log('特征值写入状态', res);
})

如果觉得有用随手点个赞吧,谢谢
关注我,不定时分享技术干货~

猜你喜欢

转载自blog.csdn.net/weixin_45295253/article/details/128982215