小程序蓝牙连接ESP32通信(可直接拿来用)

小程序中的蓝牙能力

在小程序中,要使用蓝牙能力(Beacon 除外)必须首先调用 wx.openBluetoothAdapter 初始化蓝牙适配器模块,其生效周期为调用 wx.openBluetoothAdapter 至调用 wx.closeBluetoothAdapter 或小程序被销毁为止。只有在小程序蓝牙适配器模块生效期间,开发者才能够正常调用蓝牙相关的小程序 API,并收到蓝牙模块相关的事件回调(绑定监听不受此限制)。

小程序对蓝牙支持情况如下:

经典蓝牙:iOS 因系统限制暂无法提供,安卓目前已在规划中。

蓝牙低功耗 (BLE):

  • 主机模式:基础库 1.1.0(微信客户端 iOS 6.5.6,Android 6.5.7)开始支持。
  • 从机模式:基础库 2.10.3 开始支持。
  • 蓝牙信标 (Beacon):基础库 1.2.0 开始支持。

前置条件

  • 蓝牙模块需要是 低功耗蓝牙(BLE) ,不然小程序搜索不到(将导致无法继续进行开发),可购买我们的设备 来进行开发。
  • 开发者工具上只能模拟部分蓝牙接口能力,完整功能请使用真机调试。

官方文档

微信小程序蓝牙开发文档

微信小程序提供的操作蓝牙的 API

微信小程序目前有蓝牙 API 共 18 个

操作蓝牙适配器的 API
wx.openBluetoothAdapter 初始化蓝牙适配器
wx.closeBluetoothAdapter 关闭蓝牙模块
wx.getBluetoothAdapterState 获取本机蓝牙适配器状态
wx.onBluetoothAdapterStateChange 监听蓝牙适配器状态变化事件
连接前使用的 API
wx.startBluetoothDevicesDiscovery 开始搜寻附近的蓝牙外围设备
wx.stopBluetoothDevicesDiscovery 停止搜寻附近的蓝牙外围设备
wx.getBluetoothDevices 获取所有已发现的蓝牙设备
wx.onBluetoothDeviceFound 监听寻找到新设备的事件
连接和断开时使用的 API
wx.createBLEConnection 连接低功耗蓝牙设备
wx.closeBLEConnection 断开与低功耗蓝牙设备的连接
连接成功后使用的 API
wx.getConnectedBluetoothDevices 根据 uuid 获取处于已连接状态的设备
wx.getBLEDeviceServices 获取蓝牙设备所有 service(服务)
wx.getBLEDeviceCharacteristics  获取蓝牙设备所有 characteristic(特征值)
wx.readBLECharacteristicValue  读取低功耗蓝牙设备的特征值的二进制数据值
wx.writeBLECharacteristicValue 向低功耗蓝牙设备特征值中写入二进制数据
wx.notifyBLECharacteristicValueChange  启用低功耗蓝牙设备特征值变化时的 notify 功能
wx.onBLECharacteristicValueChange 监听低功耗蓝牙设备的特征值变化
wx.onBLEConnectionStateChange 监听低功耗蓝牙连接的错误事件

基本操作流程

最基本的操作流程是:初始化蓝牙适配器 → 开始搜寻附近的蓝牙外围设备 → 监听寻找到新设备的事件 → 连接低功耗蓝牙设备 → 获取蓝牙设备所有 service 和 characteristic → 读取或写入低功耗蓝牙设备的特征值的二进制数据值。

蓝牙组件代码

由于我们 index 中代码量比较多,不利于维护,所以我们将蓝牙功能单独抽离成一个 component(组件),方便管理和复用。

新建组件

新建一个 components 目录,在该目录下新建一个目录为 bluetooth-comp,然后在 bluetooth-comp 点击"新建 Component"按钮,输入 index 并点击确定。

页面结构部分
<!-- bluetooth-comp/index.wxml -->
<view style="margin: 26rpx"><button wx:if="{{!connected}}" bindtap="openBluetoothAdapter">开始扫描</button><button wx:else bindtap="closeBLEConnection">断开连接 - {{name}}</button><view class="devices_summary">已发现 {{devices.length}} 个外围设备:</view><viewwx:for="{{devices}}"wx:key="index"data-device-id="{{item.deviceId}}"data-name="{{item.name || item.localName}}"bindtap="createBLEConnection"class="device_item"hover-class="device_item_hover"><view style="font-size: 16px; color: #333">{{item.name}}</view><view style="font-size: 10px">信号强度: {{item.RSSI}}dBm</view><view style="font-size: 10px">UUID: {{item.deviceId}}</view></view>
</view>
样式部分
/* bluetooth-comp/index.wxss */
.devices_summary {margin-top: 30px;padding: 10px;font-size: 16px;
}.device_item {border-bottom: 1px solid #eee;padding: 10px;color: #666;
}
.device_item_hover {background-color: rgba(0, 0, 0, 0.1);
}
逻辑部分

在 data 中定义变量

// bluetooth-comp/index.js
data:{devices: [],connected: false,chs: []
}

js 文件顶部定义工具方法

function inArray(arr, key, val) {for (let i = 0; i < arr.length; i++) {if (arr[i][key] === val) {return i;}}return -1;
}// 将字符串转为 ArrayBuffer
function str2ab(str) {let buf = new ArrayBuffer(str.length);let bufView = new Uint8Array(buf);for (var i = 0, strLen = str.length; i < strLen; i++) {bufView[i] = str.charCodeAt(i);}return buf;
}

在 methods 中定义方法

// bluetooth-comp/index.js
methods: {/* 初始化蓝牙模块 */openBluetoothAdapter() {// 先关闭蓝牙模块再开启 防止断开后点连接连接不上this.closeBluetoothAdapter();wx.openBluetoothAdapter({success: response => {console.log("初始化蓝牙模块成功:openBluetoothAdapter", response);this.startBluetoothDevicesDiscovery();},fail: err => {if (err.errCode === 10001) {/* 监听蓝牙适配器状态变化事件 */wx.onBluetoothAdapterStateChange(res => {console.log("监听蓝牙适配器状态变化事件:onBluetoothAdapterStateChange", res);res.available && this.startBluetoothDevicesDiscovery();});}},});},/* 获取本机蓝牙适配器状态 */getBluetoothAdapterState() {wx.getBluetoothAdapterState({success: res => {console.log("getBluetoothAdapterState", res);if (res.discovering) {// 是否正在搜索设备this.onBluetoothDeviceFound();} else if (res.available) {// 蓝牙适配器是否可用this.startBluetoothDevicesDiscovery();}},});},/* 开始搜寻附近的蓝牙外围设备 */startBluetoothDevicesDiscovery() {// 开始扫描参数if (this._discoveryStarted) return;this._discoveryStarted = true;wx.startBluetoothDevicesDiscovery({allowDuplicatesKey: true,success: response => {console.log("开始搜寻附近的蓝牙外围设备:startBluetoothDevicesDiscovery", response);this.onBluetoothDeviceFound();},fail: err => {console.log("搜索设备失败", err);wx.showToast({ title: "搜索设备失败", icon: "none" });},});},/* 停止搜寻附近的蓝牙外围设备。*/stopBluetoothDevicesDiscovery() {console.log("停止搜寻附近的蓝牙外围设备");wx.stopBluetoothDevicesDiscovery();},/* 监听搜索到新设备的事件 */onBluetoothDeviceFound() {wx.onBluetoothDeviceFound(res => {res.devices.forEach(device => {if (!device.name && !device.localName) {return;}const foundDevices = this.data.devices;const idx = inArray(foundDevices, "deviceId", device.deviceId);const data = {};if (idx === -1) {data[`devices[${foundDevices.length}]`] = device;} else {data[`devices[${idx}]`] = device;}this.setData(data);});});},/* 连接蓝牙低功耗设备。*/createBLEConnection(e) {const ds = e.currentTarget.dataset;const deviceId = ds.deviceId;const name = ds.name;wx.createBLEConnection({deviceId,success: () => {this.setData({ connected: true, name, deviceId });wx.showToast({ title: "连接蓝牙设备成功", icon: "none" });this.getBLEDeviceServices(deviceId);},fail: e => {console.log("连接失败", e.errMsg);wx.showToast({ title: "连接失败,错误信息: " + e.errMsg, icon: "none" });},});// 停止搜寻蓝牙设备this.stopBluetoothDevicesDiscovery();},/* 断开与蓝牙低功耗设备的连接。 */closeBLEConnection() {console.log("断开与蓝牙低功耗设备的连接");wx.showToast({ title: "已断开和蓝牙设备的连接", icon: "none" });wx.closeBLEConnection({ deviceId: this.data.deviceId });this.setData({ connected: false, chs: [], canWrite: false });},/* 获取蓝牙低功耗设备所有服务 (service) */getBLEDeviceServices(deviceId) {wx.getBLEDeviceServices({deviceId,success: res => {for (let i = 0; i < res.services.length; i++) {if (res.services[i].isPrimary) {this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);return;}}},});},/* 获取蓝牙低功耗设备某个服务中所有特征 (characteristic)。 */getBLEDeviceCharacteristics(deviceId, serviceId) {wx.getBLEDeviceCharacteristics({deviceId,serviceId,success: res => {console.log("获取蓝牙低功耗设备某个服务中所有特征:getBLEDeviceCharacteristics");for (let i = 0; i < res.characteristics.length; i++) {let item = res.characteristics[i];if (item.properties.read) {wx.readBLECharacteristicValue({ deviceId, serviceId, characteristicId: item.uuid });}if (item.properties.write) {this.setData({ canWrite: true });this._deviceId = deviceId;this._serviceId = serviceId;this._characteristicId = item.uuid;//   this.writeBLECharacteristicValue();}if (item.properties.notify || item.properties.indicate) {wx.notifyBLECharacteristicValueChange({deviceId,serviceId,characteristicId: item.uuid,state: true,success(res) {console.log("notifyBLECharacteristicValueChange success", res);},});}}},fail(res) {console.error("getBLEDeviceCharacteristics", res);},});// 操作之前先监听,保证第一时间获取数据wx.onBLECharacteristicValueChange(characteristic => {// TODO 收到的信息为ArrayBuffer类型,可根据自己的需要转换 可发送给父组件用来回显console.log("收到原始的数据", characteristic, characteristic.value);// 测试向设备发送数据// this.writeBLECharacteristicValue(JSON.stringify({"FAN":"OFF"}))});},/* 向蓝牙低功耗设备特征值中写入二进制数据 */writeBLECharacteristicValue(jsonStr) {let arrayBufferValue = str2ab(jsonStr);console.log("发送数据给蓝牙", "原始字符串", jsonStr, "转换arrayBuffer", arrayBufferValue);wx.writeBLECharacteristicValue({deviceId: this._deviceId,serviceId: this._serviceId, // 微信文档上是错误的characteristicId: this._characteristicId,value: arrayBufferValue, // 只能发送arrayBuffer类型数据success(res) {console.log("消息发送成功", res.errMsg);wx.showToast({ title: "消息发送成功", icon: "none" });},fail(e) {console.log("发送消息失败", e);wx.showToast({ title: "发送消息失败,错误信息: " + e.errMsg, icon: "none" });},});},closeBluetoothAdapter() {console.log("关闭蓝牙模块");wx.closeBluetoothAdapter();this._discoveryStarted = false;},
};

最终效果

界面

界面

真机调试结果

真机调试结果


嵌入式物联网教学开发 传感器控制拓展板二合一

不同于其他卖家提供资料和技术支持,我们提供手把手教学,完整的开发流程如下:

实现完整的一个物联网嵌入式项目:将数据上传并通过小程序对硬件进行控制。具体有:

[1]服务器配置,阿里云搭建mqttx服务器,ssl证书配置;

[2]微信小程序设计,借助微信开发者工具开发,js代码和类html语言;

[3]硬件驱动,基于Arduino平台开发esp32,提供wifi和蓝牙版本,读取传感器:温度、湿度、烟雾;控制设备:小灯、继电器。

提供教学视频在b站,合集播放破6w!提供项目开发文档,网页链接。

我们提供搭建好的mqtt测试服务器,供大家免费使用。

适合如下人群:

1.喜欢diy的电子极客;

2.物联网专业的相关学生课程或毕业设计;

3.寻求物联网项目经验的求职者;

有硬件工程师和软件工程师答疑,欢迎咨询~

文档资料,可参考:基于ESP32+微信小程序的物联网应用开发文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/704309.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【mysql】mysql导入导出数据详解

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

翻译《The Old New Thing》- What does the CS_OWNDC class style do?

What does the CS_OWNDC class style do? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20060601-06/?p31003 Raymond Chen 2006年06月01日 简要 本文讨论了CS_OWNDC窗口类样式的影响&#xff0c;它让窗口管理器为窗口创建一个永久的设…

高通QCS6490开发(三):点亮板卡

QCS6490是高通公司针对高端物联网终端而优化的SoC&#xff0c;在性能和功耗上有最优的平衡。《高通QCS6490 AIoT应用开发》是介绍如何基于QCS6490平台完成AIIoT的应用开发的系列文章。 本期主要介绍介绍如何点亮FV01开发板。 以下步骤介绍如何点亮FV01开发板步骤 1、将12V/5A…

人物介绍模板 PSD 源文件免费获取

免费获取 下载链接在最后&#xff01; 下载链接在最后&#xff01; 下载链接在最后&#xff01; 下载链接在最后&#xff01; 下载链接在最后&#xff01; 链接&#xff1a;https://pan.baidu.com/s/1sq3e6djMdZt76Sh_uqVxWg 提取码&#xff1a;naun

Gini Impurity(基尼不纯度)

基尼不纯度&#xff1a;衡量集合的无序程度&#xff1b; 基尼不纯度 基尼不纯度&#xff1a;将来自集合的某种结果随机应用于某一数据项的预期误差率。 1、显然基尼不纯度越小&#xff0c;纯度越高&#xff0c;集合的有序程度越高&#xff0c;分类的效果越好&#xff1b; 2、…

广告小白必看|谷歌Google Ads被封禁原因是什么,如何防范?

跨境出海业务少不了需要做Google Ads推广业务&#xff1b;其中让投手们闻风丧胆的消息就是帐户被暂停。当 Google 检测到任何违反其政策且可能损害用户在线体验的行为时&#xff0c;就会发生这种情况。那么如何在做广告推广的同时&#xff0c;保证账号不被封禁呢&#xff1f;看…

独立静态ISP:互联网连接的新选择

在数字化时代&#xff0c;互联网连接的质量直接影响着我们的工作与生活。随着技术的发展&#xff0c;独立静态ISP&#xff08;Internet Service Provider&#xff0c;互联网服务提供商&#xff09;逐渐成为企业和个人用户关注的焦点。本文将从五个方面探讨独立静态ISP的优势、应…

异步I/O库-libuv介绍

1.简介 libuv是一个跨平台的支持事件驱动的异步I/O的库&#xff0c;使开发者可以以非阻塞的方式执行文件I/O操作、网络通信、子进程管理等。 libuv的主要特点包括&#xff1a; 事件循环&#xff1a;libuv有一个基于事件循环的模型&#xff0c;它不断地轮询事件&#xff0c;并…

【2024年电工杯数学建模竞赛】选题分析+A题B题完整思路+代码分享

.2024年电工杯数学建模AB题选题思路 比赛开始第一时间在下面的资料裙分享&#xff1a; 点击链接加入群聊【2024数维杯数学建模ABC题资料汇总】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kBwulH5tSN2X7iLXzZHAJqRk9sYnegd0y&authKey2TSsuOgqXZQ%2FvTX4R59…

Java面试八股之Java中有哪些原子类,原理是什么

Java中有哪些原子类&#xff0c;原理是什么 AtomicInteger 和 AtomicLong&#xff1a; 用于对整数&#xff08;int&#xff09;和长整数&#xff08;long&#xff09;进行原子操作。 原理&#xff1a;它们内部封装了一个整型或长整型变量&#xff0c;并通过使用Unsafe类提供…

手机如何下载短视频到本地:成都鼎茂宏升文化传媒公

手机如何下载短视频到本地 ​随着移动互联网的迅猛发展&#xff0c;短视频已经成为人们生活中不可或缺的一部分。从娱乐、学习到社交&#xff0c;短视频以其短小精悍、内容丰富的特点&#xff0c;吸引了大量用户的关注。然而&#xff0c;有时我们可能希望将喜欢的短视频保存到…

jspXMl标记语言基础

1.打开命令框进入数据库 打开eclipse创建需要连接的项目 粘贴驱动程序 查看驱动器 使用sql的包 int代表个 conlm代表列名 <%page import"java.sql.ResultSet"%> <%page import"java.sql.Statement"%> <%page import"java.sql.Connect…