UNI-APP 连接蓝牙

实现了开启蓝牙——搜索附近蓝牙——获取对应读写特征值服务——断开蓝牙全过程。

<template>
	<view class='content_box'>
		<view class="pay_box">
			<button class="btn" type="primary" @click="initBlue">开启蓝牙</button>
			<!-- <button class="btn" type="primary" @click="stopBluetooth">停止搜索外围</button> -->
			<button class="btn" type="primary" @click="findBlue">搜寻附近蓝牙</button>
		</view>
		<view>
			<scroll-view scroll-y class="box">
				<view class="itemContent" v-for="(item,index) in bleDevs" :key='index' @click="connetBlue(item)">
					<view>
						<text>设备名称: {{ item.name }}</text>
					</view>
					<view>
						<text>设备id: {{ item.deviceId }}</text>
					</view>
				</view>
			</scroll-view>
		</view>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				bleDevs: [],//蓝牙列表
			}
		},
		onload() {
			// 初始化蓝牙设备
			// this.initBlue();
		},
		methods: {
			// 初始化蓝牙设备
			initBlue() {
				let vm = this;
				uni.openBluetoothAdapter({ // 初始化蓝牙、判断是否开启蓝牙
					success: function(res) {
						vm.getState();
					},
					fail: res => {
						uni.showModal({
							title: '提示',
							content: '蓝牙初始化失败,请到设置打开蓝牙',
							showCancel: false
						})
					}
				})
			},
			//获取本机蓝牙适配器状态
			getState() {
				uni.getBluetoothAdapterState({ //获取本机蓝牙适配器状态
					success(res) {
						uni.showModal({
							title: '提示',
							content: '蓝牙初始化成功,获取本机蓝牙适配器状态成功',
							showCancel: false
						})
					},
					fail(err) {
						uni.showModal({
							title: '提示',
							content: '查看手机蓝牙是否打开',
							showCancel: false
						})
					}
				})
			},
			// 停止搜索外围蓝牙设备
			// stopBluetooth() {
			// 	uni.stopBluetoothDevicesDiscovery({
			// 		success: e => {
			// 			uni.showModal({
			// 				title: '提示',
			// 				content:  e.errMsg,
			// 				showCancel: false
			// 			})
			// 		},
			// 		fail: err => {
			// 			console.log("停止搜索失败",err);
			// 		}
			// 	});
			// },
			//获取蓝牙设备信息
			findBlue() {
				var vm = this;
				uni.showLoading({
					title: '正在加载',
					icon: 'loading',
				});
				uni.startBluetoothDevicesDiscovery({
					interval: 0, //上报设备的间隔
					allowDuplicatesKey: false,//是否允许重复上报
					success: (res) => {
						//获取所有的蓝牙设备列表
						vm.getBlue();
					},
					fail: err => {
						uni.showToast({
							title: '搜索蓝牙设备失败',
							icon: 'none',
							duration: 1000                                                            
						})
					}
				})
			},
			// 获取设备列表
			getBlue() {
				var vm = this;
				setTimeout(() => {
					uni.hideLoading();
					uni.getBluetoothDevices({
						success: function(res) {
							// 过滤掉name为未知设备的设备
							var bluetoothArr = [];
							res.devices.forEach((obj) => {
								if(obj.name !== "未知设备") {
									bluetoothArr.push(obj);
								}
							})
							vm.bleDevs = bluetoothArr;
						},
						fail: function() {
							uni.showToast({
								title: '搜索蓝牙设备失败',
								icon: 'none',
								duration: 1000                                                            
							})
						},
					});
					
				},2000)
			},
			// 连接蓝牙设备
			connetBlue(item) {
				// uni.setStorageSync("name", item);
				// // 跳转到成功页面
				// uni.navigateTo({
				// 	url:'/pages/blueSuccess/blueSuccess',
				// })
				
				let vm = this;
				uni.showLoading({
					title: "连接中,请稍等",
					mask: true,
				});
				uni.createBLEConnection({
					deviceId: item.deviceId, //设备的 id
					success(res) {
						console.log("连接蓝牙成功",res);
						uni.setStorageSync("name", item);
						uni.hideLoading();
						uni.showToast({
							title: item.name + "蓝牙连接成功",
							icon: "none",
							duration: 1000
						});
						// 跳转到成功页面
						uni.navigateTo({
							url:'/pages/blueSuccess/blueSuccess',
						})
					},
					fail(res) {
						uni.hideLoading();
						uni.showToast({
							title: item.name + "蓝牙连接失败",
							icon: "none",
						});
					}
				});
			},
		}
	}
</script>
<style lang="scss" scoped>
	.blueList {
		width: 100%;
		height: 100px;
		background-color: #ffd5de;
	}
	.itemContent{
		width: 80%;
		height: 60px;
		border-radius:  10px;
		background-color: #e0ffff;
		text-align: center;
		margin: 15px auto;
		line-height: 30px;
	}
	.content_box {
		width: 100%;
		.pay_box {
			display: flex;
			flex-wrap: wrap;
			justify-content: space-evenly;
			margin-top: 30rpx;
		}
	
		.btn {
			background-color: #007aff;
			padding: 20rpx;
			box-sizing: border-box;
			font-size: 26rpx;
			border-radius: 60rpx;
			width: 28%;
			margin-top: 10px;
		}
	}
</style>
<template>
<view>
	<view class="pay_box">
		<!-- <button class="btn" type="primary" @click="connetBlue">连接蓝牙</button> -->
		<button class="btn" type="primary" @click="getServiceId">获取服务</button>
		<button class="btn" type="primary" @click="closeBlue">断开蓝牙</button>
	</view>
	<bushOver v-if='showBtn'  @childEvent="getWrite" ></bushOver>
	<view class='displayFrame'>
		<view>蓝牙表号:{{ servicesDataName  }}</view>
		<scroll-view  scroll-y="true" class="scroll-Y" >
			<view class="dataWidth">{{ ServerSuccess }} </view>
			<view class="dataWidth">{{ stateSuccess }} </view>
			<view class="dataWidth">{{ notifyStateSuccess }}</view>
			<view class="dataWidth">{{ writeStateSuccess }}</view>
			<view class="dataWidth">{{ cardInfo }}</view>
			<view class="dataWidth">{{ agoData }}</view>
			<view class="dataWidth">{{ closeBlueData }}</view>
		</scroll-view>
	</view>
</view>
</template>
<script>
	import bushOver from '../component/bushOver.vue'
	export default {
		components: {
			bushOver,
		},
		data() {
			return {
				ServicesData: {}, //传过来的deviceId
				servicesDataName:'',
				getCharateristicId: '', //特征值的charateristicId(uuid)
				getServiceIdData:'', // 服务的serviceId(uuid)
				hexStringData: '',
				showBtn:false, //抄读和充值是否显示
				stateSuccess:'', //特征值数据
				notifyStateSuccess:'', //notify数据
				writeStateSuccess:'',//写入数据
				cardInfo:'', //解析后的结果
				ServerSuccess:'', //获取服务成功数据
				agoData:'',//接收的原始数据
				closeBlueData:'',//断开蓝牙
				closeNotify:true,//关闭监听
				errCode: {
					10000:	'未初始化蓝牙适配器',
					10001:	'当前蓝牙适配器不可用',
					10002:	'没有找到指定设备',
					10003:	'连接失败',
					10004:	'没有找到指定服务',
					10005:	'没有找到指定特征值',
					10006:	'当前连接已断开',
					10007:	'当前特征值不支持此操作',
					10008:	'其余所有系统上报的异常',
					10009:	'Android 系统特有,系统版本低于 4.3 不支持 BLE',
					10010:	'已连接',
					10011:	'配对设备需要配对码',
					10012:	'连接超时',
					10013:	'连接 deviceId 为空或者是格式不正确',
				}
			}
		},
		onLoad(options) {
			// 接收跳转传递的参数
			let vm = this;
			this.ServicesData = uni.getStorageSync('name');
			const name = uni.getStorageSync('name').name;
			this.servicesDataName = name.replace(/[a-zA-Z]/g, '');
			// 充值成功后调用写入函数
			if(options.source === 'pay') {
				uni.getStorage({
					key:'payData',
					success: (res) => {
						let data = res.data;
						vm.getWrite(data);
						uni.removeStorage('payData');
					}
				});
				
			}
		},
		onUnload() {
			this.closeNotify = false;
			// 关闭监听状态
			this.getNotify();
			// 断开蓝牙
			this.closeBlue();
		},
		methods: {
			// 连接蓝牙设备
			// connetBlue() {
			// 	let vm = this;
			// 	let item = uni.getStorageSync("name");
			// 	uni.showLoading({
			// 		title: "连接中,请稍等",
			// 		mask: true,
			// 	});
			// 	uni.createBLEConnection({
			// 		deviceId: item.deviceId, //设备的 id
			// 		success(res) {
			// 			console.log("连接蓝牙成功",res);
						
			// 			uni.hideLoading();
			// 			uni.showToast({
			// 				title: item.name + "蓝牙连接成功",
			// 				icon: "none",
			// 				duration: 1000
			// 			});
			// 		},
			// 		fail(res) {
			// 			uni.hideLoading();
			// 			uni.showToast({
			// 				title: item.name + "蓝牙连接失败",
			// 				icon: "none",
			// 			});
			// 		}
			// 	});
			// },
			
			// // 获取蓝牙的所有服务
			getServiceId() {
				let vm = this;
				let item = vm.ServicesData;
				setTimeout(() => {//获取数据可能有延迟
					uni.getBLEDeviceServices({
						deviceId: item.deviceId, //蓝牙设备 id
						success(res) {
							const useData = 'D973F2E0';
							let chooseData = res.services;
							// 选择合适的uuid
							chooseData.forEach( item => {
								let data = item.uuid.split('-');
								if(data[0] === useData) {
									vm.getServiceIdData = item.uuid;
									uni.setStorageSync('serId',vm.getServiceIdData);
								}
							})
							console.log("获取服务成功", res);
							vm.ServerSuccess = '获取服务成功,数据为' + vm.getServiceIdData;
							// 获取蓝牙特征
							vm.getCharacteId(vm.getServiceIdData);
						},
						fail(err) {
							console.log("获取服务失败", err);
							vm.ServerSuccess = '获取服务失败' + err.errCode;
						}
					});
				},1000);
			},			
			//获取蓝牙特征
			getCharacteId(data) {
				let vm = this;
				let serID = vm.ServicesData;  
				uni.getBLEDeviceCharacteristics({
					deviceId: serID.deviceId,
					serviceId: vm.getServiceIdData,
					success: (res) => {
						console.log("获取特征值成功",res);
						vm.showBtn = true;
						var characteristicsData = res.characteristics;
						// 判断服务都支持什么操作
						characteristicsData.forEach(item => {
							vm.stateSuccess = '获取特征值成功,数据为' + item.uuid;
							uni.setStorageSync('gChargeId',item.uuid);
							// 读操作
							// if(item.properties.read) {
							// 	uni.readBLECharacteristicValue({
							// 		deviceId:serID.deviceId,
							// 		serviceId:vm.getServiceIdData,
							// 		characteristicId:item.uuid,
							// 		success(res) {
							// 			console.log("读成功",res);
							// 		}
							// 	})
							// }
							// 写操作
							if(item.properties.write) {
								vm.getCharateristicId = item.uuid;
							}
							// notify操作
							if (item.properties.notify || item.properties.indicate) {
								vm.getNotify();
							}
						});
					},
					fail(err) {
						vm.stateSuccess = '获取蓝牙特征值失败' + err.errCode;
						console.log("获取蓝牙特征值失败",err.errCode);
					},
				});
			},
			// notify变化
			getNotify() {
				let vm = this;
				let serID = vm.ServicesData;
				vm.getServiceIdData = uni.getStorageSync('serId');
				vm.getCharateristicId = uni.getStorageSync('gChargeId');
				uni.notifyBLECharacteristicValueChange({
					deviceId:serID.deviceId,
					serviceId:vm.getServiceIdData,
					characteristicId: vm.getCharateristicId,
					state:vm.closeNotify,
					success(res) {
						console.log("开启订阅数据监听成功",res);
						vm.notifyStateSuccess = '开启订阅数据监听成功';
						vm.hexStringData = '';
						uni.onBLECharacteristicValueChange(characteristic => {
							console.log('接收原始数据:', characteristic);
							// 获取到的所以数据转化拼接
							var array = new Uint8Array(characteristic.value);
							var hexString = Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
							vm.hexStringData += hexString;
							// 判断最后两位是否为16
							if (vm.hexStringData.substr(vm.hexStringData.length - 2, 2) == "16"){
								// 将数据转化为大写
								let data = vm.hexStringData.toUpperCase();
								vm.methodFn(data);
								 
							}
						});
					},
					fail(err) {
						console.log("开启订阅数据监听失败",err);
						vm.notifyStateSuccess = '开启订阅数据监听失败' + err.errCode
					}
				});
			},
			// 监听回调
			methodFn(val) {
				console.log("val",val);
				let vm = this;
				let params = {
				"data":val,
				"psw":44,
				"sign":"36576fb294"
				};
				let hash = vm.$md5(JSON.stringify(params) + '1350fee134a4ad0cae4da9a8');
				// #ifdef APP-PLUS
					uni.request({
						method: 'POST',
						url:'http://test.yourmeter.cn/umeter/openApi/cmd/readCmd',
						data: params,
						header: {
							'appId':2,
							'sign':hash,
						},
						success(res) {
							console.log('获取卡信息成功',res.data.msg);
							vm.agoData = '接收的原始数据为:' + val;
							vm.cardInfo = '数据解析结果为:' + res.data.msg;
						},
						fail(err) {
							vm.agoData = '接收的原始数据为:' + val;
							vm.cardInfo = '数据解析结果为:' + err;
						}
					});
				// #endif

				// #ifdef MP-WEIXIN
				uni.request({
					method: 'POST',
					url:'http://test.yourmeter.cn/umeter/openApi/cmd/readCmd',
					data: params,
					header: {
						'appId':2,
						'sign':hash,
					},
					success(res) {
						console.log('获取卡信息成功',res.data.msg);
						vm.agoData = '接收的原始数据为:' + val;
						vm.cardInfo = '数据解析结果为:' + res.data.msg;
					},
					fail(err) {
						vm.agoData = '接收的原始数据为:' + val;
						vm.cardInfo = '数据解析结果为:' + err;
					}
				});
				// #endif
				// #ifdef H5
				uni.request({
					method: 'POST',
					url:'/api/openApi/cmd/readCmd',
					data: params,
					header: {
						'appId':2,
						'sign':hash,
					},
					success(res) {
						if(res.data.msg === 'OK') {
							console.log('获取卡信息成功',res.data.msg);
							vm.agoData = '接收的原始数据为:' + val;
							vm.cardInfo = '数据接收成功:' + res.data.msg;
						}
					},
					fail(err) {
						vm.agoData = '接收的原始数据为:' + val;
						vm.cardInfo = '数据解析结果为:' + err;
					}
				})
				// #endif
			},
				
			//字符串函数
			ab2hex: function (buffer) {
				var hexArr = Array.prototype.map.call(
				new Uint8Array(buffer),
				function (bit) {
					return ('00' + bit.toString(16)).slice(-2)
				}
				)
				return hexArr.join('');
			},
			// 写入
			getWrite(data) {
				console.log("写入data",data);
				let vm = this;
				vm.hexStringData = '';
				let serID = vm.ServicesData;
				var hex = 'FEFEFE'+ data;
				var buffer = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
				  return parseInt(h, 16)
				}))
				buffer = buffer.buffer;
				let pos = 0;
				let bytes = buffer.byteLength;
				while (bytes > 0) {
				  var tmpBuffer;
				  if (bytes > 20) {
					tmpBuffer = buffer.slice(pos, pos + 20);
					pos += 20;
					bytes -= 20;
				  } else {
					tmpBuffer = buffer.slice(pos, pos + bytes);
					pos += bytes;
					bytes -= bytes;
				  }
				  vm.getServiceIdData = uni.getStorageSync('serId');
				  vm.getCharateristicId = uni.getStorageSync('gChargeId');
				  uni.writeBLECharacteristicValue({
					// 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
					deviceId:serID.deviceId,
					// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
					serviceId:vm.getServiceIdData,
					// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
					characteristicId:vm.getCharateristicId,
					// 这里的value是ArrayBuffer类型
					value: tmpBuffer,
					success(res) {
						console.log("蓝牙写入成功",res);
						vm.writeStateSuccess = '命令发送成功,数据:' + hex;
					},
					fail(err) {
						vm.writeStateSuccess = '命令发送失败,原因:' + err.errCode;
						console.log("蓝牙写入失败",err.errCode);
					}
				  })
				};
			},
				
			// 断开蓝牙
			closeBlue() {
				let vm = this;
				uni.closeBLEConnection({
					deviceId: vm.ServicesData.deviceId, //设备的 id
					success(res) {
						uni.showToast({
							title:"蓝牙断开成功",
							icon: "none",
							duration: 2000
						});
						vm.closeBlueData = "蓝牙断开成功";
						console.log("蓝牙断开成功",res);
					}
				})
			},
		}
		
	}	
</script>

<style lang="scss">
	.pay_box {
		width: 100%;
		display: flex;
		flex-wrap: wrap;
		justify-content: space-evenly;
		margin-top: 30rpx;
	}
		
	.btn {
		background-color: #007aff;
		padding: 20rpx;
		box-sizing: border-box;
		font-size: 26rpx;
		border-radius: 60rpx;
		width: 30%;
		height: 40px;
		margin-top: 10px;
	}
	.displayFrame{
		width: 90%;
		height: 400px;
		margin: 80px auto 0;
		border: 3px solid #000000;
		.dataWidth{
			width: 90%;
			display:inline-block;
			white-space: pre-wrap; 
			word-wrap: break-word;
			height: auto;
		}
	}
</style>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值