import {
isAndroid,
loadingTool
} from './common.js';
import {
deviceConfigList
} from './bluetooth_config.js';
let bluetoothTool = null;
if (isAndroid) {
//#ifdef APP-PLUS
bluetoothTool = new BluetoothToolClassic();
//#endif
}
//每个包最大数据内容
let MAX_PACKAGE_NUM = 20;
let _bluetoothOpenFlag = false;
let _readDataFlag = false;
let _readDataArray = [];
let _callback_success;
let _callback_fail;
String.prototype.replaceAll = function(s1,s2){
return this.replace(new RegExp(s1,"gm"),s2);
}
/**
- 连接设备
- @param {Object} deviceId
- @param {Object} name
- @param {Object} successFn
-
*/
function connectionToDevice(deviceId, name, successFn){
loadingTool.setMsg("蓝牙连接中...");
//2秒内未完成则显示连接中提示
setTimeout(() => { loadingTool.start() }, 2000);//check设备是否为经典蓝牙
let isClassic = _checkDeviceIsClassic(name);
//获取设备配置信息
let device = getDeviceConfig(name);//传统蓝牙
if (isClassic) {
_initBluetooth(() => {
// 连接传统蓝牙设备(安卓)
if (bluetoothTool.connDevice(deviceId, device.serviceId, successFn)) {
//蓝牙连接成功,设置回调监听函数
_connectionSuccessCallback(deviceId, device);
} else {
failFn()
};
});
} else {
_initBluetooth(() => {
//连接ble蓝牙设备
_connectionBle(deviceId, device, successFn);
});
}
}
/**
- 关闭设备连接
- @param {Object} deviceId
- @param {Object} name
-
@param {Object} sucessFn
*/
function closeConnection(deviceId, name , sucessFn){
//check设备是否为经典蓝牙
let isClassic = _checkDeviceIsClassic(name);_initBluetooth(()=> {
//传统蓝牙
if (isClassic) {
// 连接传统蓝牙设备(安卓)
let result = bluetoothTool.disConnDevice();
_bluetoothOpenFlag = false;
_readDataFlag = false;
result && sucessFn && sucessFn();
} else {
uni.closeBLEConnection({
deviceId,
success() {
console.log("close closeBLEConnection success!" + deviceId)
},
complete() {
uni.closeBluetoothAdapter({
success(res) {
console.log("close closeBluetoothAdapter!")
sucessFn && sucessFn()
}
});
_bluetoothOpenFlag = false;
_readDataFlag = false;
}
});
}
});
}
/**
- 根据蓝牙设备名称获取设备配置信息
- @param {Object} name
-
*/
function getDeviceConfig (name){
if(! name){
return null;
}var lName = name.toLowerCase();
for (var i = 0; i < deviceConfigList.length; i++) {
if (lName.indexOf(deviceConfigList[i].deviceName) >= 0) {
return deviceConfigList[i];
}
}
console.log("Can't find this device! name:" + name);
return null;
}
/**
- 搜索蓝牙设备
- @param {Object} addDevicesProc
- @param {Object} completeFn
-
@param {Object} timeout
*/
function searchBluetoothDevice(addDevicesProc, completeFn, timeout) {
//蓝牙初始化完毕后,开启搜索
_initBluetooth(()=> {
uni.startBluetoothDevicesDiscovery({
success(res) {
console.log(JSON.stringify(res))
uni.onBluetoothDeviceFound(function(res) {
let deviceArray = [];
res.devices.forEach(function(item){
let tmp = getDeviceConfig(item.name);
if(tmp){
tmp.deviceId = item.deviceId;
deviceArray.push(tmp);
}
});if (deviceArray.length > 0) { addDevicesProc && addDevicesProc(deviceArray); } }); }, fail(res) { console.log(JSON.stringify(res)) _doWithRet(res, completeFn) } }); //指定搜索时间后,自动停止搜索设备 setTimeout(() => { uni.getBluetoothAdapterState({ complete(res) { console.log(JSON.stringify(res)) //正在搜索设备的话,就停止搜索 if (res.discovering == true) { uni.stopBluetoothDevicesDiscovery({ success(res) { completeFn && completeFn(); } }); } }, fail(ret) { _doWithRet(ret, completeFn); } }); }, timeout);
});
}
/**
- 停止搜索蓝牙设备
*/
function stopBluetoothDevicesDiscovery() {
_initBluetooth(()=> {
uni.stopBluetoothDevicesDiscovery({
success: e => {
console.log('停止搜索蓝牙设备:' + e.errMsg);
},
fail: e => {
console.log('停止搜索蓝牙设备失败,错误码:' + e.errCode);
}
});
});
}
/**
- 向指定设备发送指令数据
- @param {Object} deviceId
- @param {Object} name
- @param {Object} sendData
- @param {Object} sucessFn
- @param {Object} failFn
-
*/
function sendBleCommand(deviceId, name, dataInfo, sucessFn, failFn) {
console.log("dataInfo:" + dataInfo );//设置成功/失败回调函数
_callback_success = sucessFn;
_callback_fail = failFn;_initBluetooth(()=> {
//获取设备配置信息
let device = getDeviceConfig(name);
//check设备是否为经典蓝牙
let isClassic = _checkDeviceIsClassic(name);console.log("send data :" + deviceId + " " + device.serviceId + " " + device.wcharacteristicId); if (isClassic) { // 连接传统蓝牙设备(安卓) if (bluetoothTool.connDevice(deviceId, '') && bluetoothTool.sendData(dataInfo)) { //sucessFn && sucessFn(); } else { failFn && failFn(); } } else { uni.getBLEDeviceServices({ // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接 deviceId: deviceId, success(res) { console.log('device services:', res.services) // setTimeout(()=>{ //分包发送数据(20字节以内) let packageArray = getSendDataArray(dataInfo); _sendData(packageArray, 0, deviceId, device, isClassic); // }, 1000); } }) }
});
}
/**
- 发送蓝牙数据信息
- @param {Object} dataArray
- @param {Object} index
- @param {Object} deviceId
- @param {Object} device
- @param {Object} isClassic
-
*/
function _sendData(dataArray, index, deviceId, device, isClassic){
if(index > dataArray.length - 1){
//数据包发送完毕后,设置监听设备发过来的数据
_readData(deviceId, device, isClassic);
return;
}if(isClassic){
//经典蓝牙
bluetoothTool.sendData(dataArray[index], ()=>{_sendData(dataArray, (index+1), deviceId, device, isClassic)});
}else{
//低功耗蓝牙
// uni.getBLEDeviceCharacteristics({
// deviceId: deviceId,
// serviceId: device.serviceId,
// success(res) {
// console.log('device getBLEDeviceCharacteristics:', res.characteristics)uni.writeBLECharacteristicValue({ deviceId: deviceId, serviceId: device.serviceId, characteristicId: device.wcharacteristicId, value: hexStringToArrayBuffer(dataArray[index]), success(res) { console.log(JSON.stringify(res)); _sendData(dataArray, (index + 1), deviceId, device, isClassic ); }, fail(res) { console.log(JSON.stringify(res)); }, complete(res) { console.log(JSON.stringify(res)); } }); // } // });
}
}
/**
- 读取蓝牙设备数据(经典蓝牙&低功耗蓝牙)
- @param {Object} deviceId
- @param {Object} device
- @param {Object} isClassic
*/
function _readData(deviceId, device, isClassic){
//只需要设置一次回调函数
if(! _readDataFlag){
if(isClassic){
//经典蓝牙
bluetoothTool.readData();
}else{
//低功耗蓝牙
_readDataByBle(deviceId, device);
}
_readDataFlag = true;
}
}
/**
- 读取低功耗蓝牙设备数据
- @param {Object} deviceId
- @param {Object} device
-
*/
function _readDataByBle(deviceId, device){
uni.getBLEDeviceServices({
deviceId: deviceId,
success(res) {
console.log('device services:', res.services)uni.getBLEDeviceCharacteristics({ deviceId: deviceId, serviceId: device.serviceId, success(res) { console.log('device getBLEDeviceCharacteristics:', res.characteristics) uni.notifyBLECharacteristicValueChange({ state: true, // 启用 notify 功能 deviceId: deviceId, serviceId: device.serviceId, characteristicId: device.characteristicId, success(res) { console.log('notifyBLECharacteristicValueChange success', JSON.stringify(res)) // 必须在这里的回调才能获取 uni.onBLECharacteristicValueChange(function (res) { let data = _ab2hex(res.value); if(data.startsWith("4e") && data.length > 2){ _readDataArray.splice(0, _readDataArray.length); } _readDataArray.push(data); if(data.endsWith("4e")){ _receiveDataCallBack(); } console.log(data) }); } }); } });
}
});
}
/**
- 接收到完整数据包后,执行回调函数
-
*/
function _receiveDataCallBack(){
console.log("_receiveDataCallBack:" + JSON.stringify(_readDataArray) )let dataInfo = "";
let index = 0;
for(let i = 0 ; _readDataArray.length ; i++ ){
dataInfo = dataInfo + _readDataArray[i];
if(_readDataArray[i].endsWith("4e")){
index = i + 1;
break ;
}
}
//删除解析后的数据包
_readDataArray.splice(0, index);//字符转义
dataInfo = _decodeBleData(dataInfo);//数据格式问题,直接返回不做处理
if(dataInfo.length < 22){
return ;
}let dataCode = dataInfo.substring(18, (dataInfo.length - 4));
let receiveDataInfo = hexToString(dataCode);_callback_success && _callback_success(receiveDataInfo);
_callback_fail && _callback_fail();
}
/**
- 初始化蓝牙模块
-
*/
function _initBluetooth(successFn){
if(_bluetoothOpenFlag === true){
successFn && successFn();
return ;
}
//在页面加载时候初始化蓝牙适配器
uni.openBluetoothAdapter({
success: e => {
console.log('初始化蓝牙成功:' + e.errMsg);
_bluetoothOpenFlag = true;uni.getBluetoothAdapterState({ success(res) { console.log(JSON.stringify(res)); successFn && successFn(); }, fail(res) { //_doWithRet(res); } }); }, fail: e => { console.log('初始化蓝牙失败,错误码:' + (e.errCode || e.errMsg)); }
});
}
/**
- 连接ble蓝牙
-
*/
function _connectionBle(deviceId, device, successFn) {
console.log('蓝牙连接中:' + deviceId);
//初始化蓝牙模块后执行设备连接
_initBluetooth(()=> {
//先看是否已连接
uni.getConnectedBluetoothDevices({
success(res) {
console.log(JSON.stringify(res));
if (res.devices) {
for (var i = 0; i < res.devices.length; i++) {
if (res.devices[i].deviceId == deviceId) {
//蓝牙已经链接上了,不做任何处理
loadingTool.close();
return ;
}
}
}//连接蓝牙设备 uni.createBLEConnection({ deviceId: deviceId, timeout: 3000, //bug:timeout设置无效,且连不上也success success(res) { console.log("conn success:" + JSON.stringify(res)); successFn && successFn(); //蓝牙连接成功,设置回调监听函数 _connectionSuccessCallback(deviceId, device); }, fail(res) { loadingTool.close(); _doWithRet(res) }, complete(ret) { loadingTool.close(); } }); }, fail(res) { _connectionFail(); } });
});
}
/**
- 蓝牙设备连接成功后,设置相应的回调函数
- @param {Object} deviceId
- @param {Object} device
-
*/
function _connectionSuccessCallback(deviceId, device){
loadingTool.close();//check设备是否为经典蓝牙
let isClassic = _checkDeviceIsClassic(device.deviceName);if (isClassic) {
//经典蓝牙设备独立处理
bluetoothTool.setDisconnChangeCallback();
}else{
//蓝牙连接成功,设置回调监听函数
_setBluetoothCallback(deviceId, device);
}//设置监听设备发过来的数据
//_readData(deviceId, device);
}
function _connectionFail(){
loadingTool.close()
}
function _setBluetoothCallback(deviceId, device, disConnFn){
//初始化蓝牙模块后执行设备callback设置
_initBluetooth(()=> {
console.log("-----_setBluetoothCallback--------")
uni.onBluetoothAdapterStateChange(function(res) {
if (res.available == false) {
closeConnection();
}
});
uni.onBLEConnectionStateChange(function(res) {
if (res.connected == false && res.deviceId == deviceId) {
uni.showToast({
icon: 'none',
title: '连接已断开',
duration: 2000
});
closeConnection();
}
});
console.log("-----_setBluetoothCallback----deviceId:" + deviceId)
});
}
//检测设备是否为传统蓝牙(安卓手机& WOWOS、iNeck3)
function _checkDeviceIsClassic(name) {
if(!name){
return false;
}
if (isAndroid) {
const iNeck3 = name.toLowerCase().indexOf("iNeck3".toLowerCase()) != -1;
const WOWOS = name.toLowerCase().indexOf("WOWOS".toLowerCase()) != -1;
const iSeek = name.toLowerCase().indexOf("iSeek".toLowerCase()) != -1;
if (iNeck3 || WOWOS ) {
return true;
}
}
return false;
}
function _decodeBleData(data){
data = data.replaceAll("5e4d","4e");
data = data.replaceAll("5e5d","5e");
return data;
}
/**
- 发送数据包差分处理
-
@param {Object} data
*/
function getSendDataArray(data){
let resultArray = [];let dataHex = strToHexCharCode(data);
let dataLength = dataHex.length / 2;
dataLength = dataLength.toString(16);
for(let i = dataLength.length ; i < 4 ; i++ ){
dataLength = "0" + dataLength;
}dataHex = "01260201ffaa" + dataLength + dataHex;
//校验和取反
let checkCode = hexSumReverse(dataHex);
dataHex = dataHex + checkCode;let dataHexTrans = "";
for(let i = 0 ; i < dataHex.length / 2 ; i++){
let tmp = dataHex.substring(i2, i2+2);
if(tmp === "4e"){
dataHexTrans += "5e4d";
}else if(tmp === "5e"){
dataHexTrans += "5e5d";
}else{
dataHexTrans += tmp;
}
}
dataHexTrans = "4e" + dataHexTrans + "4e";let count = parseInt(dataHexTrans.length / 2 / MAX_PACKAGE_NUM);
if(((dataHexTrans.length / 2) % MAX_PACKAGE_NUM) > 0){
count ++;
}for(let i = 0 ; i < count ; i++){
let packInfo = "";
if(i < count - 1){
packInfo = dataHexTrans.substring(iMAX_PACKAGE_NUM2, iMAX_PACKAGE_NUM2 + MAX_PACKAGE_NUM 2);
}else{
packInfo = dataHexTrans.substring(iMAX_PACKAGE_NUM*2);
}
resultArray.push(packInfo);
}return resultArray;
}
/**
- 字符串转16进制字符( {"cmd":"GetWiFiList"} -> 7b22636d64223a22476574576946694c697374227d )
- @param {Object} str
*/
function strToHexCharCode(str) {
if(str === "")
return "";
var hexCharCode = "";
for(var i = 0; i < str.length; i++) {
let tmp = (str.charCodeAt(i)).toString(16);
if(tmp.length === 1){
tmp = "0" + tmp;
}
hexCharCode += tmp;
//hexCharCode.push((str.charCodeAt(i)).toString(16));
}
return hexCharCode;
}
/**
- 16进制字符串校验和取反(1234 -> b9)
-
@param {Object} hexCharCodeStr
*/
function hexSumReverse(hexCharCodeStr) {
var trimedStr = hexCharCodeStr.trim();
var rawStr = trimedStr.substr(0,2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
var curCharCode = 0;
var resultStr = [];
for(var i = 0; i < len;i = i + 2) {
curCharCode += parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value
}
let checkCode = (0xFF ^ curCharCode).toString(16);
if(checkCode.length === 1){
checkCode = "0" + checkCode;
}else if(checkCode.length > 2){
checkCode = checkCode.substring(checkCode.length - 2);
}//转义处理
if(checkCode === "4e"){
checkCode = "5e4d";
}else if(checkCode === "5e"){
checkCode = "5e5d";
}
return checkCode;
}
/**
- 16进制转buffer 数组
- @param {Object} str
*/
function hexStringToArrayBuffer(str) {
if (!str) {
return new ArrayBuffer(0);
}
var buffer = new ArrayBuffer(str.length / 2);
let dataView = new DataView(buffer)
let ind = 0;
for (var i = 0, len = str.length; i < len; i += 2) {
let code = parseInt(str.substr(i, 2), 16)
dataView.setUint8(ind, code)
ind++
}
console.log(str + " " + buffer + " " + (str.length / 2) + " ind:" + ind)
return buffer;
}
/**
- 处理蓝牙错误结果
-
*/
const _doWithRet = (ret, fn) => {
var errCode = ret.errCode;;
if (errCode == 10000) {
uni.openBluetoothAdapter({
success(ret) {
console.log("初始化蓝牙适配器成功!")
_bluetoothOpenFlag = true;
fn && setTimeout(fn, 1000)
},
fail(ret) {
uni.showToast({
icon: 'none',
title: '初始化蓝牙适配器失败',
duration: 2000
});
}
})
} else if (errCode == 10001) {
try {
bluetoothTool.turnOnBluetooth()
} catch (e) {
uni.showToast({
icon: 'none',
title: '蓝牙已关闭,请打开蓝牙!',
duration: 3000
});
}
} else if (errCode == 10002) {
uni.showToast({
icon: 'none',
title: '连接失败,请检查设备是否开启!',
duration: 2000
});
fn && fn()
} else if (errCode == 10003) {
uni.showToast({
icon: 'none',
title: '连接失败',
duration: 2000
});
fn && fn()
} else if (errCode == 10004) {
uni.showToast({
icon: 'none',
title: '没有找到指定服务',
duration: 2000
});
fn && fn()
} else if (errCode == -1) {
fn()
} else {
uni.showToast({
icon: 'none',
title: '蓝牙操作异常[' + errCode + ']',
duration: 2000
});
fn && fn()
}
}
/**
- buffer数组转16进制
- @param {Object} buffer
*/
function _ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2);
}
)
return hexArr.join('');
}
function _dec2utf8 (arr) {
if (typeof arr === 'string') {
return arr;
}
var unicodeString = '', _arr = arr;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2);
var 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)
}
unicodeString += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
} else {
unicodeString += String.fromCharCode(_arr[i]);
}
}
return unicodeString
};
/**
- 16进制字符串转string
-
@param {Object} hexx
*/
function hexToString(hexx) {
var hex = hexx.toString();//force conversionvar str_list = [];
for (var i = 0; (i < hex.length && hex.substr(i, 2) !== '00'); i += 2)
str_list.push(parseInt(hex.substr(i, 2), 16));return _dec2utf8(str_list);
}
function BluetoothToolClassic() {
let BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
let Intent = plus.android.importClass("android.content.Intent");
let IntentFilter = plus.android.importClass("android.content.IntentFilter");
let BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");
let UUID = plus.android.importClass("java.util.UUID");
let Toast = plus.android.importClass("android.widget.Toast");
//连接串口设备的 UUID
let DEFAULT_SERVICE_UUID = "00001101-0000-1000-8000-00805F9B34FB";
let invoke = plus.android.invoke;
let btAdapter = BluetoothAdapter.getDefaultAdapter();
let activity = plus.android.runtimeMainActivity();
//连接设备信息
let btSocket = null;
let btInStream = null;
let btOutStream = null;
let btDevice = null;
let setIntervalId = 0;
let setTimeCount = 0;
//用于接受设备传过来的数据
let receiverData = [];
let btFindReceiver = null; //蓝牙搜索广播接收器
let btStatusReceiver = null; //蓝牙状态监听广播
let state = {
bluetoothEnable: false, //蓝牙是否开启
bluetoothState: "", //当前蓝牙状态
discoveryDeviceState: false, //是否正在搜索蓝牙设备
readThreadState: false, //数据读取线程状态
};
let options = {
/**
* 监听蓝牙状态回调
* @param {String} state
*/
listenBTStatusCallback: function(state) {},
/**
* 搜索到新的蓝牙设备回调
* @param {Device} newDevice
*/
discoveryDeviceCallback: function(newDevice) {},
/**
* 蓝牙搜索完成回调
*/
discoveryFinishedCallback: function() {},
/**
* 接收到数据回调
* @param {Array} dataByteArr
*/
readDataCallback: function(data) {
console.log("readDataCallback:" + data)
},
/**
* 蓝牙连接中断回调
* @param {Exception} e
*/
connExceptionCallback: function(e) {}
}
this.init = function(setOptions) {
Object.assign(options, setOptions);
state.bluetoothEnable = getBluetoothStatus();
listenBluetoothStatus();
}
function shortToast(msg) {
Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
}
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2);
}
)
return hexArr.join('');
}
function hexStringToArrayBuffer(str) {
if (!str) {
return new ArrayBuffer(0);
}
var buffer = new ArrayBuffer(str.length / 2);
let dataView = new DataView(buffer);
let ind = 0;
for (var i = 0, len = str.length; i < len; i += 2) {
let code = parseInt(str.substr(i, 2), 16);
console.log()
dataView.setUint8(ind, code);
ind++;
}
return buffer;
}
function hexStringToByteArray(str) {
if (!str) {
return new Array(0);
}
var buffer = new Array(str.length / 2);
let index = 0;
for (var i = 0, len = str.length; i < len; i += 2) {
let code = parseInt(str.substr(i, 2), 16);
buffer[index++] = numToByte(code);
}
return buffer;
}
function numToByte(num) {
var dataStr = '';
if (num > 127) {
dataStr = parseInt(0xFF ^ (num - 128)).toString(2);
return -(parseInt(dataStr.substring(1), 2) + 1);
} else {
return num;
}
}
/**
* 是否支持蓝牙
* @return {boolean}
*/
function isSupportBluetooth() {
if (btAdapter != null) {
return true;
}
return false;
}
/**
* 获取蓝牙的状态
* @return {boolean} 是否已开启
*/
function getBluetoothStatus() {
if (btAdapter != null) {
return btAdapter.isEnabled();
}
return false;
}
/**
* 打开蓝牙
* @param activity
* @param requestCode
*/
this.turnOnBluetooth = function() {
if (btAdapter == null) {
shortToast("没有蓝牙");
return;
}
if (!btAdapter.isEnabled()) {
if (activity == null) {
shortToast("未获取到activity");
return;
} else {
let intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
let requestCode = 1;
activity.startActivityForResult(intent, requestCode);
return;
}
} else {
shortToast("蓝牙已经打开");
}
}
/**
* 关闭蓝牙
*/
function turnOffBluetooth() {
if (btAdapter != null && btAdapter.isEnabled()) {
btAdapter.disable();
}
if (btFindReceiver != null) {
try {
activity.unregisterReceiver(btFindReceiver);
} catch (e) {
}
btFindReceiver = null;
}
state.bluetoothEnable = false;
cancelDiscovery();
closeBtSocket();
if (btAdapter != null && btAdapter.isEnabled()) {
btAdapter.disable();
shortToast("蓝牙关闭成功");
} else {
shortToast("蓝牙已经关闭");
}
}
/**
* 获取已经配对的设备
* @return {Array} connetedDevices
*/
function getPairedDevices() {
let pairedDevices = [];
//蓝牙连接android原生对象,是一个set集合
let pairedDevicesAndroid = null;
if (btAdapter != null && btAdapter.isEnabled()) {
pairedDevicesAndroid = btAdapter.getBondedDevices();
} else {
shortToast("蓝牙未开启");
}
if (!pairedDevicesAndroid) {
return pairedDevices;
}
//遍历连接设备的set集合,转换为js数组
let it = invoke(pairedDevicesAndroid, "iterator");
while (invoke(it, "hasNext")) {
let device = invoke(it, "next");
pairedDevices.push({
"name": invoke(device, "getName"),
"address": invoke(device, "getAddress")
});
}
return pairedDevices;
}
/**
* 发现设备
*/
function discoveryNewDevice() {
if (btFindReceiver != null) {
try {
activity.unregisterReceiver(btFindReceiver);
} catch (e) {
console.error(e);
}
btFindReceiver = null;
cancelDiscovery();
}
let Build = plus.android.importClass("android.os.Build");
//6.0以后的如果需要利用本机查找周围的wifi和蓝牙设备, 申请权限
if (Build.VERSION.SDK_INT >= 6.0) {
}
btFindReceiver = plus.android.implements("io.dcloud.android.content.BroadcastReceiver", {
"onReceive": function(context, intent) {
plus.android.importClass(context);
plus.android.importClass(intent);
let action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND == action) { // 找到设备
let device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
let newDevice = {
"name": plus.android.invoke(device, "getName"),
"address": plus.android.invoke(device, "getAddress")
}
options.discoveryDeviceCallback && options.discoveryDeviceCallback(newDevice);
}
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) { // 搜索完成
cancelDiscovery();
options.discoveryFinishedCallback && options.discoveryFinishedCallback();
}
}
});
let filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
activity.registerReceiver(btFindReceiver, filter);
btAdapter.startDiscovery(); //开启搜索
state.discoveryDeviceState = true;
}
/**
* 蓝牙状态监听
* @param {Activity} activity
*/
function listenBluetoothStatus() {
if (btStatusReceiver != null) {
try {
activity.unregisterReceiver(btStatusReceiver);
} catch (e) {
console.error(e);
}
btStatusReceiver = null;
}
btStatusReceiver = plus.android.implements("io.dcloud.android.content.BroadcastReceiver", {
"onReceive": function(context, intent) {
plus.android.importClass(context);
plus.android.importClass(intent);
let action = intent.getAction();
switch (action) {
case BluetoothAdapter.ACTION_STATE_CHANGED:
let blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
let stateStr = "";
switch (blueState) {
case BluetoothAdapter.STATE_TURNING_ON:
stateStr = "STATE_TURNING_ON";
break;
case BluetoothAdapter.STATE_ON:
state.bluetoothEnable = true;
stateStr = "STATE_ON";
break;
case BluetoothAdapter.STATE_TURNING_OFF:
stateStr = "STATE_TURNING_OFF";
break;
case BluetoothAdapter.STATE_OFF:
stateStr = "STATE_OFF";
state.bluetoothEnable = false;
break;
}
state.bluetoothState = stateStr;
options.listenBTStatusCallback && options.listenBTStatusCallback(stateStr);
break;
}
}
});
let filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
activity.registerReceiver(btStatusReceiver, filter);
}
this.setDisconnChangeCallback = function(disConnFn) {
var intervalId = setInterval(function() {
try {
if (!btSocket || !btSocket.isConnected()) {
clearInterval(intervalId);
disConnFn && disConnFn();
}
} catch (e) {
console.log("测试连接失败。" + e);
}
}, 1000);
}
/**
* 根据蓝牙地址,连接设备
* @param {Stirng} address
* @return {Boolean}
*/
this.connDevice = function(deviceId, serviceId, successFn) {
console.log("connDevice:" + deviceId + " " + serviceId);
if (btOutStream) {
return true
}
try {
if (serviceId == '') {
serviceId = DEFAULT_SERVICE_UUID;
}
var serviceIdUuid = UUID.fromString(serviceId);
btDevice = btAdapter.getRemoteDevice(deviceId);
plus.android.importClass(btDevice);
btSocket = btDevice.createRfcommSocketToServiceRecord(serviceIdUuid);
console.log(serviceId)
} catch (e) {
console.log("=======" + e)
try {
btSocket = btDevice.createInsecureRfcommSocketToServiceRecord(serviceIdUuid);
} catch (e1) {
console.log("连接失败,获取Socket失败!" + e1);
return false;
}
}
plus.android.importClass(btSocket);
// var msg='设备蓝牙连接中...';
// uni.showLoading({title: msg});
try {
if (!btSocket.isConnected()) {
// shortToast('设备连接中');
btSocket.connect();
console.log("-------btSocket.connect()--------");
// msg='设备连接成功';
// } else {
// msg='设备已连接'
}
} catch (e) {
console.log("连接失败。" + e);
// msg='设备连接失败'
closeBtSocket();
return false;
} finally {
// uni.hideLoading()
// shortToast(msg);
}
//连接上设备,初始化输入、输出流
if (btSocket.isConnected()) {
btInStream = invoke(btSocket, "getInputStream");
plus.android.importClass(btInStream);
btOutStream = invoke(btSocket, "getOutputStream");
plus.android.importClass(btOutStream);
state.readThreadState = true;
successFn && successFn();
readData();
}
console.log("连接成功。" + btSocket.isConnected());
return true;
}
/**
* 断开连接设备
* @param {Object} address
* @return {Boolean}
*/
this.disConnDevice = function() {
if (btSocket != null) {
closeBtSocket();
}
state.readThreadState = false;
// shortToast("连接已断开");
return true
}
/**
* 断开连接设备
* @param {Object} address
* @return {Boolean}
*/
function closeBtSocket() {
state.readThreadState = false;
btInStream = null;
btOutStream = null;
btDevice = null;
if (!btSocket) {
return;
}
try {
btSocket.close();
} catch (e) {
console.error(e);
btSocket = null;
}
}
/**
* 取消发现
*/
function cancelDiscovery() {
if (btAdapter.isDiscovering()) {
btAdapter.cancelDiscovery();
}
if (btFindReceiver != null) {
activity.unregisterReceiver(btFindReceiver);
btFindReceiver = null;
}
state.discoveryDeviceState = false;
}
/**
* 发送数据
* @param {String} dataStr
* @return {Boolean}
*/
this.sendData = function(data, successFn) {
if (!btOutStream) {
shortToast("连接已断开");
closeBtSocket();
return false;
}
try {
var bytesArray = hexStringToByteArray(data);
btOutStream.write(bytesArray);
btOutStream.flush();
//successFn && successFn();
} catch (e) {
shortToast('操作失败。' + e);
console.log(e);
return false;
}
console.log('发送指令:' + data);
return true;
}
function readData() {
if (!btSocket) {
shortToast("请先连接蓝牙设备!");
return false;
}
clearInterval(setIntervalId);
setIntervalId = setInterval(function() {
if (state.readThreadState) {
setTimeCount++;
//console.log("readData : btSocket.isConnected() ==== " + btSocket.isConnected());
let startTime = new Date().getTime();
//心跳检测
// if(setTimeCount % 10 == 0) {
try {
btOutStream.write([0x00]);
} catch (e) {
closeBtSocket();
options.connExceptionCallback && options.connExceptionCallback(e);
}
// }
while (invoke(btInStream, "available") !== 0) {
let data = invoke(btInStream, "read");
receiverData.push(data);
let endTime = new Date().getTime();
//每次读取数据不超过20ms
if (endTime - startTime > 50) {
break;
}
}
if (receiverData.length > 0) {
var dataArray = [];
for (var i = 1; i < receiverData.length; i++) {
if (receiverData[i] == 78) {
dataArray = receiverData.splice(0, i + 1);
options.readDataCallback && options.readDataCallback(ab2hex(dataArray), dataArray);
}
}
}
}
}, 2000);
}
}
export {
getSendDataArray,
getDeviceConfig,
closeConnection,
sendBleCommand,
connectionToDevice,
searchBluetoothDevice,
stopBluetoothDevicesDiscovery
}
4 个回复
CLP
你就不能提供个demo来吗,这么大一串,没你的设备是不是复现不了问题?
l***@126.com (作者)
嗯,是啊。。没有设备。你们也测试不了。
其实就是连接成功后,发送指令【uni.writeBLECharacteristicValue】卡住不动。
安卓正常,ios不行。
8***@qq.com
我用iphone8调试,也遇到同样的问题,后面我用官方文档(如下的代码)向BLE发送一个16进制数据,也没有回调.
请求官方回复,谢谢!!
// 向蓝牙设备发送一个0x00的16进制数据
const buffer = new ArrayBuffer(1)
const dataView = new DataView(buffer)
dataView.setUint8(0, 0)
uni.writeBLECharacteristicValue({
// 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId,
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
characteristicId,
// 这里的value是ArrayBuffer类型
value: buffer,
success(res) {
console.log('writeBLECharacteristicValue success', res.errMsg)
}
})
3***@qq.com
请问解决没有现在我也是卡在writeBLECharacteristicValue就没响应了不报错也不成功
1***@qq.com
请问解决了吗
2023-03-13 15:40