iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >如何搭建一个蓝牙定位系统
  • 841
分享到

如何搭建一个蓝牙定位系统

蓝牙定位系统 2023-05-31 10:05:09 841人浏览 独家记忆
摘要

本篇文章给大家分享的是有关如何搭建一个蓝牙定位系统,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1、准备设备所需硬件设备:(1)低功率蓝牙定位器若干(如:10个),网上有卖(单

本篇文章给大家分享的是有关如何搭建一个蓝牙定位系统,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

1、准备设备

所需硬件设备:

(1)低功率蓝牙定位器若干(如:10个),网上有卖(单价从几十到几百都有)

(2)Android设备一台,系统版本4.2以上(SDK版本大于17)

(3)iOS设备一台,支持蓝牙4.0 BLE

2、设置蓝牙定位器

移动设备扫描周边低功率蓝牙设备,可以获得蓝牙设备对应的Proximity UUID、Major、Minor等属性信息。而刚采购来的蓝牙设备属性可能都相同,互相区别不开,所以我们需要设置每台设备的属性。

设备厂商都会提供相关手机应用,共用户设置属性信息。给蓝牙设备装上电池,打开手机应用,靠近蓝牙设备就能发现,然后就可以设置其属性值了,其中:

UUID是一个32位的16进制数,表示设备厂商,该字段可以沿用出厂设置

Major表示不同区域(比如:某一楼层、某一地区),取值范围0到6万多

Minor表示不同的设备,取值范围0到6万多

样例:UUID = e2c56db5-dffb-48d2-b060-d0f5a71096e0, Major = 1001, Minor = 10001

每台设备设置完属性后准备一个标签,填上属性信息,贴到设备上,方便以后部署。

3、部署蓝牙设备

首先,准备目标场地地图数据,可以是基于经纬度坐标,也可以是简单图片坐标,看具体使用情况。

接下来,将蓝牙设备挨个部署到场地指定位置上,顺便记录每个设备地理坐标或图片坐标。

最后,得到一张表格信息,记录着每台蓝牙设备属性和位置信息。这张表就是整个定位系统的指纹库,为定位算法使用。

UUIDMajorMinorLatLon
e2c56db5-dffb-48d2-b060-d0f5a71096e010011000139.45678116.23456
e2c56db5-dffb-48d2-b060-d0f5a71096e010011000239.45674116.23476
...............

固定蓝牙设备到场地指定位置比较容易,不过记录设备坐标信息可能复杂一点,需要在地图或图片上获得相应位置点。可以开发一个App从而快速准确地记录位置信息,顺便将相关信息录入指纹库(数据库,比如:sqlite)。

部署蓝牙设备还有一个关注点就是部署间隔。低功率蓝牙设备容易受场地、环境影响,比较不稳定,所以根据场地条件每隔几米或十几米部署一台蓝牙设备。间隔太大会影响定位精度,不过太密也是资源浪费,不是越密集定位精度越高。

4、客户端App开发

客户端app主要功能就是扫描周围蓝牙设备,将设备列表信息上传定位服务器,从而获得定位效果,并展现给终端用户。

4.1 Android应用开发

工程所需SDK版本大于17。

1. App所需权限(AndroidManifest.xml文件)

<uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

2. 创建beacon数据项类

public class IBeaconRecord {public String address;// 设备地址(Mac)public String uuid;// Proximity UUIDpublic int major;// Majorpublic int minor;// Minorpublic int rssi;// 场强}

其中,address属性可以不要,因为iOS设备获取不到该属性!

3. 创建扫描工具

import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.example.vo.IBeaconRecord;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothManager;import android.content.Context;import android.os.Build;import android.os.Handler;public class BLEPositioning {private Context m_ctx;private Handler handler;private BluetoothManager bluetoothManager;private BluetoothAdapter mBluetoothAdapter;// 存储蓝牙扫描结果,key - name_address, value - List<IBeaconRecord>private Map<String, List<IBeaconRecord>> mapBltScanResult;public BLEPositioning(Context ctx) {super();this.m_ctx = ctx;initParam();}private void initParam() {handler = new Handler();mapBltScanResult = new HashMap<String, List<IBeaconRecord>>();// 设备SDK版本大于17(Build.VERSION_CODES.JELLY_BEAN_MR1)才支持BLE 4.0if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {bluetoothManager = (BluetoothManager) this.m_ctx.getSystemService(Context.BLUETOOTH_SERVICE);mBluetoothAdapter = bluetoothManager.getAdapter();}}public void startScan(){mapBltScanResult.clear();if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {// 5秒后停止扫描,毕竟扫描蓝牙设备比较费电,根据定位及时性自行调整该值handler.postDelayed(new Runnable() {@Overridepublic void run() {mBluetoothAdapter.stopLeScan(bltScanCallback);}}, 5 * 1000);mBluetoothAdapter.startLeScan(bltScanCallback);// 开始扫描}}public void requestServer(){// TODO // 利用mapBltScanResult(蓝牙扫描结果)请求定位服务或本地计算定位}private BluetoothAdapter.LeScanCallback bltScanCallback = new BluetoothAdapter.LeScanCallback() {@Overridepublic void onLeScan(final BluetoothDevice device, int rssi,byte[] scanRecord) {IBeaconRecord record = new IBeaconRecord();if (fromScanData(scanRecord, record)) {String address = device.getAddress();// 获取Mac地址String name = device.getName();// 获取设备名称String key = name + "_" + address;record.address = address;// Mac地址record.rssi = rssi;// 场强if (mapBltScanResult.containsKey(key)) {mapBltScanResult.get(key).add(record);} else {ArrayList<IBeaconRecord> list = new ArrayList<IBeaconRecord>();list.add(record);mapBltScanResult.put(key, list);}}}};private boolean fromScanData(byte[] scanData, IBeaconRecord record) {int startByte = 2;boolean patternFound = false;while (startByte <= 5) {if (((int) scanData[startByte + 2] & 0xff) == 0x02&& ((int) scanData[startByte + 3] & 0xff) == 0x15) {// yes! This is an iBeaconpatternFound = true;break;} else if (((int) scanData[startByte] & 0xff) == 0x2d&& ((int) scanData[startByte + 1] & 0xff) == 0x24&& ((int) scanData[startByte + 2] & 0xff) == 0xbf&& ((int) scanData[startByte + 3] & 0xff) == 0x16) {return false;} else if (((int) scanData[startByte] & 0xff) == 0xad&& ((int) scanData[startByte + 1] & 0xff) == 0x77&& ((int) scanData[startByte + 2] & 0xff) == 0x00&& ((int) scanData[startByte + 3] & 0xff) == 0xc6) {return false;}startByte++;}if (patternFound == false) {// This is not an iBeaconreturn false;}// 获得Major属性record.major = (scanData[startByte + 20] & 0xff) * 0x100+ (scanData[startByte + 21] & 0xff);// 获得Minor属性record.minor = (scanData[startByte + 22] & 0xff) * 0x100+ (scanData[startByte + 23] & 0xff);// record.tx_power = (int) scanData[startByte + 24]; // this one is// signed// record.accuracy = calculateAccuracy(record.tx_power, record.rssi);// if (record.accuracy < 0) {// return false;// }try {byte[] proximityUuidBytes = new byte[16];System.arraycopy(scanData, startByte + 4, proximityUuidBytes, 0, 16);String hexString = bytesToHex(proximityUuidBytes);StringBuilder sb = new StringBuilder();sb.append(hexString.substring(0, 8));sb.append("-");sb.append(hexString.substring(8, 12));sb.append("-");sb.append(hexString.substring(12, 16));sb.append("-");sb.append(hexString.substring(16, 20));sb.append("-");sb.append(hexString.substring(20, 32));// beacon.put("proximity_uuid", sb.toString());// 获得UUID属性record.uuid = sb.toString();} catch (Exception e) {e.printStackTrace();}return true;}private char[] hexArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8','9', 'a', 'b', 'c', 'd', 'e', 'f' };private String bytesToHex(byte[] bytes) {char[] hexChars = new char[bytes.length * 2];int v;for (int j = 0; j < bytes.length; j++) {v = bytes[j] & 0xFF;hexChars[j * 2] = hexArray[v >>> 4];hexChars[j * 2 + 1] = hexArray[v & 0x0F];}return new String(hexChars);}}

扫描结果放在mapBltScanResult里,该HashMap的key由设备Mac地址和名称组成(address_name),value是个ArrayList,记录着该蓝牙设备多次扫描得到的信息(IBeaconRecord)序列,请求定位服务或本地计算定位之前,这些序列要进行平均处理(其实只是平均rssi值)。经过RSSI值多次平均处理后,一定程度上减小蓝牙设备不稳定因素。

关于请求定位服务,展现定位效果,还有定位算法都不是本文重点!关于蓝牙定位算法也可以参考其他文献资料!

4.2 iOS应用开发

iOS部分参考了AirLocate源码(苹果官方蓝牙样例工程)。

1. 引用基础配置类“APLDefaults”(来自AirLocate)

APLDefaults.h文件

extern NSString *BeaconIdentifier;@interface APLDefaults : NSObject+ (APLDefaults *)sharedDefaults;@property (nonatomic, copy, readonly) NSArray *supportedProximityUUIDs;@property (nonatomic, copy, readonly) NSUUID *defaultProximityUUID;@property (nonatomic, copy, readonly) NSNumber *defaultPower;@end

APLDefaults.m文件

#import "APLDefaults.h"NSString *BeaconIdentifier = @"com.example.apple-samplecode.AirLocate";@implementation APLDefaults- (id)init{  self = [super init];  if(self)  {    // uuidgen should be used to generate UUIDs.    _supportedProximityUUIDs = @[[[NSUUID alloc] initWithUUIDString:@"E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"],                   [[NSUUID alloc] initWithUUIDString:@"5A4BCFCE-174E-4BAC-A814-092E77F6B7E5"],                   [[NSUUID alloc] initWithUUIDString:@"74278BDA-B644-4520-8F0C-720EAF059935"]];    _defaultPower = @-59;  }    return self;}+ (APLDefaults *)sharedDefaults{  static id sharedDefaults = nil;  static dispatch_once_t onceToken;  dispatch_once(&onceToken, ^{    sharedDefaults = [[self alloc] init];  });    return sharedDefaults;}- (NSUUID *)defaultProximityUUID{  return _supportedProximityUUIDs[0];}@end

2.  定义变量

  // 存储扫描获得的蓝牙设备信息  // key - proximityUUID_Major_Minor  // value - NSArray (CLBeacon)  NSMutableDictionary *dicBeacons;    CLLocationManager *locationManager;  NSMutableDictionary *rangedRegions;   // 要扫描的region    NSTimer *timerPos; // 定时器,用于控制扫描时间长短

3. 初始化

  dicBeacons = [[NSMutableDictionary alloc] init];    locationManager = [[CLLocationManager alloc] init];  locationManager.delegate = self; // 当前类接收回调,从而获得蓝牙设备信息    // Populate the regions we will range once.  rangedRegions = [[NSMutableDictionary alloc] init];    for (NSUUID *uuid in [APLDefaults sharedDefaults].supportedProximityUUIDs)  {    CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:[uuid UUIDString]];    rangedRegions[region] = [NSArray array];  }

4. 开始扫描、停止扫描和请求定位服务

// 开始扫描蓝牙- (void)startScanning{  // 定时3.0秒后请求定位服务,时间间隔自行设置,只要有足够的扫描时间即可  timerPos = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(startPositioning) userInfo:nil repeats:NO];    [dicBeacons removeAllObjects];  // 开始扫描  for (CLBeaconRegion *region in rangedRegions)  {    [locationManager startRangingBeaconsInRegion:region];  }}// 停止扫描蓝牙- (void)stopScanning{  // 停止扫描  for (CLBeaconRegion *region in rangedRegions)  {    [locationManager stopRangingBeaconsInRegion:region];  }}// 请求定位服务- (void)startPositioning{  [self stopScanning];  // 停止扫描    // 以下根据扫描结果dicBeacons来请求定位服务  //}

其中,请求定位服务部分每个人都不一样,依赖自身定位服务。

5. 监听回调,解析扫描获得的蓝牙设备信息,存入dicBeacons变量

#pragma mark - Location manager delegate- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region{    for (NSNumber *range in @[@(CLProximityUnknown), @(CLProximityImmediate), @(CLProximityNear), @(CLProximityFar)])  {    NSArray *proximityBeacons = [beacons filteredArrayUsingPredicate:[NSPredicate predicateWithFORMat:@"proximity = %d", [range intValue]]];        for (int i = 0; i < [proximityBeacons count]; i++) {      CLBeacon *beacon = [proximityBeacons objectAtIndex:i];      // 场强过滤,RSSI值要在-90到0之间      if (beacon.rssi < 0 && beacon.rssi > -90) {        NSString *strKey = [NSString stringWithFormat:@"%@_%@_%@",[beacon.proximityUUID UUIDString], beacon.major, beacon.minor];        if ([dicBeacons objectForKey:strKey]) {          [[dicBeacons objectForKey:strKey] addObject:beacon];        } else {          NSMutableArray *arrBeacons = [[NSMutableArray alloc] init];          [arrBeacons addObject:beacon];          [dicBeacons setObject:arrBeacons forKey:strKey];        }      }    }  }}

5. 定位服务开发

部署蓝牙设备时组建了最原始的蓝牙指纹库(数据表),利用这张表可以开发一套定位服务。

客户端上传过来的是一组蓝牙设备信息列表,例如:

{  "ble_arr” =   (        {      major = 1001;      minor = 10006;      rssi = "-65";      uuid = " E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";    },        {      major = 1001;      minor = 10002;      rssi = "-72";      uuid = " E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";    },        {      major = 1001;      minor = 10005;      rssi = "-49";      uuid = " E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";    },        {      major = 1001;      minor = 10008;      rssi = "-74";      uuid = " E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";    },        {      major = 1001;      minor = 10001;      rssi = "-65";      uuid = " E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";    },        {      major = 1001;      minor = 10004;      rssi = "-76";      uuid = " E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";    },        {      major = 1001;      minor = 10007;      rssi = "-66";      uuid = " E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";    },        {      major = 1001;      minor = 17010;      rssi = "-67";      uuid = " E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";    }  );}

以上就是如何搭建一个蓝牙定位系统,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程网精选频道。

--结束END--

本文标题: 如何搭建一个蓝牙定位系统

本文链接: https://www.lsjlt.com/news/224768.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何搭建一个蓝牙定位系统
    本篇文章给大家分享的是有关如何搭建一个蓝牙定位系统,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1、准备设备所需硬件设备:(1)低功率蓝牙定位器若干(如:10个),网上有卖(单...
    99+
    2023-05-31
    蓝牙定位系统
  • win10系统蓝牙驱动如何更新
    这篇文章主要介绍“win10系统蓝牙驱动如何更新”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“win10系统蓝牙驱动如何更新”文章能帮助大家解决问题。蓝牙驱动更新的方法:方法一: 我们可以先下载一个...
    99+
    2023-06-30
  • win10系统笔记本蓝牙如何打开
    本文小编为大家详细介绍“win10系统笔记本蓝牙如何打开”,内容详细,步骤清晰,细节处理妥当,希望这篇“win10系统笔记本蓝牙如何打开”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识...
    99+
    2023-01-29
    win10
  • win10系统缺少蓝牙驱动程序如何解决
    要解决Win10系统缺少蓝牙驱动程序的问题,可以按照以下步骤进行操作:1. 打开设备管理器。可以通过按Win + X键,在弹出的菜单...
    99+
    2023-09-18
    win10
  • Linux系统如何使用rfkill命令来管理蓝牙和wifi
    这篇文章主要介绍Linux系统如何使用rfkill命令来管理蓝牙和wifi,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!#列出所有可用设备rfkill list0: ideapad_wlan: Wireless LA...
    99+
    2023-06-28
  • 如何搭建一个vue3.0 项目
    这篇文章将为大家详细讲解有关如何搭建一个vue3.0 项目,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。vue是什么软件Vue是一套用于构建用户界面的渐进式JavaScript框架,Vue与...
    99+
    2023-06-06
  • 如何搭建一个AmazeUI框架
    如何搭建一个AmazeUI框架?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.获取Amaze UI  1下载文件首先打开百度输入:Amaze UI -...
    99+
    2023-06-09
  • 如何搭建一个SpringBoot项目
    这篇文章给大家分享的是有关如何搭建一个SpringBoot项目的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。零、环境介绍环境:jdk1.8及以上,maven,Win10,IDEA,网络一、手把手创建请求创建在启动...
    99+
    2023-06-25
  • 如何手工搭建一个Servlet
    本篇内容主要讲解“如何手工搭建一个Servlet”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何手工搭建一个Servlet”吧!目录前言手工搭建一个Servlet下载Tomcat编译程序启动T...
    99+
    2023-06-20
  • 如何搭建一个react项目
    小编给大家分享一下如何搭建一个react项目,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1、npm init 生成 packa...
    99+
    2024-04-02
  • Python如何搭建一个web app
    点击打开链接https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432170937506ecfb2f6adf8e47...
    99+
    2023-01-31
    Python web app
  • 如何搭建一个SSM空间
    这篇文章给大家介绍如何搭建一个SSM空间,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。第一章:搭建整合环境1. 搭建整合环境整合说明:SSM整合可以使用多种方式,咱们会选择XML + 注解的方式整合的思路2.1. 先搭...
    99+
    2023-06-14
  • Java如何搭建一个个人网盘
    目录前言一、项目介绍二、网盘搭建2.1 Windows 环境运行2.2 Linux 环境运行三、开发环境运行3.1 下载项目3.2 运行3.3 阅读代码四、功能说明4.1 上传4.2...
    99+
    2024-04-02
  • linux如何创建一个swap文件系统
    ...
    99+
    2024-04-02
  • win10系统如何调出蓝色选定框
    这篇文章主要介绍“win10系统如何调出蓝色选定框”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“win10系统如何调出蓝色选定框”文章能帮助大家解决问题。打开设备,右键单击“此电脑”,选择属性; 然...
    99+
    2023-07-01
  • linux如何创建一个 FAT32 文件系统
    ...
    99+
    2024-04-02
  • 如何使用博客系统搭建个人网站
    如何使用博客系统搭建个人网站,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。博客,又译为网络日志、部落格或部落阁等,是一种通常由个人管理、不定期张贴新的文章的网站。博客上的文章通...
    99+
    2023-06-12
  • 如何搭建FireKylin博客系统
    这篇文章主要为大家展示了“如何搭建FireKylin博客系统”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何搭建FireKylin博客系统”这篇文章吧。FireKylin 是基于国内先进的No...
    99+
    2023-06-27
  • 如何搭建Wordpress博客系统
    小编给大家分享一下如何搭建Wordpress博客系统,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!安装SequoiaDB本文使用...
    99+
    2024-04-02
  • 如何搭建一个云服务器
    搭建一个云服务器需要遵循一定的技术和配置要求,下面是一些基本步骤: 云服务器的硬件选择:选择性能强劲的服务器主板,内存大小,以及存储设备等,这些都是云服务器所需要的关键组件。 服务器硬件配置:根据您的需求和预算,选择合适的硬件配置,例如...
    99+
    2023-10-26
    服务器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作