下篇文章蓝牙RSSI定位入门到精通(4)-指纹法实现
https://blog.csdn.net/qq_35651984/article/details/82764334
实现步骤
- 指纹的采集(离线阶段)
- 指纹的处理(数据存储)
- 指纹的使用(在线阶段)
指纹的采集
采集概述
指纹采集,其实是knn中的分类问题,也就是将待测位置划分为小块,每一块为一个类。测试每个类接收到的特征,作为离线数据保存。如图,界面为待测地,将待测地划分测量。
采集实现
每个类,通过手机蓝牙采集20份特征,用平均分获得平均特征,传递给服务器。
将蓝牙名称绑定为信标(实际中应该绑定地址,测试就不介意了哈哈)
并进行初始化。(代码中全局变量应该改成类正规点,测试我就随便写啦)
private ArrayList<String> Arr_rss;//一次的各信标的rssi值
private ArrayList<String> Arr_address; //保存信标的地址(name)
private ArrayList<Integer> max;//各信标20次的rssi总值
private ArrayList<Integer> scanum;//扫描次数,总扫描某信标的次数
private String date=null;//用来显示
private String send_date=null;//发送给服务器
private String string=null;
private void init_beacon()
{
Arr_address=new ArrayList<String>();
Arr_address.add("111");//增加信标
Arr_address.add("555");
Arr_address.add("333");
Arr_rss=new ArrayList<String>();//距离由rssi获取
Arr_rss.add(null);
Arr_rss.add(null);
Arr_rss.add(null);
max=new ArrayList<Integer>();
max.add(0);
max.add(0);
max.add(0);
scanum=new ArrayList<Integer>();
scanum.add(0);
scanum.add(0);
scanum.add(0);
}
由于每次广播一个设备只能获得一次ACTION_FOUND,可以在广播接收者中循环取得三个信标的平均rssi,开启线程发送给服务器,结束广播,然后开始广播,连续20次
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action))
{
BluetoothDevice scanDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (scanDevice.getBondState() != BluetoothDevice.BOND_BONDED)
{
for (int i=0;i<Arr_address.size();i++)
{
if (Arr_address.get(i).equals(scanDevice.getName()))//获取到信标
{
Textview1.setText("查找次数:"+time++);
short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
Textview1.append("\n 信标:" + scanDevice.getName() );
Arr_rss.set(i,String.valueOf(rssi));//存rssi
max.set(i,Integer.valueOf(rssi)+max.get(i));//最大rssi加上
scanum.set(i,scanum.get(i)+1);//扫描次数加上
size_3++;//计时器加上
}
}
}
if (size_3>=3)//如果三个信标都扫到了
{
mBluetoothAdapter.cancelDiscovery();
date=date+Arr_rss.get(0)+" "+Arr_rss.get(1)+" "+Arr_rss.get(2)+"*";
}
}else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
{
Textview1.append("\n扫描完成");
if (size_10++<20&&size_3>=3)
{
size_3=0;
mBluetoothAdapter.startDiscovery();
}
if(size_10==20)
{
// mBluetoothAdapter.cancelDiscovery();
Textview1.setText("扫描20次完成");
Textview1.append("\n"+date);
Textview1.append("\n"+max.get(0));
Textview1.append("\n"+max.get(1));
Textview1.append("\n"+max.get(2));
send_date=string+"&"+max.get(0)/Double.valueOf(scanum.get(0))+"&"+max.get(1)/Double.valueOf(scanum.get(1))+"&"+max.get(2)/Double.valueOf(scanum.get(2));
Textview1.append("\n"+send_date+" "+size_10);
MyThread myThread=new MyThread(send_date);
myThread.start();
size_10++;//重置
size_3=0;
time=0;
scanum.set(0,0);
scanum.set(1,0);
scanum.set(2,0);
max.set(0,0);
max.set(1,0);
max.set(2,0);
}
}
}
线程的代码
public void run()
{
try {
Socket socket = new Socket("43.226.xxx.xxx",8888);
OutputStream out = socket.getOutputStream();
out.write(string.getBytes());
out.flush();
out.close();
socket.close();
}catch (Exception e)
{e.printStackTrace();}
指纹的处理
服务器端用一个qt程序接收并显示数据,并附上运动轨迹
qt创建套接字,监听后会得到newConnection的信号,在槽函数进行readyRead信号的接收,获得发来的数据。
connect(tcpserver,&QTcpServer::newConnection,
[=]()
{
ui->label->setText("建立连接");
tcpsocket=tcpserver->nextPendingConnection();//获得套接字
QString str=QString("获得连接:%1 获得地址:%2").arg(tcpsocket->peerName()).arg(tcpsocket->peerAddress().toString());
ui->label->setText(str);
connect(tcpsocket,&QTcpSocket::readyRead,
[=]()
{
string=tcpsocket->readAll().data();
ui->label->setText(string);
对接收的数据进行处理,文件保存(实际应该用数据库,测试就无所谓啦)
QFile file_out(".\\ku.txt");
if(file_out.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Append))
{
QTextStream textout(&file_out);
textout<<string<<endl;
}
file_out.close();
将获得的数据显示出来,我使用的Qtableview简单显示
qstr_list<<string;
model->setItem(timer,0,new QStandardItem(string.mid(0,string.indexOf("&"))));
model->item(timer,0)->setForeground(QBrush(QColor(255,0,0)));
//设置字符居中
model->item(timer,0)->setTextAlignment(Qt::AlignCenter);
model->setItem(timer++,1,new QStandardItem(string.mid(string.indexOf("&"))));
ui->label->setText("离线阶段完成");
}
效果图
下篇中完成指纹的使用