import {
warning,
loading,
closeLoading
} from 'tips'
const app = getApp()
// 蓝牙初始化连接步骤
// 打开蓝牙 则是第一次初始化 初始化失败继续调用 isFirestShow 有值则第一次调用
export function openBlue(isFirestShow) {
return new Promise((resolved, rejected) => {
wx.closeBluetoothAdapter({
success: function (r) {
wx.openBluetoothAdapter({ //调用微信小程序api 打开蓝牙适配器接口
success: function (res) {
resolved('success')
},
fail: function (res) { //如果手机上的蓝牙没有打开,可以提醒用户
rejected('fail')
if (isFirestShow) {
warning("请开启蓝牙")
} else {
// setTimeout(function () {
// rejected(initBlue())
// // initBlue();
// }, 3000)
}
}
})
},
fail: err => {
if (isFirestShow) {
warning("该设备不支持蓝牙")
}
rejected('noBlue')
}
});
})
}
// // 开始搜索
export function starBlue() {
return new Promise((resolved, rejected) => {
let init = () => {
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: function (res) {
resolved('success')
},
fail: err => {
rejected('fail')
}
});
}
if (app.globalData.successDeviceId) {
wx.closeBLEConnection({
deviceId: app.globalData.successDeviceId,
success: (res) => {
app.globalData.successDeviceId = null
app.globalData.blueStatus = {
deviceId: null,
connected: false
}
init()
},
fail: () => {
app.globalData.successDeviceId = null
app.globalData.blueStatus = {
deviceId: null,
connected: false
}
init()
}
})
} else {
init()
}
})
}
export function inArray(arr, key, val) {
for (let i = 0; i < arr.length; i++) {
if (arr[i][key] === val) {
return i;
}
}
return -1;
}
// // 获取蓝牙搜索列表
export function getBule() {
return new Promise((resolved, rejected) => {
wx.getBluetoothDevices({
success: function (res) {
if (res.errMsg == 'getBluetoothDevices:ok') {
resolved(res)
} else {
rejected('fail')
}
},
fail: function () {
rejected('fail')
}
});
});
}
// // 蓝牙一键连接步骤 Quick为一键连接 无值则分步惭怍
// // 连接蓝牙
export function createBlue(deviceId, Quick) {
return new Promise((resolved, rejected) => {
wx.stopBluetoothDevicesDiscovery({
success: function (res) {}
})
let createBlue = () => {
wx.offBLEConnectionStateChange()
wx.createBLEConnection({
deviceId: deviceId,
success: function (res) {
getTheBlueDisConnectWithAccident(); //监听蓝牙是否会异常断开
app.globalData.successDeviceId = deviceId
if (Quick) {
/* 获取设备的服务UUID */
getBlueServe(deviceId, Quick).then(r => {
resolved(r)
}).catch(err => {
rejected('fail')
})
} else {
resolved('success')
}
},
fail: (res) => {
rejected('fail')
},
})
}
/* 开始连接蓝牙设备 */
if (app.globalData.successDeviceId) {
wx.closeBLEConnection({
deviceId: app.globalData.successDeviceId,
success: (res) => {
app.globalData.successDeviceId = null
app.globalData.blueStatus = {
deviceId: null,
connected: false
}
createBlue()
},
fail: () => {
app.globalData.successDeviceId = null
app.globalData.blueStatus = {
deviceId: null,
connected: false
}
createBlue()
}
})
} else {
createBlue()
}
})
}
// // 获取蓝牙特征 Quick是否一键连接
export function getBlueServe(deviceId, Quick) {
return new Promise((resolved, rejected) => {
wx.getBLEDeviceServices({
deviceId: deviceId,
success: function (res) {
if (Quick) {
//取出所有的服务
var all_UUID = res.services
/* 遍历服务数组 */
for (var index = 0; index < all_UUID.length; index++) {
/* 判断是否是我们需要的FFE0 */
if (all_UUID[index].isPrimary) {
// app.globalData.serviceId = all_UUID[index].uuid
Characteristics({
deviceId: deviceId,
serviceId: app.globalData.serviceId
}).then(res2 => {
resolved(res2)
}).catch(err => {
rejected('fail')
}); //调用获取特征值函数
break
}
};
} else {
resolved(res)
}
},
fail: function (err) {
rejected('fail')
},
});
})
}
// // 获取到特征值
export function Characteristics(o, Quick) {
return new Promise((resolved, rejected) => {
wx.getBLEDeviceCharacteristics({
deviceId: o.deviceId,
serviceId: o.serviceId,
success: function (res) {
app.globalData.blueStatus = {
deviceId: o.deviceId,
connected: true
}
if (Quick) {
warning('重新连接成功')
}
var c_list = res.characteristics; //获取到所有特征值
app.globalData.characteristicsList = c_list
// if (Quick) {
/* 遍历获取characteristicsId */
for (var i = 0; i < c_list.length; i++) {
if (c_list[i].properties.write) {
app.globalData.characteristicsId = c_list[i].uuid
}
if (c_list[i].properties.notify || c_list[i].properties.indicate) {
wx.readBLECharacteristicValue({
deviceId: o.deviceId,
serviceId: o.serviceId,
characteristicId: c_list[i].uuid,
success: function (res) {
console.log(res, '------notify---readBLECharacteristicValue');
},
fail: res => {
console.log(res, '---notify--shibai----readBLECharacteristicValue');
}
})
let uuid = c_list[i].uuid
app.globalData.startNoticeUUid = uuid
}
// 此处执行 发送 接收信息准备
};
startNotice()
resolved({
data: res,
type: 'success'
})
},
fail: err => {
rejected('fail')
}
})
})
}
// 接收信息 ---接收 调用只能接收一个
export function startNotice() {
wx.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
deviceId: app.globalData.successDeviceId,
serviceId: app.globalData.serviceId,
characteristicId: app.globalData.startNoticeUUid, //第一步 开启监听 notityid 第二步发送指令 write
success: function (res) {
wx.onBLECharacteristicValueChange(function (res) {
let val = arrayBufferToString(res.value);
console.log(val, '-------接收返回值-----onBLECharacteristicValueChange');
save(val)
})
// 设备返回的方法
},
fail: res => {
// rejected('fail')
}
})
}
// 存放值蓝牙返回值
let valStr = ''
// 分别存放蓝牙数据返回 处理
function save(val) {
if (val == 'start') {
valStr = ''
return
}
if (val != 'end') {
if (val.indexOf('0000##node_id##0000') != -1) {
console.log(val, '-------------------------app.setOnlinSuccess()');
//入网后判断是否能接收信息
app.setOnlinSuccess(true)
} else if (val.substring(0, 7) == 'znode##') {
let nodeId = val.split('\r\n')[0]
//254为调试盒子
console.log(nodeId, '-------nodeId');
if (nodeId.substring(13, 16) == '254') {
// 证明入网成功
console.log(nodeId, '-------app.globalData.statusManage.onlinSuccess');
app.setOnlinSuccess(true)
}
app.getZigbeeList(nodeId)
} else if (val.substring(4, 17) == '##send-fail##') {
let nodeId = val.split('\r\n')[0]
app.getZigbeeFailList(nodeId)
} else if (val.substring(0, 6) == 'node##') {
// 调光
let nodeId = val.substring(6, val.length).split('\r\n')[0]
if (!app.globalData.statusManage.nodes.includes(nodeId)) {
app.globalData.statusManage.nodes.push(nodeId)
}
} else {
valStr += val
}
return
}
if (val == 'end') {
console.log(valStr, '------end --val');
if (valStr.indexOf('line##') != -1) {
console.log(valStr, '-------------------------line');
let saveVal= valStr.split('\r\n')[0]
console.log('------saveVal-',saveVal);
app.saveMatchVal(saveVal)
}else if (valStr == 'ok\r\n') {
app.globalData.statusManage.status = valStr
} else if (valStr.substring(0, 6) == 'uuid##') {
app.globalData.statusManage.roomUUid = valStr.substring(6, valStr.length).split('\r\n')[0] //获取UUID
} else if (valStr.substring(0, 6) == 'ssid##') {
app.globalData.statusManage.RoomInfo = valStr //设备信息
} else if (valStr.substring(0, 8) == 'online##') {
app.globalData.statusManage.onlineList = valStr //设备信息
} else if (valStr.substring(0, 6) == 'type##') {
app.globalData.statusManage.type = valStr.substring(6, valStr.length).split('\r\n')[0] //设备信息
}
}
}
//监听蓝牙设备是否会异常断开 重新打开 ---- 待定
export function getTheBlueDisConnectWithAccident() {
wx.onBLEConnectionStateChange(function (res) {
app.globalData.blueStatus = res
if (!res.connected) {
warning('当前调试盒子已断开')
// monitorTheBlue()
}
})
}
//监听手机蓝牙的开关 ---- 待定
export function monitorTheBlue(cb) {
wx.onBluetoothAdapterStateChange(function (res) {
if (res.available) {
if (app.globalData.blueStatus.connected == false) {
wx.closeBluetoothAdapter({
success: function (r) {
wx.openBluetoothAdapter({ //调用微信小程序api 打开蓝牙适配器接口
success: function () {
let d = app.globalData.successDeviceId
if (d) {
createBlue(d, true)
}
}
})
}
})
}
} else {
warning("蓝牙已关闭")
}
})
}
// 获取离线列表
export function getOnline(val) {
let v = val.split('\r\n')[0].split('online##')[1]
let a = v.split('##')
let arr = []
a.forEach(v => {
if (v) {
arr.push(v)
}
})
return arr
}
// 获取设备信息 读取配置,返回wifi账号密码、UUID、版本号
export function getConfig(val) {
let obj = {}
let arr = val.split('\r\n')
arr.forEach(v => {
if (v) {
let arrInfo = v.split('##')
obj[arrInfo[0]] = arrInfo[1]
}
})
return obj
}
// 传入对象转换成##连接的字符串
export function objtoString(obj) {
let str = ''
for (let key in obj) {
str += `##${key}##${obj[key]}`
}
return str
}
// 数组变成##连接的字符串
export function arrToBlueString(arr) {
let str = ''
arr.forEach(v => {
str += v + "##"
})
return str
}
//timesTotal 发送次数 errTimesTotal 发送重发次数
const timesTotal = 2,
errTimesTotal = 5
let errTimes = 0,
index = 0,
times = 0,
changeTimes = 0
// 发送模板
function sendTab(tmpBuffer) {
wx.writeBLECharacteristicValue({
deviceId: app.globalData.successDeviceId,
serviceId: app.globalData.serviceId,
characteristicId: app.globalData.characteristicsId,
value: tmpBuffer,
success: (res) => {
index++
},
fail: (error) => {
errTimes++
}
})
}
// 循环发送命令
function forEachSend(str) {
index = 0;
let strArr = []
let length = str.length
changeTimes = Math.ceil(length / 20)
for (var i = 0; i < str.length; i += 20) {
let s = str.substring(i, i + 20)
strArr.push(stringToHexBuffer(s))
}
strArr.forEach(v => {
sendTab(v)
})
}
export function send_getType() {
var val = '0000##get-type\r\n';
errTimes = 0;
times = 0;
return new Promise((resolved, rejected) => {
if (!app.globalData.blueStatus.connected) {
warning("请先前往连接蓝牙")
rejected('openBlue')
return
}
app.globalData.statusManage.type = null
let returnVal = () => {
setTimeout(() => {
console.log(val, index, changeTimes, '----index,changeTimes', app.globalData.statusManage.type);
if (index == changeTimes && app.globalData.statusManage.type) {
console.log('成功回调', val);
resolved('success')
} else {
if (times < timesTotal) {
times++
forEachSend(val)
returnVal()
} else {
rejected('fail')
}
}
}, 2000);
}
forEachSend(val)
returnVal()
})
}
// 返回OK的封装
// 发送 Wifi账号密码、发送房间号、发送启动配置、停止配置、开始配置其他设备、停止配置、发送继电器状态
export function send_ReturnOk(str) {
console.log(str);
errTimes = 0;
times = 0;
return new Promise((resolved, rejected) => {
if (!app.globalData.blueStatus.connected) {
warning("请先前往连接蓝牙")
rejected('openBlue')
return
}
app.globalData.statusManage.status = null
let returnVal = () => {
setTimeout(() => {
console.log(str, index, changeTimes, '----index,changeTimes', app.globalData.statusManage.status);
if (index == changeTimes && app.globalData.statusManage.status == 'ok\r\n') {
console.log('成功回调', str);
resolved('success')
} else {
if (times < timesTotal) {
times++
forEachSend(str)
returnVal()
} else {
rejected('fail')
}
}
}, 2000);
}
forEachSend(str)
returnVal()
})
}
// /获取UUID
export function send_getUUid(roomNumber) {
let str = bluePrefix(roomNumber) + "##uuid\r\n";
errTimes = 0;
times = 0;
console.log(str, '------------send_getUUid');
return new Promise((resolved, rejected) => {
if (!app.globalData.blueStatus.connected) {
warning("请先前往连接蓝牙")
rejected('openBlue')
return
}
app.globalData.statusManage.roomUUid = null
let returnVal = () => {
setTimeout(() => {
console.log(index, changeTimes, '----index,changeTimes');
if (index == changeTimes && app.globalData.statusManage.roomUUid) {
if (app.globalData.statusManage.roomUUid.length == 36) {
resolved('success')
} else {
if (times < timesTotal) {
times++
forEachSend(str)
returnVal()
} else {
rejected('fail')
}
}
} else {
if (times < timesTotal) {
times++
forEachSend(str)
returnVal()
} else {
rejected('fail')
}
}
}, 2000);
}
forEachSend(str)
returnVal()
})
}
// /获取设备信息
export function get_config(str) {
errTimes = 0;
times = 0;
return new Promise((resolved, rejected) => {
if (!app.globalData.blueStatus.connected) {
warning("请先前往连接蓝牙")
rejected('openBlue')
return
}
app.globalData.statusManage.RoomInfo = null
let returnVal = () => {
setTimeout(() => {
console.log(index, changeTimes, '----index,changeTimes');
if (index == changeTimes && app.globalData.statusManage.RoomInfo) {
resolved('success')
} else {
if (times < timesTotal) {
times++
forEachSend(str)
returnVal()
} else {
rejected('fail')
}
}
}, 2000);
}
forEachSend(str)
returnVal()
})
}
// 轮询设备是否在线
export function get_onlineList(str) {
errTimes = 0;
times = 0;
return new Promise((resolved, rejected) => {
if (!app.globalData.blueStatus.connected) {
warning("请先前往连接蓝牙")
rejected('openBlue')
return
}
app.globalData.statusManage.onlineList = null
let returnVal = () => {
setTimeout(() => {
console.log(index, changeTimes, '----index,changeTimes');
if (index == changeTimes && app.globalData.statusManage.onlineList) {
resolved('success')
} else {
if (times < timesTotal) {
times++
forEachSend(str)
returnVal()
} else {
rejected('fail')
}
}
}, 2000);
}
forEachSend(str)
returnVal()
})
}
// 调光
export function get_nodeList(str) {
errTimes = 0;
times = 0;
return new Promise((resolved, rejected) => {
if (!app.globalData.blueStatus.connected) {
warning("请先前往连接蓝牙")
rejected('openBlue')
return
}
// app.globalData.statusManage.nodes = []
let returnVal = () => {
setTimeout(() => {
console.log(index, changeTimes, '----index,changeTimes');
if (index == changeTimes && app.globalData.statusManage.nodes.length > 0) {
resolved('success')
} else {
if (times < timesTotal) {
times++
forEachSend(str)
returnVal()
} else {
rejected('fail')
}
}
}, 2000);
}
forEachSend(str)
returnVal()
})
}
// Zigbee
export function get_scan_NodeList(str) {
errTimes = 0;
times = 0;
return new Promise((resolved, rejected) => {
if (!app.globalData.blueStatus.connected) {
warning("请先前往连接蓝牙")
rejected('openBlue')
return
}
// app.globalData.statusManage.nodes = []
let returnVal = () => {
setTimeout(() => {
if (index == changeTimes && app.globalData.statusManage.zigbeeList.length > 0) {
resolved('success')
} else {
if (times < timesTotal) {
times++
forEachSend(str)
returnVal()
} else {
rejected('fail')
}
}
}, 2000);
}
forEachSend(str)
returnVal()
})
}
// 字符串转buffer
export function stringToHexBuffer(str) {
var bytes = new Array();
var len, c;
len = str.length;
for (var i = 0; i < len; i++) {
c = str.charCodeAt(i);
if (c >= 0x010000 && c <= 0x10FFFF) {
bytes.push(((c >> 18) & 0x07) | 0xF0);
bytes.push(((c >> 12) & 0x3F) | 0x80);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000800 && c <= 0x00FFFF) {
bytes.push(((c >> 12) & 0x0F) | 0xE0);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000080 && c <= 0x0007FF) {
bytes.push(((c >> 6) & 0x1F) | 0xC0);
bytes.push((c & 0x3F) | 0x80);
} else {
bytes.push(c & 0xFF);
}
}
var array = new Int8Array(bytes.length);
for (var i in bytes) {
array[i] = bytes[i];
}
return array.buffer;
}
//buffer 十六进制 转字符串
export function arrayBufferToString(arr) {
if (typeof arr === 'string') {
return arr;
}
var dataview = new DataView(arr);
var ints = new Uint8Array(arr.byteLength);
for (var i = 0; i < ints.length; i++) {
ints[i] = dataview.getUint8(i);
}
arr = ints;
var str = '',
_arr = arr;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
} else {
str += String.fromCharCode(_arr[i]);
}
}
return str;
}
export function bin_to_hex(str) {
let hex_array = [{
key: 0,
val: "0000"
}, {
key: 1,
val: "0001"
}, {
key: 2,
val: "0010"
}, {
key: 3,
val: "0011"
}, {
key: 4,
val: "0100"
}, {
key: 5,
val: "0101"
}, {
key: 6,
val: "0110"
}, {
key: 7,
val: "0111"
},
{
key: 8,
val: "1000"
}, {
key: 9,
val: "1001"
}, {
key: 'a',
val: "1010"
}, {
key: 'b',
val: "1011"
}, {
key: 'c',
val: "1100"
}, {
key: 'd',
val: "1101"
}, {
key: 'e',
val: "1110"
}, {
key: 'f',
val: "1111"
}
]
let value = ''
let list = []
if (str.length % 4 !== 0) {
let a = "0000"
let b = a.substring(0, 4 - str.length % 4)
str = b.concat(str)
}
while (str.length > 4) {
list.push(str.substring(0, 4))
str = str.substring(4);
}
list.push(str)
for (let i = 0; i < list.length; i++) {
for (let j = 0; j < hex_array.length; j++) {
if (list[i] == hex_array[j].val) {
value = value.concat(hex_array[j].key)
break
}
}
}
return value
}
// 蓝牙房间号等 参数 四位封装
export function bluePrefix(val, Leg = 4) {
val = val ? val : ''
if (typeof (val) == 'number') {
val = val.toString()
}
let returnVal = '';
if (val.length < Leg) {
let iLength = Leg - val.length
for (let i = 0; i < iLength; i++) {
returnVal += '0'
}
}
returnVal += val
return returnVal
}
微信小程序蓝牙封装
于 2021-07-09 11:44:50 首次发布