蓝牙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("离线阶段完成");
                }

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


下篇中完成指纹的使用

  • 11
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 蓝牙(RSSI)室内定位是一种基于蓝牙信号强度(RSSI)和距离的室内定位技术,可以在室内环境中实现精确的位置跟踪服务。目前,Android平台提供了许多用于蓝牙定位的API和工具,开发人员可以使用这些工具来实现室内定位功能。 在实现蓝牙(RSSI)室内定位之前,需要先进行站点调查和信号质量测试。站点调查可以用于确定信标放置的位置、数量和信号范围等因素。信号质量测试可以确定信标的信号强度和覆盖范围,以便更好的设计和优化蓝牙定位系统。 在Android平台中,可以使用BluetoothAdapter API来扫描周围的蓝牙设备,获取设备的RSSI值和MAC地址等信息。一旦获取了RSSI值,就可以通过算计算出设备与信标之间的距离和位置信息,并将其显示在用户界面上。具体的算可以使用基于信号强度指数的方,例如Path Loss和Trilateration的方进行定位计算。 需要注意的是,蓝牙(RSSI)室内定位技术也存在一些挑战和限制。例如,信号强度受环境因素的影响,如环境噪声和干扰等,这可能会导致定位精度不是特别高。此外,室内定位需要多个信标进行多点定位,成本也会相应增加。 总之,在Android开发中,使用蓝牙(RSSI)室内定位技术可以实现室内定位和位置跟踪功能,为商业和社会提供更多可能性。 ### 回答2: 在Android开发中,可以通过蓝牙RSSI(接收信号强度指数)数据实现室内定位RSSI是指接收到的信号强度,通过测量不同位置的RSSI值,就能够确定设备的位置。 首先需要获取设备的蓝牙信号强度值,这可以通过蓝牙扫描获取。然后建立一个基站位置数据库,将不同位置的蓝牙信号强度值记录下来。当需要定位时,就可以通过比对当前设备的蓝牙信号强度值和基站位置数据库中的信号强度值,来确定设备所处的位置。 室内定位的精度受到多种因素影响,比如墙体厚度、金属物体等会影响信号强度。因此在开发中需要进行精细的调试和优化。同时,蓝牙定位也有一些局限性,如需要用户开启蓝牙蓝牙信号强度值容易受到干扰等。 总之,蓝牙RSSI室内定位是一种比较成熟的技术,在Android开发中也有较多的应用场景,但仍需要开发者进行精细的调试和优化,来提高室内定位的精度和性能。 ### 回答3: 蓝牙RSSI室内定位,是指通过蓝牙信号强度指示(RSSI)来确定物体或设备在室内的具体位置。这种方适用于室内定位、追踪和导航等场景,但是有其限制:比如,受到干扰等外部环境因素的影响,精准度往往难以达到预期。 对于Android开发来说,实现蓝牙RSSI室内定位需要使用蓝牙模块,并结合相关的定位,如三角定位指纹定位等。一般步骤如下: 1.获取蓝牙设备的RSSI值。通过将扫描到的蓝牙设备进行连接,获取其信号强度值。 2.建立基站地图。在室内设定多个基站,获取它们的位置信息,并记录其强度值。 3.计算物体位置。结合已知的基站位置和它们的强度值,使用相关算计算物体位置及其误差范围。 4.优化算。如增加基站数量、调整基站位置等,提升室内定位精确度。 Android开发中,需要使用一些相关技术包和类库,如蓝牙适配器、手动操作权限等,较为复杂。值得注意的是,该技术需要有精确的物理地图、较多的基站数量以及较强的数据处理能力,因此在应用中的实际场景时需要谨慎考虑。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工农村贴膜小哥

我倒是要看看是那个憨憨在给我打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值