微信小程序Ble设备连接与发送

闲来没事钻研小程序开发,写了一篇关于微信小程序ble设备控制的底层api,话不多说直接上源码:

目录结构:

baseBleApi.js文件:

var currentDevice = {}; //ble设备

var notifyService = {}; //唤醒特征值
var writeService = {}; //写入服务

var writeCharacteristic = {}; //写入特征值
var notifyCharacteristic = {}; //唤醒特征值

var onSendSuccessCallBack = undefined; //成功回调
var onConnectCallback = undefined; // 链接回调
var bleUtils = require( 'utils/strUtils.js');
var crc = require( 'crc.js');
var isConnected = false; //是否已链接



module.exports = {
writeCommend: writeCommend,
closeBLEConnection: closeBLEConnection
// disConnect, disConnect,
// openBluetoothAdapter: openBluetoothAdapter
}



/**
* @param sendCommend 写入命令
* @param deviceName 锁具名称
* @param onSuccessCallBack 成功回调
* @param onFailCallBack 返回失败回调
* @param onCompleteCallBack 成功失败都会回调
*
* @param services 主服务serviceUUID
* @param writeServiceUUID 写入服务UUID
* @param notifyServiceUUID 唤醒服务UUID
*
* @param notifyCharacteristicUUID 唤醒特征值UUID
* @param writeCharacteristicUUID 写入特征值UUID
*/


function writeCommend(options) {
var params = {};
var defalt = {
adviceId: "",
sendCommend: "",
onSuccessCallBack: function success(res) { },
onFailCallBack: function success(res) { },
onCompleteCallBack: function success(res) { },
services: [],
writeServiceUUID: "",
notifyServiceUUID: "",
notifyCharacteristicUUID: "",
writeCharacteristicUUID: ""
};

params = Object.assign(defalt, options)
// setConnectionStateChange(params.onFailCallBack)

if (!setConnectionStateChange()) {
openBluetoothAdapter(params);
} else {
// typeof str == 'string'
sendCmd(params.sendCommend, params.onSuccessCallBack, params.onFailCallBack);
}
}

/**
* 初始化蓝牙适配器
*/

function openBluetoothAdapter(params) {

wx.openBluetoothAdapter({
success: function (res) {
console.log( "初始化蓝牙适配器成功")
console.log(res)
startBluetoothDevicesDiscovery(params)

}, fail: function (res) {
console.log( "初始化蓝牙适配器失败")
params.onFailCallBack(res.errMsg)
console.log(res);
return
},
complete: function (res) {
console.log(res);
}
})
}

/**
* 开始搜寻附近的蓝牙外围设备。注意,该操作比较耗费系统资源,请在搜索并连接到设备后调用 stop 方法停止搜索。
* @ params services:['4asdga'],根据主ServiceUUID进行搜索特定蓝牙,提高搜索效率
* 本ble设备主ServiceUUid: "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
*/

var delayTimer; //停止循环获取tag
var isFound = false
function startBluetoothDevicesDiscovery(params, connectCallback) {

if ( typeof connectCallback == 'undefined') {
connectCallback = function (errMsg) { }
}

onConnectCallback = connectCallback;

setTimeout( function () {
if (isFound) {
return;
}
else {
console.log( "搜索设备超时");
params.onFailCallBack( "搜索设备超时")
stopBluetoothDevicesDiscovery();
clearInterval(delayTimer)
return
}
}, 10000);


wx.startBluetoothDevicesDiscovery({

services: params.services,
success: function (res) {
console.log(res)
console.log( "开启搜索成功")
getBluetoothDevices(params)

}, fail: function (res) {
console.log( "开启搜索失败")
console.log(res)
params.onFailCallBack(res)
return
},
complete: function (res) {
// complete
console.log(res);
}
})

//每隔一秒获取一次
delayTimer = setInterval( function () {
getBluetoothDevices(params)
}, 1000)

}



/**
* 获取所有已发现的蓝牙设备,包括已经和本机处于连接状态的设备
*/
function getBluetoothDevices(params) {

wx.getBluetoothDevices({
success: function (res) {
console.log( "getBluetoothDevices");
console.log(res.devices);
for ( var i = 0; i < res.devices.length; i++) {
//忽略传入的deviceName大小写
// isContains bleUtils
var lockNameFinal = bleUtils.removeBytes(params.adviceId, ":")

if (bleUtils.isContains(res.devices[i].name, lockNameFinal)) {
console.log( "搜索到要链接的设备....")
stopBluetoothDevicesDiscovery();
isFound = true
clearInterval(delayTimer)
currentDevice = res.devices[i]
createBLEConnection(params)
}
}
},
fail: function (res) {
clearInterval(delayTimer)
console.log( "没有搜索到要链接的设备....")
console.log(res)
params.onFailCallBack(res)
stopBluetoothDevicesDiscovery();
return
}
})
}

/**
* 停止搜寻附近的蓝牙外围设备。请在确保找到需要连接的设备后调用该方法停止搜索。
*/
function stopBluetoothDevicesDiscovery() {
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log(res)
}
})
}


/**
* 连接低功耗蓝牙设备
*/
function createBLEConnection(params) {

// setConnectionStateChange(params.onFailCallBack);

setTimeout( function () {
if (isConnected) return;
console.log( "连接设备超时");
params.onFailCallBack( "连接设备超时")
return
}, 5000)


wx.createBLEConnection({
// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId: currentDevice.deviceId + "",
success: function (res) {
console.log(res)
console.log( `连接成功 : ${currentDevice.deviceId }`)
isConnected = true
getBLEDeviceServices(params);

}, fail: function (res) {
console.log(res)
params.onFailCallBack(res)
console.log( `连接失败 : ${currentDevice.deviceId }`)
}
})
}
/**
* closeBLEConnection
* 断开与低功耗蓝牙设备的连接
*/

function closeBLEConnection(deviceId) {

wx.closeBLEConnection({
deviceId: currentDevice.deviceId + "",
success: function (res) {
console.log(res)
}
})
}




/**
*
* 返回蓝牙是否正处于链接状态
*/
function setConnectionStateChange(onFailCallback) {
wx.onBLEConnectionStateChange( function (res) {
// 该方法回调中可以用于处理连接意外断开等异常情况
console.log( `device ${res.deviceId } state has changed, connected: ${res.connected }`);
return res.connected;
});
}

/**
* 获取蓝牙设备所有 service(服务)
* @params writeServiceUUID:ble设备所具有的写入服务UUID
* @params notifyServiceUUID:ble设备具有的唤醒服务UUID
*/

function getBLEDeviceServices(params) {

wx.getBLEDeviceServices({
// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId: currentDevice.deviceId + "",
success: function (res) {
console.log( `获取服务成功 :`)
console.log( 'device services:', res.services)

for ( var i = 0; i < res.services.length; i++) {
if (res.services[i].uuid == params.writeServiceUUID) {
writeService = res.services[i]
}
if (res.services[i].uuid == params.notifyServiceUUID) {
notifyService = res.services[i]
}
}
//获取
getNotifyBLEDeviceCharacteristics(params);
}
})
}

/**
* 获取蓝牙设备唤醒characteristic(特征值)
*/
function getNotifyBLEDeviceCharacteristics(params) {

wx.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId: currentDevice.deviceId + "",
// 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取
serviceId: notifyService.uuid + "",

success: function (res) {
console.log( "唤醒特征值获取成功:")
console.log( 'device getBLEDeviceCharacteristics:', res.characteristics)

for ( var i = 0; i < res.characteristics.length; i++) {
if (res.characteristics[i].uuid == params.notifyCharacteristicUUID) {
notifyCharacteristic = res.characteristics[i]
}
}

// getWriteBLEDeviceCharacteristics();
console.log( "唤醒特征值 :", notifyCharacteristic)
getWriteBLEDeviceCharacteristics(params)
}
})
}

function getWriteBLEDeviceCharacteristics(params) {

wx.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId: currentDevice.deviceId + "",
// 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取
serviceId: writeService.uuid + "",

success: function (res) {
console.log( "写入特征值获取成功:")
console.log( 'device getBLEDeviceCharacteristics:', res.characteristics)
for ( var i = 0; i < res.characteristics.length; i++) {
if (res.characteristics[i].uuid == params.writeCharacteristicUUID) {
writeCharacteristic = res.characteristics[i]
}
}
console.log( "xieru :", writeCharacteristic)
initNotifyListener(params);
}
})
}

/**
*
* 连接成功后,初始化回调监听
*
* 启用低功耗蓝牙设备特征值变化时的 notify 功能。注意:\
* 必须设备的特征值支持notify才可以成功调用,具体参照 characteristic 的 properties 属性
*/
function initNotifyListener(params) {

wx.notifyBLECharacteristicValueChanged({

deviceId: currentDevice.deviceId + "",
serviceId: notifyService.uuid + "",
characteristicId: notifyCharacteristic.uuid + "",
state: true,


success: function (res) {
console.log( `开启监听成功${res.errMsg }`);

setTimeout( function () {
onConnectCallback( 'ok'); // 连接成功后,初始化回调监听回调
sendCmd(params.sendCommend, params.onSuccessCallBack, params.onFailCallBack);
}, 200);
},
fail: function (res) {
console.log( "开启监听失败" + res.errMsg);
params.onFailCallBack( "开启监听失败");
}
});
onBLECharacteristicValueChange();
}

/**
* 启用低功耗蓝牙设备特征值变化时的 notify 功能。注意:
* 必须设备的特征值支持notify才可以成功调用,具体参照 characteristic 的 properties 属性
*/
function onBLECharacteristicValueChange() {
wx.onBLECharacteristicValueChange( function (res) {
console.log( `characteristic ${res.characteristicId } has changed, now is ${bleUtils.arrayBuffer2HexString(res.value) }`);
onSendSuccessCallBack(bleUtils.arrayBuffer2HexString(res.value));
})
}


/**
* 发送指令,不关心指令具体长度
* @param commond 指令
* @param onSuccess 指令执行成功回调
*/
function sendCmd(commond, onSuccess, onFailCallback) {

var sendCommonds = crc.getCRCCmd(commond); //对commond的CRC处理必须放在这里
if ( typeof onSuccess == 'undefined') {
onSuccess = function (result) { }
}
onSendSuccessCallBack = onSuccess;
sendCmds(sendCommonds, 0, onFailCallback);
}

/**
*
* 逐条发送指令
*/
function sendCmds(commond, index, onFailCallback) {
var itemCmd;
var isLast = false; // 判断是否是最后一条
if (commond.length > index + 40) {
itemCmd = commond.substr(index, 40);
} else {
isLast = true;
itemCmd = commond.substr(index);
}
writeCommendToBle(itemCmd, function (errMsg) {
if (errMsg == 'ok' && !isLast) { // 发送成功并且不是最后一条时,执行下一条
sendCmds(commond, index + 40);
}

}, onFailCallback)
}

// 向蓝牙中写入数据(ble蓝牙)(增加指纹)
function writeCommendToBle(commonds, onSendCallback, onFailCallback) {
var commond = commonds;
console.log( "commond :" + commond)
let buffer = bleUtils.hexString2ArrayBuffer(commond);
console.log( `执行指令:${bleUtils.arrayBuffer2HexString(buffer) }`);

wx.writeBLECharacteristicValue({
deviceId: currentDevice.deviceId + "",
serviceId: writeService.uuid + '',
characteristicId: writeCharacteristic.uuid + '',
// 这里的value是ArrayBuffer类型
value: buffer,
success: function (res) {
console.log( '发送指令成功')
console.log( 'writeBLECharacteristicValue success', res.errMsg)
onSendCallback( 'ok');
},
fail: function (res) {
console.log( `执行指令失败${res.errMsg }`);
onFailCallback( "执行指令失败");

}
})
}

crc.js文件:

function CRC16(data) {
var len = data.length;
if (len > 0) {
var crc = 0xFFFF;

for ( var i = 0; i < len; i++) {
crc = (crc ^ (data[i]));
for ( var j = 0; j < 8; j++) {
crc = (crc & 1) != 0 ? ((crc >> 1) ^ 0xA001) : (crc >> 1);
}
}
var hi = ((crc & 0xFF00) >> 8); //高位置
var lo = (crc & 0x00FF); //低位置

// return [hi, lo];
return [lo, hi]; // 大端模式
}
return [ 0, 0];
};

function isArray(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
};

function ToCRC16(str, isReverse) {
return toString(CRC16(isArray(str) ? str : strToByte(str)), isReverse);
};



function strToByte(str) {
var tmp = str.split( ''), arr = [];
for ( var i = 0, c = tmp.length; i < c; i++) {
var j = encodeURI(tmp[i]);
if (j.length == 1) {
arr.push(j.charCodeAt());
} else {
var b = j.split( '%');
for ( var m = 1; m < b.length; m++) {
arr.push(parseInt( '0x' + b[m]));
}
}
}
return arr;
};

function convertChinese(str) {
var tmp = str.split( ''), arr = [];
for ( var i = 0, c = tmp.length; i < c; i++) {
var s = tmp[i].charCodeAt();
if (s <= 0 || s >= 127) {
arr.push(s.toString( 16));
}
else {
arr.push(tmp[i]);
}
}
return arr;
};

function filterChinese(str) {
var tmp = str.split( ''), arr = [];
for ( var i = 0, c = tmp.length; i < c; i++) {
var s = tmp[i].charCodeAt();
if (s > 0 && s < 127) {
arr.push(tmp[i]);
}
}
return arr;
};

function strToHex(hex, isFilterChinese) {
hex = isFilterChinese ? filterChinese(hex).join( '') : convertChinese(hex).join( '');

//清除所有空格
hex = hex.replace(/\s/g, "");
//若字符个数为奇数,补一个空格
hex += hex.length % 2 != 0 ? " " : "";

var c = hex.length / 2, arr = [];
for ( var i = 0; i < c; i++) {
arr.push(parseInt(hex.substr(i * 2, 2), 16));
}
return arr;
};

function padLeft(s, w, pc) {
if (pc == undefined) {
pc = '0';
}
for ( var i = 0, c = w - s.length; i < c; i++) {
s = pc + s;
}
return s;
};

function toString(arr, isReverse) {
if ( typeof isReverse == 'undefined') {
isReverse = true;
}
var hi = arr[ 0], lo = arr[ 1];
return padLeft((isReverse ? hi + lo * 0x100 : hi * 0x100 + lo).toString( 16).toUpperCase(), 4, '0');
};

function CRC16(data) {
var len = data.length;
if (len > 0) {
var crc = 0xFFFF;

for ( var i = 0; i < len; i++) {
crc = (crc ^ (data[i]));
for ( var j = 0; j < 8; j++) {
crc = (crc & 1) != 0 ? ((crc >> 1) ^ 0xA001) : (crc >> 1);
}
}
var hi = ((crc & 0xFF00) >> 8); //高位置
var lo = (crc & 0x00FF); //低位置

// return [hi, lo];
return [lo, hi]; // 大端模式
}
return [ 0, 0];
};


function ToCRC16(str, isReverse) {
return toString(CRC16(isArray(str) ? str : strToByte(str)), isReverse);
};

function ToModbusCRC16(str, isReverse) {
return toString(CRC16(isArray(str) ? str : strToHex(str)), isReverse);
};



/**
* 给命令增加CRC 16进制
*
* @param hex
* @return 16进制
*/
function getCRCCmd(hex) {
var hexTemp = hex;
if (hex.toUpperCase().startsWith( "0X")) {
hexTemp = hex.substr( 4);
} else if (hex.toUpperCase().startsWith( "AA")) {
hexTemp = hex.substr( 2);
}
return hex + getCRCStr(hexTemp);
}

/**
* 获取CRC 16进制
*
* @param data
* @return
*/
function getCRCStr(data) {
return ToModbusCRC16(data);
}





module.exports = {
ToCRC16: ToCRC16,
ToModbusCRC16: ToModbusCRC16,
getCRCCmd: getCRCCmd
}


strUtils文件:

/**
* ArrayBuffer转16进制字符串
*/
function arrayBuffer2HexString(buf) {
var out = "";
var u8a = new Uint8Array(buf);
var single;
for ( var i = 0; i < u8a.length; i++) {
single = u8a[i].toString( 16)
while (single.length < 2) single = "0".concat(single);
out += single;
}
return out;
}


/**
* 1、字符串转换为十六进制
* 主要使用 charCodeAt()方法,此方法返回一个字符的 Unicode 值,该字符位于指定索引位置。
*/
function stringToHex(str) {
var val = "";
for ( var i = 0; i < str.length; i++) {
val += str.charCodeAt(i).toString( 16);
}
return val;
}



function filterChinese(str) {
var tmp = str.split( ''), arr = [];
for ( var i = 0, c = tmp.length; i < c; i++) {
var s = tmp[i].charCodeAt();
if (s > 0 && s < 127) {
arr.push(tmp[i]);
}
}
return arr;
};
function strToHex(hex, isFilterChinese) {
hex = isFilterChinese ? filterChinese(hex).join( '') : convertChinese(hex).join( '');

//清除所有空格
hex = hex.replace(/\s/g, "");
//若字符个数为奇数,补一个空格
hex += hex.length % 2 != 0 ? " " : "";

var c = hex.length / 2, arr = [];
for ( var i = 0; i < c; i++) {
arr.push(parseInt(hex.substr(i * 2, 2), 16));
}
return arr;
};


/**
* 16进制字符串转ArrayBuffer
*/
function hexString2ArrayBuffer(hexStr) {
var count = hexStr.length / 2;
let buffer = new ArrayBuffer(count);
let dataView = new DataView(buffer);
for ( var i = 0; i < count; i++) {
var curCharCode = parseInt(hexStr.substr(i * 2, 2), 16);
dataView.setUint8(i, curCharCode);
}
return buffer;
}


/**
* 字符串转为ArrayBuffer对象,参数为字符串
*/
function string2ArrayBuffer(str) {
var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
var bufView = new Uint8Array(buf);
for ( var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}

function isArray(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
};




function strToByte(str) {
var tmp = str.split( ''), arr = [];
for ( var i = 0, c = tmp.length; i < c; i++) {
var j = encodeURI(tmp[i]);
if (j.length == 1) {
arr.push(j.charCodeAt());
} else {
var b = j.split( '%');
for ( var m = 1; m < b.length; m++) {
arr.push(parseInt( '0x' + b[m]));
}
}
}
return arr;
};

function convertChinese(str) {
var tmp = str.split( ''), arr = [];
for ( var i = 0, c = tmp.length; i < c; i++) {
var s = tmp[i].charCodeAt();
if (s <= 0 || s >= 127) {
arr.push(s.toString( 16));
}
else {
arr.push(tmp[i]);
}
}
return arr;
};

function filterChinese(str) {
var tmp = str.split( ''), arr = [];
for ( var i = 0, c = tmp.length; i < c; i++) {
var s = tmp[i].charCodeAt();
if (s > 0 && s < 127) {
arr.push(tmp[i]);
}
}
return arr;
};

function strToHex(hex, isFilterChinese) {
hex = isFilterChinese ? filterChinese(hex).join( '') : convertChinese(hex).join( '');

//清除所有空格
hex = hex.replace(/\s/g, "");
//若字符个数为奇数,补一个空格
hex += hex.length % 2 != 0 ? " " : "";

var c = hex.length / 2, arr = [];
for ( var i = 0; i < c; i++) {
arr.push(parseInt(hex.substr(i * 2, 2), 16));
}
return arr;
};

function padLeft(s, w, pc) {
if (pc == undefined) {
pc = '0';
}
for ( var i = 0, c = w - s.length; i < c; i++) {
s = pc + s;
}
return s;
};

function toString(arr, isReverse) {
if ( typeof isReverse == 'undefined') {
isReverse = true;
}
var hi = arr[ 0], lo = arr[ 1];
return padLeft((isReverse ? hi + lo * 0x100 : hi * 0x100 + lo).toString( 16).toUpperCase(), 4, '0');
};


/**
* 16进制字符串异或处理
*
* @param str1
* @param str2
* @return
*/
function stringXor(str1, str2) {
if (!str1 && !str2) {
return "";
}
if (!str1 && str2) {
return str2;
}
if (str1 && !str2) {
return str1;
}
var longStr;
var shortStr;
if (str1.length >= str2.length) {
longStr = str1;
shortStr = str2;
} else {
longStr = str2;
shortStr = str1;
}
var count = parseInt(shortStr.length / 2);
var leftCount = longStr.length - shortStr.length;
var resultStr = "";
if (leftCount > 0) {
resultStr += longStr.substr( 0, leftCount);
}
for ( var i = 0; i < count; i++) {
var shortCharCode = parseInt(shortStr.substr(i * 2, 2), 16);
var longCharCode = parseInt(longStr.substr(leftCount + i * 2, 2), 16);
var resultCode = shortCharCode ^ longCharCode;
var single = resultCode.toString( 16);
while (single.length < 2) single = "0".concat(single);
resultStr += single;
}
return resultStr.toUpperCase();
}


/**
* 指令两个16进制字符串异或处理
*
* @param command
* @param secretKey
* @return
*/
function getSecretEncoding(command, secretKey) {
if (!command || !secretKey) {
return "";
}
var secretLength = secretKey.length;
var length = parseInt(command.length / secretLength);
console.log( `command(${command.length })/secretLength(${secretLength }) = ${length }`);
var resultCmd = "";
console.log( `secretKey(${secretKey.length }):${secretKey }`);
for ( var i = 0; i < length; i++) {
var part = command.substr(i * secretLength, secretLength);
resultCmd += stringXor(part, secretKey);
console.log( `part${i }:${stringXor(part, secretKey) }`);
}
var lastLen = command.length % secretLength;
if (lastLen > 0) {
console.log( `lastCMD:${command.substr(command.length - lastLen, lastLen) }`);
console.log( `lastSecretKey:${secretKey.substr( 0, lastLen) }`);
var lastPart = command.substr(command.length - lastLen, lastLen);
var lastCmd = stringXor(lastPart, secretKey.substr( 0, lastLen));
resultCmd += lastCmd;
console.log( `lastPart:${lastCmd }`);
}
return resultCmd;
}
/**
* 2、十六进制转换为字符串
*主要使用 fromCharCode()方法,此方法将 Unicode 码转换为与之对应的字符。
*/
function hexToString(str) {
var val = "";
var arr = str.split( ",");
for ( var i = 0; i < arr.length; i++) {
val += arr[i].fromCharCode(i);

}
return val;
}

/**
* 获取随机长度16进制字符串
*/
function getRamNumber(length) {
var result = '';
for ( var i = 0; i < length; i++) {
result += Math.floor(Math.random() * 16).toString( 16); //获取0-15并通过toString转16进制
}
//默认字母小写,手动转大写
return result.toUpperCase(); //另toLowerCase()转小写
}


/**
* 得到BCD码时间字符串
*
* @param datetime
* @return
*/
function getBCDTime(datetime, needWeek) {
if ( typeof datetime == 'undefined') {
datetime = new Date();
}
if ( typeof needWeek == 'undefined') {
needWeek = true;
}
var year = datetime.getFullYear() - 2000; //获取年份,从2000年开始计算
if (year < 0) year = 0; // 不允许小于2000年的年份出现
var month = datetime.getMonth() + 1; //获取月份 0-11 所以需要加1
var day = datetime.getDate(); //获取日
var hour = datetime.getHours(); //小时
var minute = datetime.getMinutes(); //分
var second = datetime.getSeconds(); //秒
if (needWeek) {
var dayOfWeek = datetime.getDay(); //一周的第几天 0-6
return formatNumber(year) + formatNumber(month) + formatNumber(day) + formatNumber(dayOfWeek)
+ formatNumber(hour) + formatNumber(minute) + formatNumber(second); // 得到BCD码的时间字符串
} else {
return formatNumber(year) + formatNumber(month) + formatNumber(day)
+ formatNumber(hour) + formatNumber(minute) + formatNumber(second); // 得到BCD码的时间字符串
}
}
function formatNumber(n) {
n = n.toString()
return (n[ 1] ? n : '0' + n) + "";
}



/**
* 判断一个字符串是否包含子串
*/
function isContains(str, substr) {

var strUp = str.toUpperCase();
var substrUp = substr.toUpperCase()

return new RegExp(substrUp).test(strUp);
}

/**
* 去除字符串中特定的字符
*/


function removeBytes(str, substr) {
var items = str.split(substr)
// 会得到一个数组,数组中包括利用o分割后的多个字符串(不包括o)
var newStr = items.join( "");
return newStr
// }

}


module.exports = {
hexString2ArrayBuffer: hexString2ArrayBuffer,
arrayBuffer2HexString: arrayBuffer2HexString,
// getCRCCmd: getCRCCmd,
getBCDTime: getBCDTime,
stringToHex: stringToHex,
stringXor: stringXor,
getSecretEncoding: getSecretEncoding,
hexToString: hexToString,
getRamNumber: getRamNumber,
isContains: isContains,
removeBytes: removeBytes
}
听过baseBleApi接口调用输入参数直接可以对ble设备进行搜索发送链接

傻瓜式调用,

为了方便用户,这里进行了二级封装

antsBleApi.js文件时为了方便用户调用的二级接口:

var bleApi = require( 'baseBleApi.js');


module.exports = {
sendCommand: sendCommand
}

function sendCommand(params) {
var defaults = {
adviceId: "",
sendCommend: "",
onSuccessCallBack: function successCallBack(res) { },
onFailCallBack: function failCallBack(res) { },
onCompleteCallBack: function completeCallBack(res) { },
services: [ "xxxxx-xxxxxxxxx-xxxxx"],
writeServiceUUID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx",
notifyServiceUUID: "xxxxxxxxxx-xxxx -xxxx-xxxx-xxxxxxxxxxx",
notifyCharacteristicUUID: "xxxxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxx",
writeCharacteristicUUID: "xxxx-xxxx-xxxx-xxxx-xxxx"
}
var setParams = Object.assign(defaults, params)
bleApi.writeCommend(setParams);
}
此接口中service可以不写,但是adviceId,链接时必须写,,链接标志, writeServiceUUID,notifyServiceUUID,notifyCharacteristicUUID,writeCharacteristicUUID
这几个参数是为了进行ble设备通信所用到的


调用demo:

openDoor: function () {
var that = this
progressUtils.showLoding();

bleApi.sendCommand({
deviceId: "xx:xx:xx:xx:xx:xx", sendCommend: "xxxxxxxxx", onSuccessCallBack: function onSuccessCallBack(result) {
wx.showToast({
title: result,
icon: '',
image: '',
duration: 1500,

})


console.log( 'result:' + result);
}
});


  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: 微信小程序是一种在微信平台上运行的应用程序,它具有轻量化、便捷性和高兼容性的特点。微信小程序可以通过蓝牙低功耗(BLE)协议连接外部设备,并向外部设备发送数据。以下是一个示例代码,演示如何在微信小程序中实现BLE设备连接发送。 首先,在小程序的json配置文件中声明需要使用蓝牙能力: ```json { "permissions": { "bluetooth": true, "ble": true } } ``` 然后,在小程序的页面逻辑代码中执行以下步骤: 1. 开启蓝牙适配器并监听状态变化: ```js wx.openBluetoothAdapter({ success: function(res) { console.log("蓝牙适配器已打开"); // 监听蓝牙适配器状态变化 wx.onBluetoothAdapterStateChange(function(res) { console.log("蓝牙适配器状态变化", res); }); }, fail: function(res) { console.log("打开蓝牙适配器失败", res); } }); ``` 2. 开始搜索周围的蓝牙设备: ```js wx.startBluetoothDevicesDiscovery({ success: function(res) { console.log("开始搜索蓝牙设备"); // 监听蓝牙设备发现事件 wx.onBluetoothDeviceFound(function(res) { console.log("发现蓝牙设备", res.devices); // 可以通过设备的serviceUUIDs等信息筛选需要连接设备 // 根据条件筛选出需要连接设备后,调用stopBluetoothDevicesDiscovery停止搜索 }); }, fail: function(res) { console.log("开始搜索蓝牙设备失败", res); } }); ``` 3. 连接目标设备: ```js wx.createBLEConnection({ deviceId: "设备ID", success: function(res) { console.log("蓝牙设备连接成功"); // 连接成功后,可以调用getBLEDeviceServices获取设备的服务列表 }, fail: function(res) { console.log("蓝牙设备连接失败", res); } }); ``` 4. 向设备发送数据: ```js wx.writeBLECharacteristicValue({ deviceId: "设备ID", serviceId: "服务UUID", characteristicId: "特征值UUID", value: "发送的数据", success: function(res) { console.log("数据发送成功"); }, fail: function(res) { console.log("数据发送失败", res); } }); ``` 以上就是一个简单的示例代码,演示了如何在微信小程序中实现BLE设备连接发送。请注意,实际应用中可能还需要处理设备发现、服务筛选、数据解析等其他逻辑,并适配不同的设备和场景。 ### 回答2: 微信小程序是一种在微信客户端中运行的应用程序,它可以通过微信平台提供的接口与其他设备进行连接和通信。在微信小程序连接发送数据到BLE(Bluetooth Low Energy)设备源码如下: 1. 首先,我们需要在小程序的app.json文件中配置微信客户端的权限,使其支持蓝牙功能。 ``` "permissions": { "ble": true } ``` 2. 在小程序的页面中创建一个按钮或者其他交互元素,用于触发蓝牙设备连接事件。 ``` <button bindtap="connectDevice">连接设备</button> ``` 3. 在小程序对应的js文件中,编写连接蓝牙设备的相关代码。首先,获取蓝牙适配器实例。 ``` wx.openBluetoothAdapter({ success: function (res) { // 成功打开蓝牙适配器 // 在这里可以进行后续操作,如搜索附近的设备 }, fail: function (res) { // 打开蓝牙适配器失败 } }); ``` 4. 接下来,可以使用蓝牙适配器的方法搜索附近的设备。 ``` wx.startBluetoothDevicesDiscovery({ success: function (res) { // 成功开始搜索 // 在这里可以获取搜索到的设备列表,选择需要连接设备 }, fail: function (res) { // 开始搜索失败 } }); ``` 5. 当选择需要连接设备后,可以调用蓝牙适配器的connect方法进行设备连接。 ``` wx.createBLEConnection({ deviceId: deviceId, success: function (res) { // 连接设备成功 // 在这里可以进行后续操作,如发送数据到设备 }, fail: function (res) { // 连接设备失败 } }); ``` 6. 连接成功后,可以使用蓝牙适配器的write方法发送数据到设备。需要注意的是,发送的数据必须是ArrayBuffer类型。 ``` wx.writeBLECharacteristicValue({ deviceId: deviceId, serviceId: serviceId, characteristicId: characteristicId, value: buffer, success: function (res) { // 发送数据成功 }, fail: function (res) { // 发送数据失败 } }); ``` 以上就是微信小程序连接发送数据到BLE设备的简要源码解析。需要根据具体的业务需求和设备特性进行相应的开发和调试。 ### 回答3: 微信小程序是一种能够在微信中运行的轻量级应用程序,它可以通过连接BLE蓝牙低功耗)设备与之进行通信。在微信小程序中,可以使用wx.createBLEConnection方法来进行BLE设备连接。 要连接BLE设备,首先需要通过wx.openBluetoothAdapter方法打开蓝牙适配器,确保用户已经授权蓝牙权限。然后,使用wx.startBluetoothDevicesDiscovery方法开始搜索附近的蓝牙设备,并监听wx.onBluetoothDeviceFound回调事件来获取扫描到的蓝牙设备信息。 当发现需要连接BLE设备后,可以使用wx.createBLEConnection方法来与设备建立连接。该方法接收一个参数,即BLE设备的deviceId。成功建立连接后,可以通过监听wx.onBLEConnectionStateChanged事件获取连接状态。 连接建立后,可以使用wx.writeBLECharacteristicValue方法来发送数据给BLE设备。该方法接收四个参数,即连接deviceId、serviceId、characteristicsId和data。其中,services和characteristics需要通过wx.getBLEDeviceServices和wx.getBLEDeviceCharacteristics方法获取。 要注意的是,在发送数据之前,需要先通过wx.notifyBLECharacteristicValueChange方法启用notify功能,并监听wx.onBLECharacteristicValueChange回调事件来接收设备返回的数据。 以上是关于微信小程序BLE设备连接发送的简介,涉及的源码实现较为复杂,还需根据具体设备和业务需求进行进一步的开发与调试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值