uniapp实现蓝牙通信

uniapp实现读取蓝牙连接蓝牙等操作(vue2+js)直接一把梭版

参考博客地址:https://juejin.cn/post/7093171532318375950

界面demo如下

在这里插入图片描述
在这里插入图片描述

代码部分

<template>
	<view>
		<view class="BuuetoothServiceList">
			<text>蓝牙设备列表</text>
		</view>
		<scroll-view scroll-y class="box">
			<view class="item" v-for="item in blueDeviceList" @click="connect(item)">
				<view>
					<text>id: {{ item.deviceId }}</text>
				</view>
				<view>
					<text>RSSI:{{item.RSSI}}</text>
				</view>
				<view>
					<text>name: {{ item.name }}</text>
				</view>
			</view>
		</scroll-view>
		<button @click="initBluetooth()"
			style="width: 9rem;height: 3rem;background-color: rgb(138, 145, 159);">①蓝牙连接</button>
		<view class="BuuetoothServiceList">
			<text>蓝牙服务列表</text>
		</view>
		<scroll-view scroll-y class="box">
			<view class="item" v-for="item in sevicesList">
				<view>
					<text user-select="true">uuid: {{ item.uuid }}</text>
				</view>
			</view>
		</scroll-view>
		<view class="BuuetoothServiceList">
			<text>蓝牙特征值列表</text>
		</view>
		<scroll-view scroll-y class="box">
			<view class="item" v-for="item in eigenvalueList">
				<view>
					<text user-select="true">uuid: {{ item.uuid }}</text>
				</view>
			</view>
		</scroll-view>

		<!-- <uni-easyinput type="text" v-model="formData.name" placeholder="请输入姓名" /> -->
		<view class="btnBox"><input type="text"
				style="width: 75%;height: 3rem;background-color: rgb(246, 244, 241);margin-left: 5%;border-radius: 20rpx;box-shadow:0 0 8rpx #000;margin-top: 20rpx;"
				placeholder="请输入蓝牙服务表中的uuid" v-model="serviceUuid" />
			<view class="clearInput">
				<icon type="clear" @click="clearIptA()"></icon>
			</view>
		</view>

		<view class="btnBox">
			<!-- <button @click="discovery()"
				style="width: 12rem;height: 3rem;margin-top: 1rem;background-color: rgb(138, 145, 159);">②搜索附近蓝牙设备</button>
			<button @click="getServices()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color: rgb(138, 145, 159);">③获取蓝牙服务</button> -->

			<button @click="getCharacteristics()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">②获取特征值</button>
			<!-- <button @click="notify()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">③开启消息监听</button> -->
		</view>
		<view class="btnBox">
			<input type="text"
				style="box-shadow:0 0 8rpx #000;width: 75%;height: 3rem;background-color: rgb(246, 244, 241);margin-left: 5%;border-radius: 20rpx;margin-top: 20rpx;"
				placeholder="开始监听之前,请输入需要监听的特征值" v-model="eigenvalue" />
			<view class="clearInput">
				<icon type="clear" @click="clearIptB()"></icon>
			</view>
		</view>

		<view class="btnBox">
			<button @click="notify()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">③开启消息监听</button>
			<input type="text"
				style="width: 75%;height: 3rem;background-color: rgb(246, 244, 241);margin-left: 5%;border-radius: 20rpx;box-shadow:0 0 8rpx #000;margin-top: 20rpx;"
				placeholder="请填写需要发送的内容" v-model="sendMessage" />
			<!-- <uni-icons type="icon-youxi" size="30"></uni-icons> -->
			<view class="clearInput">
				<icon type="clear" @click="clearIptC()"></icon>
			</view>
			<!-- <text style="background-color: aqua;height: 3rem;line-height: 3rem;margin-left: 2.5%;"></text> -->
			<button @click="send()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">④发送数据</button>
			<button @click="read()"
				style="width: 10rem;height: 3rem;margin-top: 1rem;background-color:rgb(138, 145, 159);">⑤读取数据</button>
		</view>
		<view class="msg_x" style="background-color: rgb(246, 244, 241);">
			<view class="msg_txt">
				监听到的内容:{{ message }}
			</view>
			<view class="msg_hex">
				监听到的内容(十六进制):{{ messageHex }}
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				blueDeviceList: [],
				deviceId: null,
				sevicesList: [],
				serviceUuid: null,
				eigenvalueList: [],
				eigenvalue: null,
				message: "",
				messageHex: "",
				sendMessage: ""
			}
		},
		methods: {
			initBluetooth() {
				let that = this
				uni.openBluetoothAdapter({
					success(res) {
						console.log('初始化蓝牙成功')
						console.log(res)
						//开始搜索蓝牙设备
						that.discovery()
						//获取蓝牙服务
						console.log('调用服务预备');
						that.getServices()
					},
					fail(err) {
						console.log('初始化蓝牙失败')
						console.error(err)
					}
				})
			},
			// 开始搜索蓝牙设备
			discovery() {
				let that = this
				uni.startBluetoothDevicesDiscovery({
					//services:['FFE0'],
					success(res) {
						console.log('开始搜索')
						// 开启监听回调
						//uni.onBluetoothDeviceFound(that.found(res))
						uni.onBluetoothDeviceFound(function(res) {
							console.log(res, '---')
							if (res.devices[0].name == "iCore Server") {
								that.blueDeviceList.push(res.devices[0])
							}

						})
					},
					fail(err) {
						console.log('搜索失败')
						console.error(err)
					}
				})
			},
			//连接蓝牙设备
			connect(data) {
				console.log(data, '---+++___')
				this.deviceId = data.deviceId
				let that = this
				uni.createBLEConnection({
					deviceId: this.deviceId,
					success(res) {
						uni.showToast({
							icon: 'success',
							title: '蓝牙连接成功'
						})
						console.log('连接成功')
						console.log(res)
						that.stopDiscovery()
						//获取蓝牙服务
						that.getServices()
					},
					fail(err) {
						uni.showToast({
							icon: 'error',
							title: '蓝牙连接失败'
						})
						console.log('连接失败')
						console.log(err)
					}
				})
			},
			//停止搜索
			stopDiscovery() {
				uni.stopBluetoothDevicesDiscovery({
					success(res) {
						console.log('停止成功')
						console.log(res)
					},
					fail(err) {
						console.log('停止失败')
						console.error(err)
					}
				})
			},
			//获取蓝牙服务
			getServices() {
				console.log('开始获取蓝牙服务');
				let that = this;
				uni.getBLEDeviceServices({
					deviceId: that.deviceId, // 设备ID,在上一步【4】里获取
					success(res) {
						that.sevicesList = res.services
						console.log(that.sevicesList, '=================')
					},
					fail(err) {
						console.error(err)
					}
				})
			},
			//获取特征值
			getCharacteristics() {
				if (this.serviceUuid == null) {
					console.log('----')
					uni.showToast({
						icon: 'error',
						title: '请在上面输入框中输入uuid'
					})
				}
				let that = this
				//console.log(this.serviceUuid, 'serviceUuid')
				uni.getBLEDeviceCharacteristics({
					deviceId: that.deviceId, // 设备ID,在【4】里获取到
					serviceId: that.serviceUuid, // 服务UUID,在【6】里能获取到
					success(res) {
						that.eigenvalueList = res.characteristics
						console.log(res)
					},
					fail(err) {
						console.error(err)
					}
				})
			},
			notify() {
				let that = this
				uni.notifyBLECharacteristicValueChange({
					state: true, // 启用 notify 功能
					deviceId: that.deviceId, // 设备ID,在【4】里获取到
					serviceId: that.serviceUuid, // 服务UUID,在【6】里能获取到
					characteristicId: that.eigenvalue, // 特征值,在【7】里能获取到
					success(res) {
						console.log(res)

						// 接受消息的方法
						that.listenValueChange()
					},
					fail(err) {
						console.log(err)
					}
				})
			},
			// ArrayBuffer转16进度字符串示例
			ab2hex(buffer) {
				const hexArr = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {
						return ('00' + bit.toString(16)).slice(-2)
					}
				)
				return hexArr.join('')
			},
			// 将16进制的内容转成我们看得懂的字符串内容
			hexCharCodeToStr(hexCharCodeStr) {
				var trimedStr = hexCharCodeStr.trim();
				var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
				var len = rawStr.length;
				if (len % 2 !== 0) {
					alert("存在非法字符!");
					return "";
				}
				var curCharCode;
				var resultStr = [];
				for (var i = 0; i < len; i = i + 2) {
					curCharCode = parseInt(rawStr.substr(i, 2), 16);
					resultStr.push(String.fromCharCode(curCharCode));
				}
				return resultStr.join("");
			},
			listenValueChange() {
				let that = this
				uni.onBLECharacteristicValueChange(res => {
					// 结果
					console.log(res, '这是监听成功的回调');
					// 结果里有个value值,该值为 ArrayBuffer 类型,所以在控制台无法用肉眼观察到,必须将该值转换为16进制
					let resHex = that.ab2hex(res.value)
					//console.log(resHex)​;
					that.messageHex = resHex
					// 最后将16进制转换为ascii码,就能看到对应的结果
					let result = that.hexCharCodeToStr(resHex);
					that.message = String(result)
					console.log(String(result),'000000')
				})
			},

			//发送数据
			send() {
				// 向蓝牙设备发送一个0x00的16进制数据
				let msg = this.sendMessage
				console.log(msg,'$$$$$$$$$$$$$$$$$$$$$$$$$$');
				if (this.sendMessage == "") {
					uni.showToast({
						icon: 'error',
						title: '需要发送的内容不能为空'
					})
					return
				}


				const buffer = new ArrayBuffer(msg.length)
				const dataView = new DataView(buffer)
				// dataView.setUint8(0, 0)

				for (var i = 0; i < msg.length; i++) {
					dataView.setUint8(i, msg.charAt(i).charCodeAt())
				}

				let that = this

				uni.writeBLECharacteristicValue({
					deviceId: that.deviceId,
					serviceId: that.serviceUuid,
					characteristicId: that.eigenvalue,
					value: buffer,
					success(res) {
						console.log('writeBLECharacteristicValue success', res.errMsg)
						uni.showToast({
							title: 'write指令发送成功'
						})
					},
					fail(err) {
						console.error(err,"写入指令发送失败")
						uni.showToast({
							title: 'write指令发送失败',
							icon: 'error'
						})
					}
				})
			},
			//读取数据
			read() {
				let that = this
				uni.readBLECharacteristicValue({
					deviceId: that.deviceId,
					serviceId: that.serviceUuid,
					characteristicId: that.eigenvalue,
					success(res) {
						console.log(res,"数据读取成功")
						uni.showToast({
							title: 'read指令发送成功'
						})
					},
					fail(err) {
						console.error(err)
						uni.showToast({
							title: 'read指令发送失败',
							icon: 'error'
						})
					}
				})
			},
			//清除输入框中数据
			//清除蓝牙表中的uuid
			clearIptA() {
				this.serviceUuid = ""
			},
			//清除监听特定值的
			clearIptB() {
				this.eigenvalue = ""
			},
			//发送内容的输入框
			clearIptC() {
				this.sendMessage = ""
			}
		},
		onLoad() {

		}
	}
</script>

<style>
	.box {
		width: 100%;
		height: 500rpx;
		box-sizing: border-box;
		margin-bottom: 8rpx;
		border: 1px solid rgb(138, 145, 159);
	}

	.item {
		box-sizing: border-box;
		padding: 10rpx;
		border-bottom: 1px solid gray;
	}

	/* button {
		margin-bottom: 20rpx;
	} */

	.btnBox {
		display: flex;
		display: flex;
		align-items: flex-end;
		flex-wrap: wrap;
	}

	.BuuetoothServiceList {
		width: 100%;
		height: 2rem;
		margin-bottom: 8rpx;
		line-height: 2rem;
		text-align: center;
		font-weight: 700;

	}

	.msg_x {
		border: 2px solid seagreen;
		width: 98%;
		margin: 10rpx auto;
		box-sizing: border-box;
		padding: 20rpx;
	}

	/*	​.msg_txt {
		margin-bottom: 20rpx;
	} */

	.clearInput {
		width: 5%;
		height: 3rem;
		line-height: 3rem;
		float: left;
		margin-left: 2%;
	}
</style>

总结如下:

参考uniapp官方文档api
初始化:打开蓝牙模块
搜寻:检测附近存在的设备
连接:找到目标设备进行
监听:开启监听功能,接收其他设备传过来的数据
发送指令:不管发送数据还是读取数据,都可以理解为向外发送指令

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值