序言
序言不会写,怎么简单怎么来,主要讲蓝牙向手机app传递数据怎么爬坑
概括
Ble蓝牙和uniapp数据互传的玩法,一般都是以下几步
1、初始化蓝牙 uni.openBluetoothAdapter(OBJECT)
2、开始搜索蓝牙设备 uni.startBluetoothDevicesDiscovery(OBJECT)/
3、发现外围设备 uni.onBluetoothDeviceFound(CALLBACK)
4、停止搜寻附近的蓝牙外围设备 uni.stopBluetoothDevicesDiscovery(OBJECT)
5、连接低功耗蓝牙设备 uni.createBLEConnection(OBJECT)
6、获取蓝牙设备所有服务 uni.getBLEDeviceServices(OBJECT)
7、获取蓝牙特征 uni.getBLEDeviceCharacteristics(OBJECT)
8、启用蓝牙设备特征值变化时的 notify 功能uni.notifyBLECharacteristicValueChange(OBJECT)
9、监听低功耗蓝牙设备的特征值变化 uni.onBLECharacteristicValueChange(CALLBACK)
一点点讲的话内容有点多,我贴一个大佬的代码,会用vue的应该在uniapp中写一个小程序问题不是很大,如果不会vue开发,后面我会把我自己的代码打包给大家的,只要你按照概括里面的流程就能玩起来,坑不在这里,顺便提一嘴坑也不在uni.readBLECharacteristicValue(OBJECT),ble低功耗蓝牙只是一个透传模块,不用考虑太多具体的细节
主要内容
终于正文了~,相信大家玩蓝牙通信都是看过太极创客这个网站的,第一块蓝牙买HC-06的不知道多不多,我的第一块蓝牙就是HC-06,踩坑的绝大部分人应该都是因为看过这个HC-06的教程,为啥又买HM-10,原因必然是BLE蓝牙太过任性,HM-10的参数相信大家都看过,里面有这样一段讲的是
保护蓝牙RX引脚的方法,这1-2K大家有没有注意啊,调试大家应该都是用的串口监视器,能正常连接蓝牙HM-10,串口监视器也有输出,这里的前提是你选择的特征值notify:true,并且在uni.onBLECharacteristicValueChange(CALLBACK)这个监听方法调用前你已经调用了uni.notifyBLECharacteristicValueChange(OBJECT),change方法可以放在notify方法的成功回调中调用,成功连接后,无论在串口监视器中怎么输入数据蓝牙的就是不能回传数据,无法触发uni.onBLECharacteristicValueChange(CALLBACK)方法,这是太极创客为保护HC-06提供的一种分压接线方式
不知道有没有大佬照搬接线方式在HM-10上面的?官方文档说的很清楚1-2k电阻直接接入电路,分压电路可能会导致高电平无法达到蓝牙RX引脚需要的电压,所以蓝牙接收模块无法接收到Arduino发送来的数据,有条件的发烧友可以买HM-15,工作电压和Arduino引脚高电平完美匹配,就不用每次去分压了,我是直接接的,还是建议接一个保护电阻。
为了不让没有获取准入的用户无法获取数据,我想检测手机发过来的指定秘钥,通过才开始推数据,但是下面这段代码让我必须手动在串口监视器输入数据,uni端才能检测到数据变化,太裂开了,挖个槽后面慢慢解决吧
问题代码块:
if (Serial.available()){
delay(10); // The DELAY!
bluetooth.print(sensors.getTempCByIndex(0));
}
导致问题的原因官方说了
我这里用到的模块我讲讲
Arduino UNO板子,注意芯片是 ATMEGA328克隆版,买官配准没错,温度检测模块蓝牙RX引脚接个1-2k的电阻保护一下,DS18B20接线我给个图,电阻4.7k-10k之间都可以,作用是作为上拉电阻拉升电压这很重要,不然中间的输出引脚就一直输出-127,接线按下面这个图接,端口啥的选自己喜欢的就行
以下代码贴上就能跑
相关代码
Arduino代码
//我蓝牙用的3和5别搞错了
#include <SoftwareSerial.h>
#include<OneWire.h>
#include<DallasTemperature.h>
SoftwareSerial bluetooth(3, 5); // RX, TX
OneWire onewire(7);
DallasTemperature sensors(&onewire);
void setup()
{
// Start the hardware serial port
Serial.begin(9600);
sensors.begin();
//pinMode(13, OUTPUT); // onboard LED
//digitalWrite(13, LOW); // switch OFF LED
bluetooth.begin(9600);
// un REM this to set up a Master and connect to a Slave
Serial.println("BLE CC41A Bluetooth");
Serial.println("----------------------------------");
Serial.println("");
Serial.println("Trying to connect to Slave Bluetooth");
delay(1000);
//Serial.println("AT");// just a check
// bluetooth.write("AT");
}
void loop()
{
sensors.requestTemperatures();
Serial.write("温度:");
Serial.print(sensors.getTempCByIndex(0));
Serial.println("摄氏度");
delay(1000);
bluetooth.listen();
//这里我直接发数据,不甄别用户
bluetooth.print(sensors.getTempCByIndex(0));
//下面的代码有点问题,必须从串口监视器输入手机端才能出发uni.change方法否则挂起不动
//后续解决,必须手机端给个指定秘钥才能获取数据,数据裸奔肯定是不行的,先裸奔一会儿
// if (Serial.available()){
// delay(10); // The DELAY!
// bluetooth.print(sensors.getTempCByIndex(0));
// }
while(bluetooth.available() > 0) {
char inByte = bluetooth.read();
Serial.write(inByte);
}
delay(1000);
}
uniapp代码文件,但是为毛不能导整个项目
//特征值我写死了的,只是为了测试,如果是其它ble最好遍历一下特征值,取出notify:true的特征值作为数据载体,请务必打开蓝牙和定位功能
<template>
<view>
蓝牙连接信息:<br>
<view class="btn_con">
<view v-if="this.list.length>0">
<ol>
<li v-if=tem style="color:gold">当前温度:{{tem}}℃</li>
<li v-for="item in list">
<view>deviceId: {{item.deviceId}}</view>
<view>name: {{item.name}}</view>
<view>RSSI: {{item.RSSI}}</view>
<view>localName: {{item.localName}}</view>
<view>advertisServiceUUIDs: {{item.advertisServiceUUIDs}}</view>
<view>advertisData: {{item.advertisData}}</view>
<button
class="btn_sty"
:loading="loading"
:plain='true'
:hover-class="'hover-class'"
@click="createBLEConnection(item)">连接蓝牙
</button>
<button
class="btn_sty"
:plain='true'
:hover-class="'hover-class'"
@click="closeBletoohConnection()">断开连接
</button>
<!--下面的代码测试用的-->
<!-- <button
class="btn_sty"
:plain='true'
:hover-class="'hover-class'"
@click="getReadValue()">获取数据
</button> -->
</li>
</ol>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list:[],
loading:false,
deviceId:"",
serviceId:"",
shiliu:"",
characteristics:[],
tem:""
}
},
onLoad() {
uni.openBluetoothAdapter({
success:(res)=> { //已打开
uni.getBluetoothAdapterState({//蓝牙的匹配状态
success:(res1)=>{
console.log(res1,'“本机设备的蓝牙已打开”')
// 开始搜索蓝牙设备
this.startBluetoothDeviceDiscovery()
},
fail(error) {
uni.showToast({icon:'none',title: '查看手机蓝牙是否打开' });
}
});
},
fail:err=>{ //未打开
uni.showToast({icon:'none',title: '查看手机蓝牙是否打开'});
}
})
},
methods:{
//此方法用于向蓝牙写数据
checkTem(){
let thit=this;
if(thit.deviceId&&thit.serviceId)
uni.writeBLECharacteristicValue({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId:thit.deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId:thit.serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId:"0000FFE1-0000-1000-8000-00805F9B34FB",
value:thit.string2buffer("1"),
success:(res)=> {
uni.showToast({icon:'none',title: '已开启数据监测' });
},
fail:(er)=> {
console.log(er)
uni.showToast({icon:'none',title: '启动失败,请重试' });
}
})
else
uni.showToast({icon:'none',title: '请先连接蓝牙设备' });
},
//此方法用于将字符串转为arraybuffer数据
string2buffer(str) {
var buf = new ArrayBuffer(str.length); // 可以str.length * 2,两个字节存一个字符,但是测试好像没啥影响,可能就是长度不同,没细测
var bufView = new Uint8Array(buf);//new Uint16Array(buf)按照16读取后端传来的数据
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
console.log(buf)
return buf;
},
//8位存一个字符读取数据并转字符串
ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
},
// 开始搜索蓝牙设备
startBluetoothDeviceDiscovery(){
uni.startBluetoothDevicesDiscovery({
success: (res) => {
console.log('startBluetoothDevicesDiscovery success', res)
// 发现外围设备
this.onBluetoothDeviceFound()
},fail:err=>{
console.log(err,'错误信息')
}
})
},
// 发现外围设备
onBluetoothDeviceFound() {
// console.log("zhixing")
uni.onBluetoothDeviceFound((res) => {
console.log(res)
// ["name", "deviceId"]
// 吧搜索到的设备存储起来,方便我们在页面上展示
if(res.devices.length>0){
res.devices.forEach(item=>{
this.list.push(item)
})
}
})
},
createBLEConnection(item){
let thit = this
//data里面建立一个deviceId,存储起来
this.deviceId = item.deviceId
//连接蓝牙
uni.createBLEConnection({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId:this.deviceId,
success(res) {
//防止在这里面取不到this,古在外面用thit存储了this
thit.stopBluetoothDevicesDiscovery()
console.log(res)
console.log("蓝牙连接成功")
thit.getBLEDeviceServices();
},fail(res) {
console.log("蓝牙连接失败",res)
}
})
},
// 停止搜寻蓝牙设备
stopBluetoothDevicesDiscovery(){
uni.stopBluetoothDevicesDiscovery({
success: e => {
this.loading = false
console.log('停止搜索蓝牙设备:' + e.errMsg);
},
fail: e => {
console.log('停止搜索蓝牙设备失败,错误码:' + e.errCode);
}
});
},
//获取蓝牙的所有服务
getBLEDeviceServices(){
setTimeout(()=>{
uni.getBLEDeviceServices({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId:this.deviceId,
success:(res)=>{
// console.log("成功",res)
console.log('device services:', res)
res.services.forEach((item)=>{
if(item.uuid==="0000FFE0-0000-1000-8000-00805F9B34FB"){
this.serviceId = item.uuid;
//存储到状态
//this.$store.commit("upserviceId",item.uuid)
console.log(this.serviceId)
// 这里获取回调,读取成功就的值就会在这个地方接收到!!!
this.getBLEDeviceCharacteristics()
}
})
}
})
},1000)
},
//获取蓝牙特征
getBLEDeviceCharacteristics(){
console.log("进入特征");
setTimeout(()=>{
uni.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId:this.deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId:this.serviceId,
success:(res)=>{
console.log(res,'特征getBLEDeviceCharacteristics')
this.characteristics = res.characteristics
console.log(this.characteristics)
this.notifyBLECharacteristicValueChange("0000FFE1-0000-1000-8000-00805F9B34FB")
},
fail:(res)=>{
console.log(res)
}
})
},1000);
},
// 启用 notify 功能
notifyBLECharacteristicValueChange(characteristicId){
let thit=this;
uni.readBLECharacteristicValue({
deviceId:thit.deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId:thit.serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId:"0000FFE1-0000-1000-8000-00805F9B34FB",
success:res=>{
console.log("读取特征值成功:"+res)
},
fail:err=>{
console.log("读取特征值失败:"+err)
}
})
console.log(characteristicId,'characteristicId')
uni.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId:thit.deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId:thit.serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId:characteristicId,
success:(res)=> {
console.log(res)
// console.log(this.characteristicId)
console.log('notifyBLECharacteristicValueChange success', res.errMsg)
},
fail:(res)=> {
console.log('notifyBLECharacteristicValueChange success2', res.errMsg)
}
});
thit.onBLECharacteristicValueChange();
},
onBLECharacteristicValueChange(){
let thit=this;
uni.onBLEConnectionStateChange(res => {
// 该方法回调中可以用于处理连接意外断开等异常情况
console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`)
if (res.connected == false) {
// this.dklj();
// this.createBLEConnection()
}
})
uni.onBLECharacteristicValueChange(function(re){
//console.log(re.value);
thit.tem=thit.ab2str(re.value);
console.log(thit.ab2str(re.value))
//res.value是ArrayBuffer类型的,官方给了一个方法转16进制,我们再进行操作
//console.log(thit.ab2hex(re.value));
})
},
getReadValue(){
let thit=this;
uni.readBLECharacteristicValue({
deviceId:thit.deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId:thit.serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId:"0000FFE1-0000-1000-8000-00805F9B34FB",
success:res=>{
console.log("读取特征值成功:"+res)
// thit.receiveCharacterValue();
},
fail:err=>{
console.log("读取特征值失败:"+err)
}
});
},
closeBletoohConnection(){
uni.closeBLEConnection({
deviceId:this.deviceId,
success:res=>{
uni.showToast({icon:'none',title: '连接已断开...'});
},
fail:err=>{
uni.showToast({icon:'none',title: '连接断开失败'});
}
});
}
},
}
</script>
<style scoped>
.btn_con{
/* margin-top:20px; */
display:flex;
flex-direction:row ;
justify-content:flex-start;
align-items:center;
align-content:space-around;
flex-wrap:wrap;
}
.hover-class{
color:#ed080c;
}
.btn_sty{
flex:1;
display: inline-block;
margin: 10px;
color:#ee696b;
border: none;
}
</style>
以下是运行结果
手机上的效果
Arduino串口监视器传值,这里这是模拟,真实场景可以使用各种传感器采集的数据作为输入
uni.onBLECharacteristicValueChange(CALLBACK)已经能正常监听值的改变了
给你们看一下我的个性化接线
总结
硬件模块不正常工作的时候首先检查接入是否正确,串口是否占用、工作电压是否稳定,有条件最好别硬接,买个万用表测一下,一般模块的参数文档都不会很复杂,通过蓝牙模块把数据传输的问题解决了,就能在板子另一端加装各种传感器愉快玩耍了,最后如果这篇博客对您有帮助赶紧收藏,转载请注明转载地址,说得不对的地方请不吝指出,谢谢~