Nama: wx-sederhana-bluetooth
Platform yang berlaku: applet WeChat
Bluetooth: Bluetooth Hemat Energi
Versi proyek: 2.0.1
Proyek ini dirancang dari tiga level: koneksi Bluetooth, komunikasi protokol Bluetooth, langganan status, dan pemberitahuan. Ini dapat dengan mudah menyesuaikan pengembangan Bluetooth dari program mini Anda sendiri. Fungsi utamanya adalah sebagai berikut:
!!!Anda harus mengaktifkan kompilasi alat pengembangan WeChat yang disempurnakan terlebih dahulu!!!
这个项目从蓝牙连接、蓝牙协议通信、状态订阅及通知三个层面进行设计,可以很方便的定制您自己的小程序的蓝牙开发。主要功能如下
:
Berikut ini adalah kasus ketika fungsi Bluetooth, izin pemosisian GPS dan WeChat diaktifkan di ponsel:
getAppBLEManager.connect()
akan secara otomatis memindai perangkat Bluetooth di sekitarnya setiap 350ms
, dan terhubung ke perangkat dengan sinyal terkuat dalam waktu tersebut.uuid
service
utama dan ID layanan terkait yang digunakan untuk komunikasi; Anda juga dapat menambahkan nama perangkat Bluetooth tambahan untuk memfilter perangkat lebih lanjut.注意:目前在发送数据时大于20包的数据会被裁剪为20包
. (有些蓝牙连接问题是微信兼容或是手机问题,目前是无法解决的。如错误码10003以及部分华为手机蓝牙连接或重连困难。如果您有很好的解决方案,还请联系我,十分感谢)
lb-example-bluetooth-manager.js
untuk detailnya.Oleh karena itu, berdasarkan pertimbangan tersebut, kerangka kerja ini mempunyai kendala sebagai berikut:
- Perjanjian tersebut harus dirumuskan sesuai dengan format perjanjian yang telah disepakati agar kerangka tersebut dapat digunakan secara normal.
- Jumlah maksimum data dalam satu paket protokol adalah 20 byte. Kerangka kerja ini tidak mendukung format protokol yang lebih besar dari 20 byte. Jika data melebihi batas, disarankan untuk membaginya menjadi beberapa pengiriman.
- Disarankan untuk melakukan operasi penulisan dalam mode serial.
- Disarankan untuk terlebih dahulu memahami dokumentasi resmi Bluetooth dari program mini untuk memfasilitasi pemahaman tentang penggunaan kerangka kerja.
协议约定格式:[...命令字之前的数据(非必需), 命令字(必需), ...有效数据(非必需 如控制灯光发送255,255,255), 有效数据之后的数据(非必需 如协议结束标志校、验位等)
协议格式示例:[170(帧头), 10(命令字), 1(灯光开启),255,255,255(三个255,白色灯光),233(协议结束标志,有的协议中没有这一位),18(校验位,我胡乱写的)]
有效数据是什么:
在刚刚的这个示例中,帧头、协议结束标志是固定的值,校验位是按固定算法生成的,这些不是有效数据。而1,255,255,255这四个字节是用于控制蓝牙设备的,属于有效数据。
Jika proyek ini bermanfaat, saya berharap dapat memberikannya bintang di GitHub!
modules
di bawah proyek ke proyek Anda import Toast from "../../view/toast";
import UI from './ui';
import {ConnectState} from "../../modules/bluetooth/lb-bluetooth-state-example";
import {getAppBLEProtocol} from "../../modules/bluetooth/lb-example-bluetooth-protocol";
import {getAppBLEManager} from "../../modules/bluetooth/lb-example-bluetooth-manager";
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
connectState: ConnectState.UNAVAILABLE
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.ui = new UI(this);
console.log(app);
//监听蓝牙连接状态、订阅蓝牙协议接收事件
//多次订阅只会在最新订阅的函数中生效。
//建议在app.js中订阅,以实现全局的事件通知
getAppBLEManager.setBLEListener({
onConnectStateChanged: async (res) => {
const {connectState} = res;
console.log('蓝牙连接状态更新', res);
this.ui.setState({state: connectState});
switch (connectState) {
case ConnectState.CONNECTED:
//在连接成功后,紧接着设置灯光颜色和亮度
//发送协议,官方提醒并行调用多次会存在写失败的可能性,所以建议使用串行方式来发送
await getAppBLEProtocol.setColorLightAndBrightness({
brightness: 100,
red: 255,
green: 0,
blue: 0
});
break;
default:
break;
}
},
/**
* 接收到的蓝牙设备传给手机的有效数据,只包含你最关心的那一部分
* protocolState和value具体的内容是在lb-example-bluetooth-protocol.js中定义的
*
* @param protocolState 蓝牙协议状态值,string类型,值是固定的几种,详情示例见:
* @param value 传递的数据,对应lb-example-bluetooth-protocol.js中的{effectiveData}字段
*/
onReceiveData: ({protocolState, value}) => {
console.log('蓝牙协议接收到新的 protocolState:', protocolState, 'value:', value);
}
});
//这里执行连接后,程序会按照你指定的规则(位于getAppBLEManager中的setFilter中指定的),自动连接到距离手机最近的蓝牙设备
getAppBLEManager.connect();
},
/**
* 断开连接
* @param e
* @returns {Promise<void>}
*/
async disconnectDevice(e) {
// closeAll() 会断开蓝牙连接、关闭适配器
await getAppBLEManager.closeAll();
this.setData({
device: {}
});
setTimeout(Toast.success, 0, '已断开连接');
},
/**
* 连接到最近的设备
*/
connectHiBreathDevice() {
getAppBLEManager.connect();
},
async onUnload() {
await getAppBLEManager.closeAll();
},
});
setFilter
Anda sendiri dan aturan pemfilteran pemindaian (opsional) File terletak di ./modules/bluetooth/lb-example-bluetooth-manager.js
import {LBlueToothManager} from "./lb-ble-common-connection/index";
import {getAppBLEProtocol} from "./lb-example-bluetooth-protocol";
/**
* 蓝牙连接方式管理类
* 初始化蓝牙连接时需筛选的设备,重写蓝牙连接规则
*/
export const getAppBLEManager = new class extends LBlueToothManager {
constructor() {
super();
//setFilter详情见父类
super.setFilter({
services: ['0000xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'],//必填
targetServiceArray: [{
serviceId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',//必填
writeCharacteristicId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxE',//必填
notifyCharacteristicId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxF',//必填
readCharacteristicId: '',//非必填
}],
targetDeviceName: '目标蓝牙设备的广播数据段中的 LocalName 数据段,如:smart-voice',//非必填,在判断时是用String.prototype.includes()函数来处理的,所以targetDeviceName不必是全称
scanInterval: 350//扫描周围设备,重复上报的时间间隔,毫秒制,非必填,默认是350ms
});
super.initBLEProtocol({bleProtocol: getAppBLEProtocol});
//setMyFindTargetDeviceNeedConnectedFun函数调用可选,不实现过滤规则框架会按默认规则执行
super.setMyFindTargetDeviceNeedConnectedFun({
/**
* 重复上报时的过滤规则,并返回过滤结果
* 在执行完该过滤函数,并且该次连接蓝牙有了最终结果后,才会在下一次上报结果回调时,再次执行该函数。
* 所以如果在一次过滤过程中或是连接蓝牙,耗时时间很长,导致本次连接结果还没得到,就接收到了下一次的上报结果,则会忽略下一次{scanFilterRuler}的执行。
* 如果不指定这个函数,则会使用默认的连接规则
* 默认的连接规则详见 lb-ble-common-connection/utils/device-connection-manager.js的{defaultFindTargetDeviceNeedConnectedFun}
* @param devices {*}是wx.onBluetoothDeviceFound(cb)中返回的{devices}
* @param targetDeviceName {string}是{setFilter}中的配置项
* @returns targetDevice 最终返回对象{targetDevice},是数组{devices}其中的一个元素;{targetDevice}可返回null,意思是本次扫描结果未找到指定设备
*/
scanFilterRuler: ({devices, targetDeviceName}) => {
console.log('执行自定义的扫描过滤规则');
const tempFilterArray = [];
for (let device of devices) {
if (device.localName?.includes(targetDeviceName)) {
tempFilterArray.push(device);
}
}
if (tempFilterArray.length) {
const device = tempFilterArray.reduce((pre, cur) => {
return pre.RSSI > cur.RSSI ? pre : cur;
});
return {targetDevice: device};
}
return {targetDevice: null};
}
})
}
/**
* 获取本机蓝牙适配器状态
* @returns {Promise<*>} 返回值见小程序官网 wx.getBluetoothAdapterState
*/
async getBLEAdapterState() {
return await super.getBLEAdapterState();
}
/**
* 获取最新的蓝牙连接状态
* @returns {*}
*/
getBLELatestConnectState() {
return super.getBLELatestConnectState();
}
}();
File terletak di ./modules/bluetooth/lb-ble-example-protocol-body
//send-body.js
import {IBLEProtocolSendBody} from "../lb-ble-common-protocol-body/index";
import {HexTools} from "../lb-ble-common-tool/index";
/**
* 组装蓝牙协议发送数据示例
* 该框架的蓝牙协议必须按照约定格式来制定,最多20个字节
*/
export default class SendBody extends IBLEProtocolSendBody {
getDataBeforeCommandData({command, effectiveData} = {}) {
//有效数据前的数据 该示例只返回了帧头110
return [110];
}
getDataAfterEffectiveData({command, effectiveData} = {}) {
//协议结束标志
const endFlag = 233;
//该示例中checkSum的生成规则是计算协议从第0个元素累加到结束标志
let checkSum = endFlag + HexTools.hexToNum(command);
for (let item of this.getDataBeforeCommandData()) {
checkSum += item;
}
for (let item of effectiveData) {
checkSum += item;
}
//生成有效数据之后的数据
return [endFlag, checkSum];
}
}
//receive-body.js
import {IBLEProtocolReceiveBody} from "../lb-ble-common-protocol-body/index";
/**
* 组装蓝牙协议接收数据示例
* 该框架的蓝牙协议必须按照约定格式来制定,最多20个字节
*/
export default class ReceiveBody extends IBLEProtocolReceiveBody {
constructor() {
//commandIndex 命令字位置索引
//effectiveDataStartIndex 有效数据开始索引,比如:填写0,{getEffectiveReceiveDataLength}中返回20,则会在{LBlueToothProtocolOperator}的子类{getReceiveAction}实现中,在参数中返回所有数据
super({commandIndex: 1, effectiveDataStartIndex: 0});
}
/**
* 获取有效数据的字节长度
* 该长度可根据接收到的数据动态获取或是计算,或是写固定值均可
* 有效数据字节长度是指,在协议中由你的业务规定的具有特定含义的值的总字节长度
* 有效数据更多的说明,以及该长度的计算规则示例,见 IBLEProtocolReceiveBody 类的 {getEffectiveReceiveData}函数
*
* @param receiveArray 接收到的一整包数据
* @returns {number} 有效数据的字节长度
*/
getEffectiveReceiveDataLength({receiveArray}) {
return 20;
}
}
Terletak di modules/bluetooth/lb-example-bluetooth-protocol.js
import {LBlueToothProtocolOperator} from "./lb-ble-common-protocol-operator/index";
import SendBody from "./lb-ble-example-protocol-body/send-body";
import ReceiveBody from "./lb-ble-example-protocol-body/receive-body";
import {ProtocolState} from "./lb-bluetooth-state-example";
/**
* 蓝牙协议管理类
* 在这个类中,以配置的方式来编写读操作和写操作
* 配置方式见下方示例
*/
export const getAppBLEProtocol = new class extends LBlueToothProtocolOperator {
constructor() {
super({protocolSendBody: new SendBody(), protocolReceiveBody: new ReceiveBody()});
}
/**
* 写操作(仅示例)
*/
getSendAction() {
return {
/**
* 0x01:设置灯色(写操作)
* @param red 0x00 - 0xff
* @param green 0x00 - 0xff
* @param blue 0x00 - 0xff
* @returns {Promise<void>}
*/
'0x01': async ({red, green, blue}) => {
return await this.sendProtocolData({command: '0x01', effectiveData: [red, green, blue]});
},
/**
* 0x02:设置灯亮度(写操作)
* @param brightness 灯亮度值 0~100 对应最暗和最亮
* @returns {Promise<void>}
*/
'0x02': async ({brightness}) => {
//data中的数据,填写多少个数据都可以,可以像上面的3位,也可以像这条6位。你只要能保证data的数据再加上你其他的数据,数组总长度别超过20个就行。
return await this.sendProtocolData({command: '0x02', effectiveData: [brightness, 255, 255, 255, 255, 255]});
},
}
}
/**
* 读操作(仅示例)
* {dataArray}是一个数组,包含了您要接收的有效数据。
* {dataArray}的内容是在lb-ble-example-protocol-body.js中的配置的。
* 是由您配置的 dataStartIndex 和 getEffectiveReceiveDataLength 共同决定的
*/
getReceiveAction() {
return {
/**
* 获取设备当前的灯色(读)
* 可return蓝牙协议状态protocolState和接收到的数据effectiveData,
* 该方法的返回值,只要拥有非空的protocolState,该框架便会同步地通知前端同protocolState类型的消息
* 当然是在你订阅了setBLEListener({onReceiveData})时才会在订阅的地方接收到消息。
*/
'0x10': ({dataArray}) => {
const [red, green, blue] = dataArray;
return {protocolState: ProtocolState.RECEIVE_COLOR, effectiveData: {red, green, blue}};
},
/**
* 获取设备当前的灯亮度(读)
*/
'0x11': ({dataArray}) => {
const [brightness] = dataArray;
return {protocolState: ProtocolState.RECEIVE_BRIGHTNESS, effectiveData: {brightness}};
},
/**
* 接收到设备主动发送的灯光关闭消息
* 模拟的场景是,用户关闭了设备灯光,设备需要主动推送灯光关闭事件给手机
*/
'0x12': () => {
//你可以不传递effectiveData
return {protocolState: ProtocolState.RECEIVE_LIGHT_CLOSE};
},
/**
* 接收到蓝牙设备的其他一些数据
*/
'0x13': ({dataArray}) => {
//do something
//你可以不返回任何值
}
};
}
/**
* 设置灯亮度和颜色
* @param brightness
* @param red
* @param green
* @param blue
* @returns {Promise<[unknown, unknown]>}
*/
async setColorLightAndBrightness({brightness, red, green, blue}) {
//发送协议,小程序官方提醒并行调用多次会存在写失败的可能性,所以建议使用串行方式来发送,哪种方式由你权衡
//但我这里是并行发送了两条0x01和0x02两条协议,仅演示用
return Promise.all([this.sendAction['0x01']({red, green, blue}), this.sendAction['0x02']({brightness})]);
}
}();
File terletak di modules/bluetooth/lb-bluetooth-state-example.js
import {CommonConnectState, CommonProtocolState} from "./lb-ble-common-state/index";
//特定的蓝牙设备的协议状态,用于拓展公共的蓝牙协议状态
//使用场景:
//在手机接收到蓝牙数据成功或失败后,该框架会生成一条消息,包含了对应的蓝牙协议状态值{protocolState}以及对应的{effectiveData}(effectiveData示例见 lb-example-bluetooth-protocol.js),
//在{setBLEListener}的{onReceiveData}回调函数中,对应参数{protocolState}和{value}(value就是effectiveData)
const ProtocolState = {
...CommonProtocolState,
RECEIVE_COLOR: 'receive_color',//获取到设备的颜色值
RECEIVE_BRIGHTNESS: 'receive_brightness',//获取到设备的亮度
RECEIVE_LIGHT_CLOSE: 'receive_close',//获取到设备灯光关闭事件
};
export {
ProtocolState, CommonConnectState as ConnectState
};
bisnis | Folder yang sesuai | Contoh berkas |
---|---|---|
koneksi Bluetooth | lb-ble-common-connection (penanganan peristiwa koneksi, pemutusan, dan penyambungan kembali) | abstract-bluetooth.js (yang paling sederhana, memanggil API platform untuk menghubungkan, memutuskan sambungan Bluetooth, dll.)base-bluetooth.js (mencatat ID perangkat, nilai karakteristik, status koneksi, dan informasi lain dari perangkat yang terhubung, menangani pengiriman data Bluetooth dan koneksi ulang Bluetooth)base-bluetooth-imp.js (menangkap hasil koneksi Bluetooth, memantau pemindaian Bluetooth pada perangkat di sekitarnya, koneksi, dan peristiwa status adaptor dan menanganinya sesuai kebutuhan) |
Perakitan protokol Bluetooth | lb-ble-common-protocol-body (implementasi perakitan format protokol transceiver) | i-protocol-receive-body.js i-protocol-send-body.js |
Mengirim dan menerima protokol Bluetooth | lb-ble-common-protocol-operator (agen yang menangani pengiriman dan penerimaan data) | lb-bluetooth-protocol-operator.js |
Transmisi ulang protokol Bluetooth | lb-ble-common-connection | lb-bluetooth-manager.js (lihat LBlueToothCommonManager untuk detailnya) |
Status Bluetooth dan status protokol | lb-ble-common-state | lb-bluetooth-state-example.js , yang juga dapat memperluas status baru |
Langganan untuk koneksi Bluetooth dan peristiwa status protokol | lb-ble-common-connection/base | base-bluetooth-imp.js |
Mari kita bicara tentang distribusi koneksi Bluetooth dan status protokol.
File terletak di lb-ble-common-connection/base/base-bluetooth.js
latestConnectState
.set latestConnectState
fungsi setter
lastConnectState ._onConnectStateChanged
di dalam setter
.onConnectStateChanged({connectState})
dari getAppBLEManager.setBLEListener
. onBLECharacteristicValueChange
terletak di lb-ble-common-connection/abstract-bluetooth.js
receiveOperation
terletak di lb-ble-common-protocol-operator/lb-bluetooth-protocol-operator.js
Dalam fungsi onBLECharacteristicValueChange
, setelah menerima data, saya mencegat data yang valid sesuai dengan receive-body.js
, dan memproses data yang valid sesuai dengan metode konfigurasi getReceiveAction
di lb-example-bluetooth-protocol.js
untuk menghasilkan value, protocolState
yang sesuai value, protocolState
. filter
dihasilkan ketika protokol yang tidak dikenal diterima.
onBLECharacteristicValueChange((res) => {
console.log('接收到消息', res);
if (!!valueChangeListener) {
const {value, protocolState, filter} = this.dealReceiveData({receiveBuffer: res.value});
!filter && valueChangeListener({protocolState, value});
}
});
Kode ini terlihat sederhana, namun ada banyak proses di baliknya. Yang paling penting adalah baris ini const {value, protocolState, filter} = this.dealReceiveData({receiveBuffer: res.value});
;. Izinkan saya menjelaskan secara rinci apa yang telah dilakukan bidang pekerjaan ini:
dealReceiveData
untuk memproses data protokol. dealReceiveData
di sini pada akhirnya diserahkan ke fungsi dealReceiveData
di lb-bluetooth-manager.js
untuk memproses data.this.bluetoothProtocol.receive({receiveBuffer})
di dealReceiveData
untuk menghasilkan data dan status protokol yang valid. receive
ini pada akhirnya dieksekusi oleh fungsi receiveOperation
.receiveOperation
dijalankan, ia akan mereferensikan item konfigurasi getReceiveAction
dari subkelas LBlueToothProtocolOperator
(subkelasnya adalah lb-example-bluetooth-protocol.js
).getReceiveAction
akhirnya mengembalikan objek yang disepakati {protocolState,effectiveData}
sesuai dengan implementasi pengembang sendiri. Setelah mengembalikan objek ke receiveOperation
, ia melakukan pemeriksaan ( protocolState
yang tidak dikonfigurasi di getReceiveAction
diproses sebagai CommonProtocolState.UNKNOWN
), dan mengembalikan objek tersebut. menyetujui objek ke dealReceiveData
Variabel lokal effectiveData, protocolState
dalam fungsi.protocolState!==CommonProtocolState.UNKNOWN
akan ditandai sebagai filter:true
; jika tidak, objek yang disetujui akan dikembalikan ke value, protocolState
dalam fungsi onBLECharacteristicValueChange
.Hanya itu yang dilakukan baris kode ini.
Objek yang disepakati akan diteruskan sebagai parameter ke valueChangeListener({protocolState, value})
dan callback akan dieksekusi. Setelah itu, front end dapat menerima peristiwa berlangganan, yaitu jenis protokol dan objek value
diterima dalam fungsi onReceiveData({protocolState, value})
dari getAppBLEManager.setBLEListener
.
Dokumen
UbahLog
QA
LISENSI
Untuk teknis pertukaran silahkan gabung di grup QQ : 821711186