uniapp 与蓝牙设备收发指令详细步骤(完整项目版)

阅读前须知

1、若已知蓝牙设备的 deviceId、serviceId、以及读写特征值,可以直接从第7点开始阅读
2、文档中各函数的详细属性、回调函数等介绍内容,可以查看官网文档:uniapp 低功耗蓝牙连接
3、与蓝牙设备之间收发数据格式必须为 ArrayBuffer
4、本文中与蓝牙设备收发数据时,数据包的长度为20 字节,不够 20 字节的补 0

1、初始化蓝牙模块
uni.openBluetoothAdapter({
	success(res) {
		console.log('初始化蓝牙成功')
		console.log(res)
	},
	fail(err) {
		console.log('初始化蓝牙失败')
		console.error(err)
	}
})
2、搜索附近可连接的蓝牙设备

uni.startBluetoothDevicesDiscovery()比较耗费系统资源,建议搜索完成后调用stopBluetoothDevicesDiscovery()结束搜索。

uni.startBluetoothDevicesDiscovery({
	allowDuplicatesKey: false,
	interval: 0,
	success: (res) => {
		console.log("执行搜索成功的回调")
	},
	fail: (error) => {
		console.log(error)
	}
})

若需要过滤搜索出来的蓝牙设备,可以设置services属性进行过滤

在这里插入图片描述

3、搜索附近可连接的蓝牙设备

uni.getBluetoothDevices()获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备

uni.getBluetoothDevices({
	success: function(res) {
		console.log(res)
	},
	fail: function() {
		console.log("获取蓝牙设备列表失败")
	}
})

到这一步,已经能拿到附近所有的蓝牙设备列表,下面开始进行连接。

4、连接低功耗蓝牙设备

前提条件:

  1. 蓝牙设备支持低功耗协议(BLE)
  2. 拿到设备的deviceId
uni.createBLEConnection({
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	success: (res) => {
		console.log("连接成功", res)
		
		// 在这里可以执行获取蓝牙设备的所有服务,若获取失败可以使用 setTimeout
	},
	fail: (error) => {
		console.log("连接失败", error)
	}
})
5、获取蓝牙设备的所有服务
uni.getBLEDeviceServices({
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	success: (res) => {
		console.log('成功获取蓝牙设备的所有服务', res)
		
		// 这里可以拿到蓝牙设备的 serviceId
	}
})
6、获取蓝牙设备某个服务中所有特征值(characteristic)
uni.getBLEDeviceCharacteristics({
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	serviceId: this.serviceId,  // 在第 5 步可以拿到蓝牙的 serviceId 的值
	success: (res) => {
		console.log('获取 characteristic 成功', res)
		
		// 在这里可以获取到这个服务的所有特征值,需要确定哪些特征值是此次使用的
		// 一般这里可以拿到两个特征值:写characteristic、读characteristic
		// 接下来这里可以根据拿到的“读characteristic”开启 notify
	},
	fail: (res) => {
		console.log('获取 characteristic 失败', res)
	}
})
7、启动 notify 功能监听蓝牙设备回传信息

注意:必须设备的特征值支持 notify 或者 indicate 才可以成功调用

uni.notifyBLECharacteristicValueChange({
	state: true,
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	serviceId: this.serviceId,  // 在第 5 步可以拿到蓝牙的 serviceId 的值
	characteristicId: this.readCharacteristic,  // 在第 6 步可以拿到蓝牙的 characteristic 的值,这里使用的是 “读characteristic”
	success(res) {
		console.log("开启 notify 功能成功...")
		
		// 必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送
		uni.onBLECharacteristicValueChange(res => {
			let resHex = ab2hex(res.value)  // 将蓝牙设备回传的内容进行解析
			console.log("接收到回传内容:", resHex)  // 若需要,可参考第 9 点解析响应包的源码
			
			// 蓝牙设备会分多次回传数据,并且都可以在这里监听到
			// 这里可以执行一个处理所有回传结果的函数
		})
	},
	fail(err) {
		console.log("监听失败,发生错误", err)
	}
})


// ArrayBuffer 转 16 进制字符串示例
function ab2hex(buffer) {
  const hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('')
}

到这里,已经完成了与低功耗蓝牙设备连接、蓝牙设备回传数据的监听。

8、向蓝牙设备发送指令

假设,存在一个获取蓝牙设备电量的指令如下:

向蓝牙设备发送数据格式:

起始码数据类型数据
0xSA0x010x00,0x00,…,0x00

蓝牙设备回传数据格式:

起始码数据类型结果电量空数据
0xRA0x010x010x140x00,0x00,…,0x00
let buffer = generate_command(0xSA, 0x01)

uni.writeBLECharacteristicValue({
	deviceId: this.deviceId,  // 在第 3 步可以拿到蓝牙的 deviceId 的值
	serviceId: this.serviceId,  // 在第 5 步可以拿到蓝牙的 serviceId 的值
	characteristicId: this.writeCharacteristicId,  // 在第 6 步可以拿到蓝牙的 characteristic 的值,这里使用的是 “写characteristicId”
	value: buffer,  // buffer 的格式为 ArrayBuffer
	success(res) {
		console.log('指令下发成功', res)
	},
	fail(err) {
		console.log('指令发送失败', err)
	}
})


/**
 * 生成 ArrayBuffer 格式的数据,可以直接用于给蓝牙设备发送数据
 * @param {Object} startCode 起始码
 * @param {Object} dataType 数据类型
 * @param {Object} sentData 发送给蓝牙的数据数组,例如:[0x12,0x01]
 */
function generate_command(startCode, dataType, sentData) {
	let buffer = new ArrayBuffer(20)
	let dataView = new DataView(buffer)
	dataView.setUint8(0, startCode)
	dataView.setUint8(1, dataType)
	let _beforeIndex = 2
	
	if(sentData) {
		for (var k = 0; k < sentData.length; k++) {
			dataView.setUint8(k + _beforeIndex, sentData[k])
		}
		_beforeIndex += sentData.length
	}
	return buffer
}

当指令发送成功后,在第 7 点中可以接收到蓝牙设备的响应包。否则,都视作为蓝牙接收数据失败!

9、附加:解析蓝牙响应数据包

在第 7 点中接受到响应的数据包后,仍然不是可以直观看出数据真实信息的格式,因此需要再次转换。

// responseData 的值为第 7 点中的 resHex
function parse_blue_response(responseData) {
	const dataList = responseData.match(/.{1,2}/g)
	const [resCode, resType, resResult] = dataList.splice(0, 3)
	// resCode:响应包起始码;
	// resType:响应包数据类型
	// resResult:响应包结果
	// dataList:其他响应数据 + 空数据,Array 格式数据
	return [resCode, resType, String(resResult), dataList]
}

10、附加:将上一步的 Array 解析成 number
function array16_to_number(arrayValue) {
	const newArray = arrayValue.filter(item => String(item) !== '00' || String(item) !== '0')
	const _number16 = newArray.map(hex => parseInt(hex, 16).toString(16)).join('')
	return parseInt(`0x${_number16}`)
}

如第 8 点,指令返回的电量结果为0x14,经过转换的得到值为20

在这里插入图片描述

  • 26
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32的串口通信是通过USART(通用同步/异步收发器)模块实现的,可以使用HAL库提供的函数来配置和操作串口。下面是一个示例代码,用于通过串口收发蓝牙AT指令。 首先,需要包含相关的头文件: ``` #include "stm32xxx.h" // 根据芯片型号选择正确的头文件 #include "stm32xxx_hal.h" // 使用HAL库的头文件 #include "string.h" // 包含字符串操作函数的头文件 ``` 然后,需要定义全局变量: ``` UART_HandleTypeDef huart1; // 定义UART句柄,用于串口通信 char buffer[1000]; // 定义接收缓冲区 ``` 接下来,需要配置串口: ``` void USART1_Init(void) { huart1.Instance = USART1; // 使用USART1作为串口 huart1.Init.BaudRate = 9600; // 设置波特率为9600 huart1.Init.WordLength = UART_WORDLENGTH_8B; // 设置数据字长为8位 huart1.Init.StopBits = UART_STOPBITS_1; // 设置停止位为1位 huart1.Init.Parity = UART_PARITY_NONE; // 设置校验位为无校验 huart1.Init.Mode = UART_MODE_TX_RX; // 设置模式为收发模式 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 设置硬件流控制为无 huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 设置过采样率为16倍 HAL_UART_Init(&huart1); // 初始化串口 } ``` 然后,可以在主函数中调用此初始化函数,并编写接收和发送蓝牙AT指令的代码: ``` int main(void) { USART1_Init(); // 初始化串口 while (1) { memset(buffer, 0, sizeof(buffer)); // 清空接收缓冲区 HAL_UART_Receive(&huart1, (uint8_t *)buffer, sizeof(buffer), HAL_MAX_DELAY); // 接收串口数据 if (strstr(buffer, "AT") != NULL) // 如果接收到的数据包含AT指令 { // 执行AT指令操作,例如发送AT指令 char *at_cmd = "AT\r\n"; HAL_UART_Transmit(&huart1, (uint8_t *)at_cmd, strlen(at_cmd), HAL_MAX_DELAY); // 发送AT指令 } } } ``` 这样,代码就可以通过串口收发蓝牙AT指令了。当接收到的数据中包含AT指令时,可以执行相应的操作,例如发送AT指令。请根据具体需求进行修改和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值