uniapp实现蓝牙自动连接并获取心电图(代码篇)

embedded/2024/10/18 22:25:32/

我们最近的项目是需要写一个app和公司设备通过蓝牙连接,并且获取到心电图,这次是实现自动的,用户在第一次的时候需要点击连接蓝牙实现自动连接,后续更是不需要点击直接获取心电图,直接上代码,供大家参考!

javascript"><template><view><page-head :title="title"></page-head><!-- 心电图显示区 --><view class="displayarea">心电图显示区<view class="container"><canvas canvas-id="grids" style="width: 750rpx; height: 750rpx;"></canvas></view></view><!-- <view style="background-color: red;">心率:{{heartRateData[heartRateData.length-1]}}</view> --><canvas canvas-id="waveform" id="waveform" style="width: 500px; height: 400px; margin: 0 auto"></canvas><view class="uni-padding-wrap uni-common-mt"><!-- button class="heartrate">心率</button> --><view class="uni-btn-v"><button type="primary" :disabled="disabled" @click="openBluetoothAdapter">连接蓝牙</button><button type="primary" :disabled="!disabled" @click="closeBLEConnection">断开蓝牙设备</button><button type="primary" :disabled="!disabled" @click="closeBluetoothAdapter">关闭蓝牙模块</button></view></view><!-- 遮罩 --></view>
</template>
<script>let num = 0;let timer = null;export default {data() {return {title: 'bluetooth',disabled: false,deviceId: '',serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',writeCharacteristicsId: '',connectCharacteristicsId: '',characteristicId: '0000FFF1-0000-1000-8000-00805F9B34FB',heartRateData: [],macAddress: '',macValue: '',valueChangeData: {value: ''},extraLine: [],};},onLoad() {this.setOnBLECharacteristicValueChange();this.openBluetoothAdapter()},onShow() {const ctx = uni.createCanvasContext('waveform', this);if(timer != null){clearInterval(timer);}timer = setInterval(() => {if (this.heartRateData.length) {this.drawLine(ctx, this.heartRateData)}}, 50)},beforeDestroy() {clearInterval(timer);timer = null;this.closeBLEConnection()uni.closeBluetoothAdapter()},methods: {moveHandle() {},/*** 关闭遮罩*/maskclose() {this.maskShow = false;},/*** 选择设备*/queryDevices() {// this.newDeviceLoad = true;this.showMaskType = 'device';this.maskShow = true;},tapQuery(item) {if (this.showMaskType === 'device') {this.$set(this.disabled, 4, false);if (this.equipment.length > 0) {this.equipment[0] = item;} else {this.equipment.push(item);}this.newDeviceLoad = false;}if (this.showMaskType === 'service') {this.$set(this.disabled, 6, false);if (this.servicesData.length > 0) {this.servicesData[0] = item;} else {this.servicesData.push(item);}}if (this.showMaskType === 'characteristics') {this.$set(this.disabled, 7, false);if (this.characteristicsData.length > 0) {this.characteristicsData[0] = item;} else {this.characteristicsData.push(item);}}this.maskShow = false;},/*** 第一步* 初始化蓝牙设备** */openBluetoothAdapter() {// 设置 监听蓝牙适配器状态变化事件console.log("第一步");this.disabled = true// this.setOnBluetoothAdapterStateChange()uni.openBluetoothAdapter({success: e => {console.log('openBluetoothAdapter success', e);this.startBluetoothDevicesDiscovery()},fail: e => {console.log(e)console.log('初始化蓝牙失败,错误码:' + (e.errCode || e.errMsg));if (e.errCode !== 0) {initTypes(e.errCode, e.errMsg);}}});},/*** 第二步,* 监听蓝牙适配器状态变化事件*/setOnBluetoothAdapterStateChange() {console.log("第二步");uni.onBluetoothAdapterStateChange((res) => {console.log("第二步", res);if (res.available) {// 蓝牙适配器 ,则开始搜索蓝牙设备this.startBluetoothDevicesDiscovery()}})},/*** 第二步,* 开始搜索蓝牙设备* */startBluetoothDevicesDiscovery() {console.log("第三步");// 搜索之前监听寻找到新设备的事件this.onBluetoothDeviceFound();uni.startBluetoothDevicesDiscovery({success: e => {},fail: e => {console.log('搜索蓝牙设备失败,错误码:' + e.errCode);if (e.errCode !== 0) {initTypes(e.errCode);}}});},/*** 第三步* 寻找到新设备* * */onBluetoothDeviceFound() {console.log("第四步");uni.onBluetoothDeviceFound(res => {console.log(res);// 监听寻找到新设备的事件for (var i = 0; i < res.devices.length; i++) {let device = res.devices[i]// 根据设备名称找到对应的设备,然后链接设备if (device.name && device.name == 'FSC-BT1036-LE-09F8') {this.deviceId = device.deviceId// 停止设备查找this.stopBluetoothDevicesDiscovery()uni.showLoading({title: '连接蓝牙...'});uni.createBLEConnection({deviceId: this.deviceId,success:res => {uni.hideLoading()setTimeout(()=> {this.getBLEDeviceServices().then(res => {console.log(res);return this.getBLEDeviceCharacteristics()}).then(res => {console.log(res);return this.bleNotifyAndlisten()}).then(res => {console.log(res);// 需要延时 再去调用读取数据setTimeout(() => {this.readBLECharacteristicValue()}, 1000);})},1000)},fail: (err) => {uni.hideLoading()uni.showModal({title: "温馨提示",content: '"蓝牙连接失败'})}});}}});},/*** 第四步* 连接低功耗蓝牙设备* */createBLEConnection(deviceId) {return },/***  第五步* 获取蓝牙所有服务*/getBLEDeviceServices() {return new Promise((reslove, reject) => {uni.getBLEDeviceServices({deviceId: this.deviceId,success: res => {console.log(res);reslove("[ok-5].获取蓝牙所有服务成功!")},fail: err => {reject(err)}})})},/***  第六步* 获取该蓝牙设备某个服务的特征*/getBLEDeviceCharacteristics() {return new Promise((reslove, reject) => {uni.getBLEDeviceCharacteristics({deviceId: this.deviceId,serviceId: this.serviceId,success: res => {console.log('getBLEDeviceCharacteristics success');console.log(res);let characteristics = res.characteristicsfor (let i = 0; i < characteristics.length; i++) {let item = characteristics[i]if (item.properties.write) {this.writeCharacteristicsId = item.uuid;}if (item.properties.notify || item.properties.indicate) {this.connectCharacteristicsId = item.uuid}}console.log(this.writeCharacteristicsId, this.connectCharacteristicsId);reslove("[ok-6].获取蓝牙下该服务的特征成功!")},fail: err => {console.log('getBLEDeviceCharacteristics fail',err);reject(err)}})})},/***  第七步* 启用低功耗蓝牙设备特征值变化时的 notify 功能,*/bleNotifyAndlisten() {return new Promise((reslove, reject) => {uni.notifyBLECharacteristicValueChange({state: true,deviceId: this.deviceId,serviceId: this.serviceId,characteristicId: this.connectCharacteristicsId,success: res => {console.log('notifyBLECharacteristicValueChange success', res);reslove("[ok-7]. notify 启动成功")},fail: err => {console.log('notifyBLECharacteristicValueChange err', err);reject(err)}})})},/***  第八步* 发起读数据请求  * 读取低功耗蓝牙设备的特征值的二进制数据值。注意:必须设备的特征值支持 read 才可以成功调用 */readBLECharacteristicValue() {console.log("第八步");uni.readBLECharacteristicValue({deviceId: this.deviceId,serviceId: this.serviceId,characteristicId: this.connectCharacteristicsId,success: (res) => {console.log('读取设备数据值成功');console.log(JSON.stringify(res));},fail: (res) => {console.log('读取设备数据值失败,错误码:' + res.errCode);// if (res.errCode !== 0) {// 	initTypes(e.errCode);// }}});//this.onBLECharacteristicValueChange();},/*** 第九步,解析数据* 监听低功耗蓝牙设备的特征值变化事件。必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification。* * */setOnBLECharacteristicValueChange() {let that = this// 必须在这里的回调才能获取uni.onBLECharacteristicValueChange((res) => {console.log("第九步");console.log('监听低功耗蓝牙设备的特征值变化事件成功');console.log(`characteristic ${res.characteristicId} has changed, now is ${JSON.stringify(res)}`);const unit8Array = new Uint8Array(res.value);// console.log("unit8Array: ", unit8Array);// 获取canvas绘图上下文// let heartRate = that.heartRateData;if (this.heartRateData.length >= 100) {this.heartRateData.shift();}this.heartRateData.push(unit8Array);// that.heartRateData = heartRate;console.log("----heartRate", this.heartRateData)console.log("length", this.heartRateData.length)this.macAddress = res.deviceId;this.macValue = this.ab2hex(res.value);this.valueChangeData.value = this.ab2hex(res.value);this.extraLine.push(this.macValue);this.valueChangeData = this.extraLine.join(' \n ');});},/*** 停止搜索蓝牙设备*/stopBluetoothDevicesDiscovery() {uni.stopBluetoothDevicesDiscovery({success: e => {},fail: e => {console.log('停止搜索蓝牙设备失败,错误码:' + e.errCode);}});},/*** 断开与低功耗蓝牙设备的连接*/closeBLEConnection() {uni.closeBLEConnection({deviceId:this.deviceId,success: res => {console.log(res);console.log('断开低功耗蓝牙成功:' + res.errMsg);this.$set(this.disabled, 1, false);this.$set(this.disabled, 3, true);this.$set(this.disabled, 4, true);this.$set(this.disabled, 5, true);this.$set(this.disabled, 6, true);this.$set(this.disabled, 7, true);this.$set(this.disabled, 8, true);this.$set(this.disabled, 9, true);this.equipment = [];this.servicesData = [];this.characteristicsData = [];},fail: e => {console.log('断开低功耗蓝牙成功,错误码:' + e.errCode);if (e.errCode !== 0) {initTypes(e.errCode);}}});},ab2hex(buffer) {const hexArr = Array.prototype.map.call(new Uint8Array(buffer),function(bit) {return ('00' + bit.toString(16)).slice(-2)})return hexArr.join('')},drawLine(ctx) {// num++;// console.log("----------------num",num)// 				const y = (Number(unit8Array[0]) + (Number(unit8Array[1])<<8) + (Number(unit8Array[2])<<16) + (Number(unit8Array[3])<<24));// 				console.log("----",y);// 			 // console.log("ctx: ", ctx);// 			 console.log("that.heartRateDat: ", heartRate);// 绘制波形图const width = 600;const height = 600;// 设置波形图样式ctx.setStrokeStyle('#F79A18');ctx.setLineWidth(3);ctx.setLineCap("round")ctx.clearRect(0, 0, width, height);// 清除Canvas并绘制新的波形图ctx.beginPath();ctx.moveTo(-10, 0); // 将起点移动到Canvas的中间位置for (let i = 0; i < this.heartRateData.length; i++) {const y = (Number(this.heartRateData[i][0]) + (Number(this.heartRateData[i][1]) << 8) + (Number(this.heartRateData[i][2]) << 16) + (Number(this.heartRateData[i][3]) << 24));ctx.lineTo(i * 5, -y / 260 + 250); // 将数据绘制 n 到Canvas上,放大50倍以适应Canvas高度}ctx.stroke();ctx.draw();},/***     断开蓝牙模块          */closeBluetoothAdapter(OBJECT) {uni.closeBluetoothAdapter({success: res => {console.log('断开蓝牙模块成功');this.isStop = true;this.$set(this.disabled, 0, false);this.$set(this.disabled, 1, true);this.$set(this.disabled, 2, true);this.$set(this.disabled, 3, true);this.$set(this.disabled, 4, true);this.$set(this.disabled, 5, true);this.$set(this.disabled, 6, true);this.$set(this.disabled, 7, true);this.$set(this.disabled, 8, true);this.$set(this.disabled, 9, true);this.$set(this.disabled, 10, true);this.equipment = [];this.servicesData = [];this.characteristicsData = [];this.valueChangeData = {};this.adapterState = [];this.searchLoad = false;toast('断开蓝牙模块');}});}}};/*** 判断初始化蓝牙状态*/function initTypes(code, errMsg) {switch (code) {case 10000:toast('未初始化蓝牙适配器');break;case 10001:toast('未检测到蓝牙,请打开蓝牙重试!');break;case 10002:toast('没有找到指定设备');break;case 10003:toast('连接失败');break;case 10004:toast('没有找到指定服务');break;case 10005:toast('没有找到指定特征值');break;case 10006:toast('当前连接已断开');break;case 10007:toast('当前特征值不支持此操作');break;case 10008:toast('其余所有系统上报的异常');break;case 10009:toast('Android 系统特有,系统版本低于 4.3 不支持 BLE');break;default:toast(errMsg);}}/*** 弹出框封装    */function toast(content, showCancel = false) {uni.showModal({title: '提示',content,showCancel});}
</script><style>.uni-title {/* width: 100%; *//* height: 80rpx; */text-align: center;}.displayarea {}.uni-mask {position: fixed;top: 0;left: 0;bottom: 0;display: flex;align-items: center;width: 100%;background: rgba(0, 0, 0, 0.6);padding: 0 30rpx;box-sizing: border-box;}.uni-scroll_box {height: 70%;background: #fff;border-radius: 20rpx;}.uni-list-box {margin: 0 20rpx;padding: 15rpx 0;border-bottom: 1px #f5f5f5 solid;box-sizing: border-box;}.uni-list:last-child {border: none;}.uni-list_name {font-size: 30rpx;color: #333;white-space: pre-wrap;}.uni-list_item {font-size: 24rpx;color: #555;line-height: 1.5;}.uni-success_box {position: absolute;left: 0;bottom: 0;min-height: 100rpx;width: 100%;background: #fff;box-sizing: border-box;border-top: 1px #eee solid;}.uni-success_sub {/* width: 100%%; */height: 100rpx;display: flex;justify-content: space-between;align-items: center;padding: 0 30rpx;}.uni-close_button {padding: 0 20rpx;height: 60rpx;line-height: 60rpx;background: #ce3c39;color: #ffffff;border-radius: 10rpx;}.uni-success_content {height: 600rpx;margin: 30rpx;margin-top: 0;border: 1px #eee solid;padding: 30rpx;}.uni-content_list {padding-bottom: 10rpx;border-bottom: 1px #f5f5f5 solid;}.uni-tips {text-align: center;font-size: 24rpx;color: #666;}.heartrate {width: 200rpx;height: 150rpx;line-height: 150rpx;background-color: #ce3c39;border: 0;color: #fff;}
</style>

我这里是直接拿设备的名称和uuid,因考虑到用户大多数为中老年人,实现一键自动连接完全很有必要(只是自己的一些看法,这个还是得根据需求来)只不过我们的需求是这样的,如果有更好的方法请大家多多评论!


http://www.ppmy.cn/embedded/43910.html

相关文章

基于Centos7 安装k8s一主两从

一、资源准备 mac下虚拟机环境搭建 1、使用搜狐的iso源 http://mirrors.sohu.com/centos/7.5.1804/isos/x86_64/CentOS-7-x86_64-Minimal-1804.iso 下载 iso镜像。 2、https://www.macwk.com/soft/vmware 下载 mac vm虚拟机 3、搭建一主两从集群所需虚拟机 4、新建虚拟机…

子分支想主分支发起合并请求

请求合并 1.点击 git Web 页右上角打开 Merge requests 进入新页&#xff0c;点击右上角。注意选择要合并的项目 2.左边是源分支&#xff0c;右边是要合并的目标分支。 3.最后点击左下角绿色按钮 4.第一个红框 Assignee&#xff0c;选择要通知去合并的人。第二个红框不动&#…

python前端通过API接口调用与后端进行数据交互前端如何调用api接口获取电商平台商品实时评论信息数据

要在Python前端通过API接口调用与后端进行数据交互并获取商品实时评论信息数据&#xff0c;可以通过封装好的api接口通过链接直接请求获取商品数据&#xff0c;以下是接入api的请求示例&#xff1a; # coding:utf-8 """ Compatible for python2.x and python3.…

npm,yarn,cnpm,tyarn,pnpm 安使用装配置镜像

npm 安装 安装node后就可以使用了 官方默认地址 npm config set registry https://registry.npmjs.org 镜像 npm config set registry https://registry.npm.taobao.org npm config set registry http://registry.npmmirror.org全局安装依赖 npm install -g <包名&g…

Spring 中常用的手动装载 bean 方法

在 Spring 的 bean 装载条件中&#xff0c;虽然 Spring 给我们提供了非常好用便捷的 Condition 相关注解&#xff0c;但是很多时候 Condition 相关注解并不满足我们的需求&#xff0c;我需要更复杂的条件手动控制是否装置 bean。这个时候我们就可以实现 Spring 为我们提供的几个…

设计模式20——职责链模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 职责链模式&#xff08;Chain …

mac版本Phpstudy本地环境安装Discuz教程【2024】

此方法适用于m1版本的mac版本Phpstudy本地环境安装Discuz&#xff0c;当然同样使用更高版本的mac端。网上各种安装教程参差不齐&#xff0c;根本解决不了小白的入门需求&#xff0c;以下是最新且直接明了的安装教程。 Phpstudy本地环境安装Discuz教程&#xff1a; 1、安装Phps…

Flutter 中的 Opacity 小部件:全面指南

Flutter 中的 Opacity 小部件&#xff1a;全面指南 在Flutter中&#xff0c;动画和视觉效果是提升用户体验的重要手段。Opacity小部件允许你改变子组件的透明度&#xff0c;从而实现淡入、淡出或其它透明度相关的动画效果。本文将提供Opacity的全面指南&#xff0c;帮助你了解…