蓝牙RSSI定位入门到精通(3)-指纹法实现

下篇文章蓝牙RSSI定位入门到精通(4)-指纹法实现
https://blog.csdn.net/qq_35651984/article/details/82764334

实现步骤

  1. 指纹的采集(离线阶段)
  2. 指纹的处理(数据存储)
  3. 指纹的使用(在线阶段)

指纹的采集

采集概述

指纹采集,其实是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("离线阶段完成");
                }

效果图
在这里插入图片描述


下篇中完成指纹的使用

猜你喜欢

转载自blog.csdn.net/qq_35651984/article/details/82763636