123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- // 引入必要的微信小程序 API
- // const wx = require('wx');
- class bleManager {
- constructor() {
- this.hasPermission = false;
- this.isAvailable = false;
- this.scanDevices = [];
- this.device = null;
- }
- // 检查蓝牙权限
- async checkBluetoothPermission(callback) {
- // return new Promise((resolve, reject) => {
- // 获取蓝牙权限
- let _this = this;
- const _app = getApp();
- wx.getSetting({
- success(res) {
- if (res.authSetting["scope.bluetooth"]) {
- _app.globalData.scopeBluetooth = true;
- _this.hasPermission = true;
- // console.log('checkBluetoothPermission success, now is', res)
- if (callback) {
- callback(true);
- }
- // resolve(true);
- } else if (res.authSetting["scope.bluetooth"] === undefined) {
- _app.globalData.scopeBluetooth = false;
- _this.hasPermission = false;
- if (callback) {
- callback(false);
- }
- wx.authorize({
- scope: "scope.bluetooth",
- complete() {
- _this.checkBluetoothPermission()
- // resolve(_this.checkBluetoothPermission());
- }
- });
- } else {
- _this.globalData.scopeBluetooth = false;
- _this.hasPermission = false;
- if (callback) {
- callback(false);
- }
- wx.showModal({
- title: '请打开系统蓝牙进行配网',
- content: '如已打开蓝牙仍然弹框,请尝试重启小程序',
- success(res) {
- if (res.confirm) {
- console.log('用户点击确定')
- wx.openSetting({
- complete() {
- // _this.getBluetoothStatus();
- }
- })
- } else if (res.cancel) {
- console.log('用户点击取消')
- }
- }
- })
- // resolve(false);
- };
- }
- })
- // })
- }
- // 初始化蓝牙适配器
- async initBluetoothAdapter(callback) {
- let _this = this
- return new Promise((resolve, reject) => {
- wx.openBluetoothAdapter({
- success: (res) => {
- _this.isAvailable = true;
- // console.log('adapterState success, now is', res)
- if (callback) {
- callback(true);
- }
- resolve(true);
- },
- fail: (err) => {
- _this.isAvailable = false;
- console.log('adapterState fail, now is', err)
- if (callback) {
- callback(false);
- }
- reject(false);
- }
- });
- wx.onBluetoothAdapterStateChange(function (res) {
- console.log('adapterState changed, now is', res)
- if (callback) {
- callback(res.available ?? false);
- }
- _this.isAvailable = res.available ?? false
- })
- });
- }
- closeBle() {
- console.log('关闭蓝牙了')
- wx.closeBluetoothAdapter()
- }
- // 获取已连接的蓝牙设备
- getConnectedDevices() {
- if (!this.isAvailable && !this.hasPermission) {
- return [];
- }
- return new Promise((resolve, reject) => {
- wx.getConnectedBluetoothDevices({
- // services: ["FFC0", "ffc0", "FFC1", "FFC2", "ffc1", "ffc2", "AB00", "ab00", "AB01", "AB02", "FFF1", "fff1", "FFE2", "FFE5",],
- services: ["ab00", "ffe5", "1111", "FFC0", "FFC1", "FFF1",],
- // services: [],
- // services: [
- // "0000ab00-0000-1000-8000-00805f9b34fb",
- // "0000ffc0-0000-1000-8000-00805f9b34fb",
- // "0000FFF0-0000-1000-8000-00805F9B34FB",
- // "0000FFF1-0000-1000-8000-00805F9B34FB",
- // "0000FFE5-0000-1000-8000-00805F9B34FB",
- // ],
- success: (res) => {
- let newDevices = this.fiterDevice(res)
- console.log('已连接的蓝牙设备:', newDevices);
- resolve(newDevices);
- },
- fail: (err) => {
- console.error('获取已连接的蓝牙设备失败:', err);
- reject([]);
- }
- });
- });
- }
- // 获取获取在蓝牙模块生效期间所有搜索到的蓝牙设备。包括已经和本机处于连接状态的设备。
- getAllConnectedDevices() {
- if (!this.isAvailable && !this.hasPermission) {
- return [];
- }
- return new Promise((resolve, reject) => {
- wx.getBluetoothDevices({
- success: (res) => {
- // const connectedDevices = res.devices.map(device => ({
- // deviceId: device.deviceId,
- // name: device.name || device.localName
- // }));
- let newDevices = this.fiterDevice(res)
- resolve(newDevices);
- },
- fail: (err) => {
- console.error('已扫描过的蓝牙设备失败:', err);
- reject([]);
- }
- });
- });
- }
- // 断开与指定设备的连接
- disconnect() {
- let _this = this;
- let device = _this.device ?? {};
- let deviceId = device.deviceId ?? ""
- if (deviceId.length === 0) {
- return;
- }
- return new Promise((resolve, reject) => {
- wx.closeBLEConnection({
- deviceId: _this.device.deviceId ?? "",
- success: (res) => {
- _this.device = null;
- console.log('断开连接成功:', res);
- resolve(res);
- },
- fail: (err) => {
- console.error('断开连接失败:', err);
- reject(new Error('断开连接失败'));
- }
- });
- });
- }
- // 发送数据到指定设备
- async sendData(data) {
- let _this = this
- return new Promise((resolve, reject) => {
- var buffer = null;
- // todo 判断是否是buffer
- // if (Buffer.isBuffer(data)) {
- // buffer = data;
- // } else {
- buffer = new ArrayBuffer(data.length);
- // 下面是赋值,不能删
- const dataView = new DataView(buffer);
- data.forEach((value, index) => {
- dataView.setUint8(index, value); // 将每个16进制数值写入到 buffer 中
- });
- // }
- console.log('开始发送数据:', data, buffer);
- wx.writeBLECharacteristicValue({
- deviceId: _this.device.deviceId,
- serviceId: _this.device.serviceId,
- characteristicId: _this.device.characteristicId,
- value: buffer,
- success: (res) => {
- // console.log('数据发送成功:');
- resolve(res);
- },
- fail: (err) => {
- console.error('数据发送失败:', err);
- reject(new Error('数据发送失败'));
- }
- });
- });
- }
- async getSetting() {
- const _this = this;
- return new Promise((resolve, reject) => {
- wx.getSetting({
- success(res) {
- if (res.authSetting["scope.userFuzzyLocation"]) {
- // 成功
- // _this.getBluetoothStatus();
- console.log("有定位权限")
- resolve(true);
- } else if (res.authSetting["scope.userFuzzyLocation"] === undefined) {
- wx.authorize({
- scope: "scope.userFuzzyLocation",
- success() {
- console.log("再次获取定位权限")
- resolve(_this.getSetting());
- }
- });
- } else {
- wx.showModal({
- title: '请打开系统位置获取定位权限',
- success(res) {
- if (res.confirm) {
- console.log('用户点击确定')
- wx.openSetting({
- complete() {
- // _this.getSetting();
- // resolve(_this.getSetting());
- }
- })
- } else if (res.cancel) {
- console.log('用户点击取消');
- }
- }
- })
- console.log("没有有定位权限")
- reject(false);
- }
- }
- })
- });
- }
- // 开始搜索蓝牙设备
- async startScan(success, fail) {
- let open = await this.getSetting()
- if (!open) {
- if (fail) {
- fail("需要先开启定位");
- }
- console.log('需要先开启定位');
- }
- if (!this.isAvailable && !this.hasPermission) {
- return false;
- }
- wx.startBluetoothDevicesDiscovery({
- // services: ["ffc0", "ab00", "ffe5"],
- success: (res) => {
- // this.onBluetoothDeviceFound();
- console.log('蓝牙设备搜索已启动:', res);
- if (success) {
- success(res);
- }
- // resolve(res);
- },
- fail: (err) => {
- if (fail) {
- if (err.errno == 1509008) {
- wx.showToast({
- title: '搜索蓝牙需要先开启定位权限',
- icon: 'none',
- duration: 2000
- })
- }
- fail(err);
- }
- console.log('启动蓝牙设备搜索失败', err ?? "err is null");
- // reject(new Error('启动蓝牙设备搜索失败', err ?? "err is null"));
- }
- });
- }
- // 监听发现新设备的事件
- onBluetoothDeviceFound(callback) {
- wx.onBluetoothDeviceFound((res) => {
- let newDevices = this.fiterDevice(res)
- // this.devices.push(...devices);
- if (newDevices.length > 0) {
- // console.log('发现设备1:', res);
- }
- if (callback) {
- callback(newDevices);
- }
- });
- }
- getMac() {
- }
- ab2hex(buffer) {
- var hexArr = Array.prototype.map.call(
- new Uint8Array(buffer),
- function (bit) {
- return ('00' + bit.toString(16)).slice(-2)
- }
- )
- return hexArr.join(':');
- }
- fiterDevice(res) {
- var devices = res.devices.filter(device => {
- const name = device.name || '';
- const localName = device.localName || '';
- let isNot = this.isNotEmpty(name) || this.isNotEmpty(localName);
- if (isNot) {
- // console.log('是猫王设备名称:', device.advertisData, device.serviceData)
- let mac = this.ab2hex(device.advertisData)
- // console.log(mac)
- device.mac = mac
- }
- return isNot
- });
- let newDevices = devices.map((device) => {
- let uuid = device.advertisServiceUUIDs[0] ?? ""
- return {
- deviceId: device.deviceId,
- name: device.name,
- localName: device.localName,
- uuid: uuid,
- mac: device.mac,
- connectable: device.connectable
- }
- });
- return newDevices
- }
- isNotEmpty(name) {
- let isNot = (name !== '' &&
- (name.startsWith("MW_") ||
- name.startsWith("MW-") ||
- // name.startsWith("猫王") ||
- // name.startsWith("妙播") ||
- // name.startsWith("AirSmart") ||
- name === "le")
- )
- // if (!isNot && name !== '') {
- // console.log('不是猫王设备名称:', name)
- // }
- return isNot;
- }
- // 连接到指定设备
- async connectToDevice(device) {
- return new Promise((resolve, reject) => {
- console.log("开始连接蓝牙:", device.deviceId)
- wx.createBLEConnection({
- deviceId: device.deviceId,
- success: (res) => {
- this.device = device
- console.log('连接成功:', res);
- resolve(true);
- },
- fail: (err) => {
- this.device = null
- console.error('连接失败:', err);
- resolve(false);
- }
- });
- });
- }
- // 停止搜索
- stopScan() {
- return new Promise((resolve, reject) => {
- wx.stopBluetoothDevicesDiscovery({
- success: (res) => {
- console.log('停止搜索成功:', res);
- resolve(res);
- },
- fail: (err) => {
- console.error('停止搜索失败:', err);
- reject(new Error('停止搜索失败'));
- }
- });
- });
- }
- closeBle() {
- wx.closeBluetoothAdapter({
- success(res) {
- console.log(res)
- }
- })
- }
- // 发现服务
- discoverServices(deviceId) {
- console.log('发现服务:', deviceId);
- return new Promise((resolve, reject) => {
- wx.getBLEDeviceServices({
- deviceId: deviceId,
- success: (res) => {
- // this.device.services = res.services;
- let service_id = "";
- for (let i = 0; i < res.services.length; i++) {
- if (res.services[i].uuid.toUpperCase().indexOf("AB00") != -1 ||
- res.services[i].uuid.toUpperCase().indexOf("FFC0") != -1
- // res.services[i].uuid.toUpperCase().indexOf("ae800") != -1
- ) {
- service_id = res.services[i].uuid;
- break;
- }
- console.log('发现服务1:', service_id);
- service_id = res.services[i].uuid;
- }
- this.device.serviceId = service_id;
- console.log('发现服务2:', service_id);
- resolve(service_id);
- // resolve(res.services);
- },
- fail: (err) => {
- this.device.serviceId = null;
- console.error('发现服务失败:', err);
- reject([]);
- }
- });
- });
- }
- // 发现特征值 read / write
- discoverCharacteristics(deviceId, serviceId) {
- console.log('发现特征值:' + deviceId + " , " + serviceId);
- // if (deviceId !== this.device.deviceId) {
- // console.log('设备id不匹配')
- // return false
- // }
- return new Promise((resolve, reject) => {
- wx.getBLEDeviceCharacteristics({
- deviceId: deviceId,
- serviceId: serviceId,
- success: (res) => {
- // this.characteristics[serviceId] = res.characteristics;
- console.log('发现特征值2:', res);
- // this.device.characteristics = res.characteristics;
- resolve(res.characteristics);
- },
- fail: (err) => {
- this.device.characteristics = null;
- console.error('发现特征值失败:', err);
- reject("");
- }
- });
- });
- }
- // 读取特征值
- readCharacteristicValue(characteristicId) {
- console.log('开始读取特征值', characteristicId)
- return new Promise((resolve, reject) => {
- wx.readBLECharacteristicValue({
- deviceId: this.device.deviceId,
- serviceId: this.device.serviceId,
- characteristicId: characteristicId,
- success: (res) => {
- const name = this.parseBLEValue(res.value); // 解析读取到的值
- console.log('读取特征值成功:', name, res);
- resolve(res);
- },
- fail: (err) => {
- console.error('读取特征值失败:', err);
- reject("");
- }
- });
- });
- }
- // 解析读取到的设备名称
- parseBLEValue(buffer) {
- return String.fromCharCode.apply(null, new Uint8Array(buffer));
- }
- // 监听特征值变化
- notifyCharacteristicValueChange(characteristicId, callback) {
- console.log('监听特征值变化:', characteristicId, this.device.deviceId, this.device.serviceId);
- wx.notifyBLECharacteristicValueChange({
- deviceId: this.device.deviceId, //设备mac IOS和安卓系统不一样
- serviceId: this.device.serviceId, //服务通道,这里主要是notify
- characteristicId: characteristicId, //notify uuid
- state: true,
- success: function (res) {
- console.log("开启notify 成功")
- //TODO onBLECharacteristicValueChange 监听特征值 设备的数据在这里获取到
- wx.onBLECharacteristicValueChange(function (characteristic) {
- let buffer = characteristic.value
- let dataView = new DataView(buffer)
- let dataResult = []
- for (let i = 0; i < dataView.byteLength; i++) {
- // console.log("0x" + dataView.getUint8(i).toString(16))
- // dataResult.push("0x" + dataView.getUint8(i).toString(16))
- dataResult.push(dataView.getUint8(i))
- }
- const result = dataResult
- console.log("拿到的数据:", result)
- if (callback) {
- callback(result)
- }
- })
- },
- fail: function (res) {
- console.log("订阅特征失败:", res)
- }
- })
- }
- setWrite(wirte, characteristicId) {
- console.log('写入特征值:', characteristicId)
- // this.device.wirte = wirte
- this.device.characteristicId = characteristicId;
- }
- }
- // const ble = new bleManager();
- // 导出 bleManager 类
- module.exports = bleManager;
|