Cordova 使用 cordova-plugin-ble-central 蓝牙插件,实现蓝牙设备持续扫描,打印RSSI等信息 RSSI三点定位 demo
前言
算法讲解:RSSI 平面 三点定位算法(C语言、JS源码例程)
你已经装好了cordova及其环境和插件cordova-plugin-ble-central。
插件官网:Bluetooth Low Energy (BLE) Central Plugin for Apache Cordova
官网自带例程,可直接参考。
安装命令 npm i cordova-plugin-ble-central
添加插件 cordova plugin add cordova-plugin-ble-central
以下是我的环境
ps:如果想跑例程,我已经打好debug版apk,release中下载即可
代码下载
版本更新
V1.0 即本文演示内容版本
V2.0 新增RSSI三点定位
V2.1 参考点、1m时的rssi值的绝对值,环境衰减因子可配置。功能配置页可切换。
V2.2 新增平行xy轴筛选、可用参考点全组合求平均解算法
V2.3 合并配置项,针对信标进行单一配置
V2.4 新增“删除信标”功能,文本可以进行复制
效果图
都是安卓为示例
完整演示动图
主界面
效果页
核心代码
index.js
// 设备列表
var deviceList = [];
var loopScan;
// 显示设备列表于deviceListDiv
function showDeviceList() {
document.getElementById("deviceListDiv").innerHTML = "";
/*
参考:http://www.elecfans.com/baike/wuxian/20171120582427.html
公式 d=10^((ABS(RSSI)-A)/(10*n))
其中d为距离,单位是m。
RSSI为rssi信号强度,为负数。
A为距离探测设备1m时的rssi值的绝对值,最佳范围在45-49之间。
n为环境衰减因子,需要测试矫正,最佳范围在3.25-4.5之间
*/
var d = 0;
var A = 50;
var n = 2.96;
// 遍历deviceList
for(var i=0; i<deviceList.length; i++){
var msgDiv = document.createElement("div");
d = Math.pow(10, (Math.abs(deviceList[i].rssi) - A) / (10 * n));
msgDiv.textContent = JSON.stringify(deviceList[i]) + " RSSI算法预估距离:" + d;
msgDiv.style.padding = "5px 0";
msgDiv.style.borderBottom = "rgb(192,192,192) solid 1px";
document.getElementById("deviceListDiv").appendChild(msgDiv);
}
//log(deviceList, "log");
log("调用showDeviceList()", "log");
}
// 打印日志
function log(msg, level) {
level = level || "log";
if (typeof msg === "object") {
msg = JSON.stringify(msg, null, " ");
}
console.log(msg);
if (level === "status" || level === "error" || level === "success") {
var msgDiv = document.createElement("div");
msgDiv.textContent = msg;
if (level === "error") {
msgDiv.style.color = "red";
}
else if(level === "success") {
msgDiv.style.color = "green";
}
msgDiv.style.padding = "5px 0";
msgDiv.style.borderBottom = "rgb(192,192,192) solid 1px";
document.getElementById("output").appendChild(msgDiv);
}
else {
var msgDiv = document.createElement("div");
msgDiv.textContent = msg;
msgDiv.style.color = "#57606a";
msgDiv.style.padding = "5px 0";
msgDiv.style.borderBottom = "rgb(192,192,192) solid 1px";
document.getElementById("output").appendChild(msgDiv);
}
}
// 扫描蓝牙设备
function scanBT() {
var idSubstring = document.getElementById('idSubstring').value;
ble.startScan([], function(res) {
deviceListLen = deviceList.length;
// 判空
if(idSubstring.length != 0){
// 含有子串
if(res["id"].indexOf(idSubstring) >= 0) {
// deviceList为空则直接加入
if(0 == deviceListLen) {
deviceList.push(res);
}
else {
for(var i=0; i<deviceListLen; i++){
if(deviceList[i].id == res["id"]){
log("发现同id:" + deviceList[i].id +
"消息,进行rssi值的替换,原rssi:" +
deviceList[i].rssi +
",现rssi:" +
res["rssi"], "log");
deviceList[i].rssi = res["rssi"];
break;
}
if(i == (deviceListLen - 1)) deviceList.push(res);
}
}
// 重新显示设备列表
showDeviceList();
}
}
else {
if(0 == deviceListLen) {
deviceList.push(res);
}
else {
for(var i=0; i<deviceListLen; i++){
if(deviceList[i].id == res["id"]){
log("发现同id:" + deviceList[i].id +
"消息,进行rssi值的替换,原rssi:" +
deviceList[i].rssi +
",现rssi:" +
res["rssi"], "log");
deviceList[i].rssi = res["rssi"];
break;
}
if(i == (deviceListLen - 1)) deviceList.push(res);
}
}
showDeviceList();
}
//log(JSON.stringify(res), "status");
}, function(res){
log("扫描蓝牙设备失败", "error");
});
}
document.addEventListener('deviceready', function () {
// 停止扫描按钮
var stopScanBtn = document.getElementById('stopScanBtn');
stopScanBtn.onclick = function(){
clearInterval(loopScan);
ble.stopScan(function(res){
log("停止扫描成功", "success");
}, function(res){
log("停止扫描失败", "error");
});
};
// 开始扫描按钮
var startScanBtn = document.getElementById('startScanBtn');
startScanBtn.onclick = function() {
loopScan = setInterval(scanBT, 3000);
};
// 清空日志按钮
var clearOutBtn = document.getElementById('clearOutBtn');
clearOutBtn.onclick = function(){
document.getElementById("output").innerHTML =