微信小程序 藍牙設備連接,控制開關燈

1.前言

微信小程序中連接藍牙設備,信息寫入流程
1、檢測當前使用設備(如自己的手機)是否支持藍牙/藍牙開啟狀態
wx:openBluetoothAdapter({})
2、如藍牙已開啟狀態,檢查藍牙適配器的狀態
wx.getBluetoothAdapterState({})
3、添加監聽藍牙適配器狀態變化
wx.onBluetoothAdapterStateChange({})
4、搜索附近藍牙設備
wx.startBluetoothDevicesDiscovery({})
5、監聽搜索的到設備
wx.onBluetoothDeviceFound({})
遍歷設備列表找到和macAddr(看自己家的藍牙裝置的物理地址)匹配的設備的deviceId
6、連接想要連接的切匹配成功的設備
wx.createBLEConnection({})
7、獲取連接成功的設備的設備服務servicesID
wx.getBLEDeviceServices({})
8、獲取設備特征id
wx.getBLEDeviceCharacteristics({})
9、向設備寫入指令
wx.writeBLECharacteristicValue({})

以下是代碼重點,本人親測有效,集官網和百家之所長,匯聚之大成,入我門來,使君不負觀賞

#2. 小程序前端index.wxml

<wxs module="utils">
module.exports.max = function(n1, n2) {return Math.max(n1, n2)
}
module.exports.len = function(arr) {arr = arr || []return arr.length
}
</wxs>
<button bindtap="openBluetoothAdapter"   class="primary-btn" >開始掃描</button>
<button bindtap="closeBLEConnection"  class="default-btn" >斷開連接</button>
<button bindtap="opendeng"   class="sumit-btn" >開燈</button>
<button bindtap="guandeng"   class="warn-btn" >關燈</button><view class="devices_summary">已發現 {{devices.length}} 個外圍設備:</view>
<scroll-view class="device_list" scroll-y scroll-with-animation><view wx: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 ({{utils.max(0, item.RSSI + 100)}}%)</view><view style="font-size: 10px">UUID: {{item.deviceId}}</view><view style="font-size: 10px">Service數量: {{utils.len(item.advertisServiceUUIDs)}}</view></view>
</scroll-view><view class="connected_info" wx:if="{{connected}}"><view><icon class="icon-box-img" type="success" size="33"></icon><view class="icon-box-text"> {{name}}連接成功!!!</view></view> </view>

3.小程序index.wxss


page {color: #333;
}
.icon-box-img{height: 20px;float: left;margin-left: 20%;
}
.icon-box-text{height: 30px;line-height: 30px;margin-left:5px;float: left;
}.primary-btn{margin-top: 30rpx;/* border: rgb(7, 80, 68) 1px solid; */color: rgb(241, 238, 238);background-color: rgb(14, 207, 46);
}
.default-btn{margin-top: 30rpx;/* border: #333 1px solid; */color: rgb(243, 236, 236);background-color: rgb(189, 112, 25);
}.warn-btn{margin-top: 30rpx;/* border: #333 1px solid; */color: rgb(240, 231, 231);background-color: rgb(235, 10, 10);
}
.sumit-btn{margin-top: 30px;width: 60px;color: rgb(240, 231, 231);background-color: rgb(10, 100, 235);
}.devices_summary {margin-top: 30px;padding: 10px;font-size: 16px;
}
.device_list {height: 300px;margin: 50px 5px;margin-top: 0;border: 1px solid #EEE;border-radius: 5px;width: auto;
}
.device_item {border-bottom: 1px solid #EEE;padding: 10px;color: #666;
}
.device_item_hover {background-color: rgba(0, 0, 0, .1);
}
.connected_info {position: fixed;bottom: 10px;width: 80%;margin-left: 6%;background-color: #F0F0F0;padding: 10px;padding-bottom: 20px;margin-bottom: env(safe-area-inset-bottom);font-size: 18px;/* line-height: 20px; */color: #1da54d;text-align: center;/* height: 20px; */box-shadow: 0px 0px 3px 0px;
}
.connected_info .operation {position: absolute;display: inline-block;right: 30px;
}

4.小程序 index.ts


const app = getApp()function inArray(arr, key, val) {for (let i = 0; i < arr.length; i++) {if (arr[i][key] === val) {return i;}}return -1;
}// ArrayBuffer轉16進度字符串示例
function ab2hex(buffer) {var hexArr = Array.prototype.map.call(new Uint8Array(buffer),function (bit) {return ('00' + bit.toString(16)).slice(-2)})return hexArr.join('');
}Page({data: {devices: [],connected: false,chs: [],},getCeshi() {wx.navigateTo({url: '/pages/main/main',})},// 搜尋周邊藍牙openBluetoothAdapter() {//console.log('openBluetoothAdapter success')wx.openBluetoothAdapter({success: (res) => {console.log('openBluetoothAdapter success', res)this.startBluetoothDevicesDiscovery()},fail: (res) => {if (res.errCode === 10001) {wx.onBluetoothAdapterStateChange(function (res) {console.log('onBluetoothAdapterStateChange', res)if (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 = truewx.startBluetoothDevicesDiscovery({allowDuplicatesKey: true,success: (res) => {console.log('startBluetoothDevicesDiscovery success', res)this.onBluetoothDeviceFound()},})},//停止搜尋附近的藍牙外圍設備。若已經找到需要的藍牙設備并不需要繼續搜索時,建議調用該接口停止藍牙搜索。stopBluetoothDevicesDiscovery() {wx.stopBluetoothDevicesDiscovery()},//監聽搜索到新設備的事件onBluetoothDeviceFound() {wx.onBluetoothDeviceFound((res) => {res.devices.forEach(device => {if (!device.name && !device.localName) {return}const foundDevices = this.data.devicesconst 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.datasetconst deviceId = ds.deviceIdconst name = ds.namewx.createBLEConnection({deviceId,success: (res) => {this.setData({connected: true,name,deviceId,})this.getBLEDeviceServices(deviceId)}})this.stopBluetoothDevicesDiscovery()},closeBLEConnection() {wx.closeBLEConnection({deviceId: this.data.deviceId})this.setData({connected: false,chs: [],canWrite: false,})},//獲取藍牙低功耗設備所有服務。getBLEDeviceServices(deviceId) {console.log('deviceId ========', deviceId)wx.getBLEDeviceServices({deviceId,success: (res) => {for (let i = 0; i < res.services.length; i++) {//獲取通過設備id多個特性服務serviceid (包含 讀、寫、通知、等特性服務)//   console.log('serviceId ========', res.services[2].uuid)// 通過上邊注釋解封,排查到判斷服務id 中第三個服務id  代表寫入服務//  isPrimary代表 :判斷服務id是否為主服務// if (res.services[2].isPrimary) {//  this.getBLEDeviceCharacteristics(deviceId, res.services[2].uuid)//  }//判斷通過(設備id獲取的多個特性服務)中是否有與(藍牙助手獲取的寫入特性服務),相一致的serviceidif (res.services[i].uuid=="0000FFE0-0000-1000-8000-00805F9B34FB") {this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) }}}})},//獲取藍牙低功耗設備某個服務中所有特征 (characteristic)。getBLEDeviceCharacteristics(deviceId, serviceId) {console.info("藍牙的deviceId====" + deviceId);console.info("藍牙服務的serviceId====" + serviceId);wx.getBLEDeviceCharacteristics({deviceId,serviceId,success: (res) => {console.log('getBLEDeviceCharacteristics success', res.characteristics)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 = deviceIdthis._serviceId = serviceIdthis._characteristicId = item.uuidconsole.info("寫入(第一步)的characteristicId====" + item.uuid);//初始化調用 寫入信息的方法  1:代表開燈this.writeBLECharacteristicValue("1")}if (item.properties.notify || item.properties.indicate) {wx.notifyBLECharacteristicValueChange({deviceId,serviceId,characteristicId: item.uuid,state: true,})}}},fail(res) {console.error('getBLEDeviceCharacteristics', res)}})// 操作之前先監聽,保證第一時間獲取數據wx.onBLECharacteristicValueChange((characteristic) => {const idx = inArray(this.data.chs, 'uuid', characteristic.characteristicId)const data = {}if (idx === -1) {data[`chs[${this.data.chs.length}]`] = {uuid: characteristic.characteristicId,value: ab2hex(characteristic.value)}} else {data[`chs[${idx}]`] = {uuid: characteristic.characteristicId,value: ab2hex(characteristic.value)}}this.setData(data)})},/*** 寫入的數據 格式轉換* @param str* @returns 字符串 轉 ArrayBuffer*/
hex2buffer(str) {console.info("寫入的數據====" + str);//字符串 轉 十六進制var val = "";for (var i = 0; i < str.length; i++) {if (val == "")val = str.charCodeAt(i).toString(16);elseval += "," + str.charCodeAt(i).toString(16);}//十六進制 轉 ArrayBuffervar buffer = new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) {return parseInt(h, 16)})).buffer;return buffer;
},
//開燈
opendeng() {// 調用寫入信息的方法 向藍牙設備發送一個開燈的參數數據 ,  1:代表開燈var writeValue ="1";this.writeBLECharacteristicValue(writeValue)},
//關燈
guandeng() {// 調用寫入信息的方法 向藍牙設備發送一個關燈的參數數據 ,  0:代表關燈var writeValue ="0";this.writeBLECharacteristicValue(writeValue)},
writeBLECharacteristicValue(writeValue) {// 向藍牙設備發送一個0x00的16進制數據// let buffer = new ArrayBuffer(1)// let dataView = new DataView(buffer)//  dataView.setUint8(0, 0)//調用hex2buffer()方法,轉化成ArrayBuffer格式console.log('獲取傳遞參數writeValue的數據為=====',writeValue)var buffer =this.hex2buffer(writeValue);console.log('獲取二進制數據',buffer)//向低功耗藍牙設備特征值中寫入二進制數據。wx.writeBLECharacteristicValue({deviceId: this._deviceId,serviceId: this._serviceId,characteristicId: this._characteristicId,value: buffer,success (res) {console.log('成功寫數據writeBLECharacteristicValue success', res)//如果 uni.writeBLECharacteristicValue 走 success ,證明你已經把數據向外成功發送了,但不代表設備一定就收到了。通常設備收到你發送過去的信息,會返回一條消息給你,而這個回調消息會在 uni.onBLECharacteristicValueChange 觸發},fail(res) {console.error('失敗寫數據getBLEDeviceCharacteristics', res)}})
},
//斷開與藍牙低功耗設備的連接。closeBluetoothAdapter() {wx.closeBluetoothAdapter()this._discoveryStarted = false},
})

5.疑難點

1.如果你不確定寫入的特性服務值可以通過(安卓)藍牙助手獲取特性值 deviceId(mac地址)、serviceId、characteristicId(蘋果手機)藍牙助手獲得特性值deviceId(uuid地址)、serviceId、characteristicId  

注意:手機品類不同獲取的deviceId的名稱不同,但serviceId、characteristicId,是相同的

1.安卓手機(藍牙助手獲取的信息)
在這里插入圖片描述
在這里插入圖片描述

2.蘋果手機(藍牙助手)獲取的信息

在這里插入圖片描述
在這里插入圖片描述

FFF0代表的serviceId全稱:0000FFF0-0000-1000-8000-00805F9B34FB

FFF3代表的characteristicId全稱:0000FFF3-0000-1000-8000-00805F9B34FB

最后:

祝愿你能一次成功
(代碼直接復制粘貼到你的小程序中,替換下你自己設備的寫入特性serviceId值),
就可以測試了
最后如果還滿意,記得點下贊、收藏加關注、我也好回關,相互進步!!!!!!!!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41632.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41632.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41632.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第十三章 SpringBoot項目(總)

1.創建SpringBoot項目 1.1.設置編碼 1.4.導入已有的spring boot項目 2.快速搭建Restfull風格的項目 2.1.返回字符串 RestController public class IndexController {RequestMapping("/demo1")public Object demo1() {System.out.println("demo1 ran...."…

kafka的位移

文章目錄 概要消費位移__consumer_offsets主題位移提交 概要 本文主要總結kafka的位移是如何管理的&#xff0c;在broker端如何通過命令行查看到位移信息&#xff0c;并從代碼層面總結了位移的提交方式。 消費位移 對于 Kafka 中的分區而言&#xff0c;它的每條消息都有唯一…

0基礎學習VR全景平臺篇 第86篇:智慧眼-為什么要設置分組選擇?

一、功能說明 分組選擇&#xff0c;也就是給全景的每個分組去設置其所屬的行政區劃&#xff0c;設置后只有屬于同行政區劃的成員才可進入其場景進行相關操作&#xff0c;更便于實現城市的精細化管理。 二、后臺編輯界面 分組名稱&#xff1a;場景的分組名稱。 對應分類&…

網絡安全--linux下Nginx安裝以及docker驗證標簽漏洞

目錄 一、Nginx安裝 二、docker驗證標簽漏洞 一、Nginx安裝 1.首先創建Nginx的目錄并進入&#xff1a; mkdir /soft && mkdir /soft/nginx/cd /soft/nginx/ 2.下載Nginx的安裝包&#xff0c;可以通過FTP工具上傳離線環境包&#xff0c;也可通過wget命令在線獲取安裝包…

【數據結構與算法】隊列

文章目錄 一&#xff1a;隊列1.1 隊列的概念1.2 隊列的介紹1.3 隊列示意圖 二&#xff1a;數組模擬隊列2.1 介紹2.2 思路2.3 代碼實現2.3.1 定義隊列基本信息2.3.2 初始化隊列2.3.3 判斷隊列是否滿&#xff0c;是否為空2.3.4 添加數據到隊列2.3.5 獲取隊列數據&#xff0c;出隊…

垃圾回收機制

什么是內存泄漏&#xff1f; 內存泄漏是指程序中已經不再使用的內存卻沒有被正確釋放或回收的情況。在編程中&#xff0c;當對象或數據不再被程序使用&#xff0c;但其所占用的內存空間沒有被垃圾回收機制回收&#xff0c;就會導致內存泄漏。 內存泄漏可能會導致程序的內存消…

圖數據庫_Neo4j和SpringBoot整合使用_創建節點_刪除節點_創建關系_使用CQL操作圖譜---Neo4j圖數據庫工作筆記0009

首先需要引入依賴 springboot提供了一個spring data neo4j來操作 neo4j 可以看到它的架構 這個是下載下來的jar包來看看 有很多cypher對吧 可以看到就是通過封裝的驅動來操作graph database 然后開始弄一下 首先添加依賴

【實用黑科技】如何 把b站的緩存視頻弄到本地——數據恢復軟件WinHex 和 音視頻轉碼程序FFmpeg

&#x1f468;?&#x1f4bb;個人主頁&#xff1a;元宇宙-秩沅 &#x1f468;?&#x1f4bb; hallo 歡迎 點贊&#x1f44d; 收藏? 留言&#x1f4dd; 加關注?! &#x1f468;?&#x1f4bb; 本文由 秩沅 原創 &#x1f468;?&#x1f4bb; 收錄于專欄&#xff1a;效率…

onnxruntime 支持的所有后端

1 代碼導出 import onnxruntime as ort aaa ort.get_all_providers() print(aaa)1. 1 下面是ort支持的所有后端 TensorrtExecutionProvider, CUDAExecutionProvider, MIGraphXExecutionProvider, ROCMExecutionProvider, OpenVINOExecutionProvider, DnnlExecutionProvider…

Baumer工業相機堡盟工業相機如何通過BGAPISDK設置相機的固定幀率(C#)

Baumer工業相機堡盟工業相機如何通過BGAPI SDK設置相機的固定幀率&#xff08;C#&#xff09; Baumer工業相機Baumer工業相機的固定幀率功能的技術背景CameraExplorer如何查看相機固定幀率功能在BGAPI SDK里通過函數設置相機固定幀率 Baumer工業相機通過BGAPI SDK設置相機固定幀…

藍牙資訊|中國智能家居前景廣闊,藍牙Mesh照明持續火爆

據俄羅斯衛星通訊社報道&#xff0c;中國已成為全球最大的智能家居消費國&#xff0c;占全球50%—60%的市場份額。未來&#xff0c;隨著人工智能技術的發展以及智能家居生態的不斷進步&#xff0c;智能家居在中國的滲透率將加速提升。德國斯塔蒂斯塔調查公司數據顯示&#xff0…

win10系統docker創建ubuntu容器解決開發環境問題

一、win10系統使用docker的原因 最近啊&#xff0c;在學習人工智能-深度學習&#xff0c;用的win10系統進行開發&#xff0c;老是出現一些莫名其妙的問題&#xff0c;無法解決&#xff0c;每天都在為環境問題搞得傷透了腦筋。 說到底還是要使用Linux系統進行開發比較合適。 …

【MT32F006】MT32F006之HT1628驅動LED

本文最后修改時間&#xff1a;2023年03月30日 一、本節簡介 本文介紹如何使用MT32F006連接HT1628芯片驅動LED。 二、實驗平臺 庫版本&#xff1a;V1.0.0 編譯軟件&#xff1a;MDK5.37 硬件平臺&#xff1a;MT32F006開發板&#xff08;主芯片MT32F006&#xff09; 仿真器&a…

LeetCode算法心得——限制條件下元素之間的最小絕對差(TreeSet)

大家好&#xff0c;我是晴天學長&#xff0c;今天用到了Java一個非常實用的類TreeSet&#xff0c;能解決一些看起來棘手的問題。 1 &#xff09;限制條件下元素之間的最小絕對差 2) .算法思路 初始化變量&#xff1a;n為列表nums的大小。 min為整型最大值&#xff0c;用于記錄…

python3 0學習筆記之基本知識

0基礎學習筆記之基礎知識 &#x1f4da; 基礎內容1. 條件語句 if - elif - else2. 錯誤鋪捉try - except(一種保險策略&#xff09;3. 四種開發模式4. 函數&#xff1a;def用來定義函數的5. 最大值最小值函數&#xff0c;max &#xff0c;min6. is 嚴格的相等&#xff0c;is no…

機器學習:基本介紹

機器學習介紹 Hnad-crafted rules Hand-crafted rules&#xff0c;叫做人設定的規則。那假設今天要設計一個機器人&#xff0c;可以幫忙打開或關掉音樂&#xff0c;那做法可能是這樣&#xff1a; 設立一條規則&#xff0c;就是寫一段程序。如果輸入的句子里面看到**“turn of…

C#__使用Type類反射數據的基本用法

// 簡單介紹 // 元數據&#xff08;metadata&#xff09;&#xff1a;與程序及其類型有關的數據。 // 反射&#xff1a;一個運行的程序查看本身元數據或其他程序集中的元數據的行為 // Assembly類&#xff1a;允許訪問給定程序集的元數據&#xff0c;包含了可以加載和執行程序…

Maven框架SpringBootWeb簡單入門

一、Maven ★ Maven:是Apache旗下的一個開源項目,是一款用于管理和構建java項目的工具。 官網:https://maven.apache.org/ ★ Maven的作用: 1. 依賴管理:方便快捷的管理項目依賴的資源(jar包),避免版本沖突問題。 2. 統一項目結構:提供標準、統一的項目結構。 …

LightDB 23.3 plorasql 函數支持inout參數輸出

開篇立意 oracle PLSQL函數中返回值有兩種情況&#xff1a; &#xff08;1&#xff09;使用return返回值&#xff1b; &#xff08;2&#xff09;使用out修飾的參數&#xff08;oracle不支持inout&#xff09; SQL> create function yu(id inout int) return int asbeginn…

【C# 基礎精講】文件讀取和寫入

文件讀取和寫入是計算機程序中常見的操作&#xff0c;用于從文件中讀取數據或將數據寫入文件。在C#中&#xff0c;使用System.IO命名空間中的類來進行文件讀寫操作。本文將詳細介紹如何在C#中進行文件讀取和寫入&#xff0c;包括讀取文本文件、寫入文本文件、讀取二進制文件和寫…