【发布时间】:2014-05-29 10:31:46
【问题描述】:
我正在尝试了解 CLBeacons 的工作原理。我之前使用过 CBPeripherals,它实际上是 BLE 设备的核心蓝牙框架实现。
我做了以下步骤:
- 使用 CBPeripheralManager 检测我周围的信标,(以获取每个信标的单独标识符)。
- 使用了要在 UITableView 上显示的数据
- 在选择 Tableview 时,我将 CBPeripheral 对象本身传递给另一个我有 CLLocationManager 的类。在这里,我使用 CBPeripheral 对象的邻近 UUID 和该区域中的 startToRangeBeacons 定义 CLBeaconRegion。
没有出现任何信标。
令人惊讶的是,当我使用 [NSUUID alloc] initWithUUIDString:@"E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"] 作为 uuid(我从 AirLocate 项目中收集)时,出现了多个信标。
根据我阅读的文档,邻近 UUID 是信标的标识符。那么为什么我使用传递的标识符时它不起作用,为什么我使用定义的标识符时它起作用?
代码---- 1.第一屏
#import "TiBViewController.h"
#import "DEASensorTag.h"
#import "TiBScanTableViewCell.h"
#import "TiBLocateViewController.h"
@interface TiBViewController ()
@property (nonatomic,strong) NSTimer *timer_check;
@end
@implementation TiBViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
[self performSelector:@selector(initialise) withObject:self afterDelay:2.0];
}
-(void)initialise
{
DEACentralManager *centralManager = [DEACentralManager initSharedServiceWithDelegate:self];
if (centralManager.isScanning == NO)
{
[centralManager startScan];
centralManager.isScanning=YES;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
if(self.timer_check==nil)
{
self.timer_check = [NSTimer timerWithTimeInterval:20
target:self
selector:@selector(timer_function)
userInfo:nil
repeats:YES];
NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer:self.timer_check forMode: NSDefaultRunLoopMode];
}
[self.timer_check fire];
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state)
{
case CBCentralManagerStatePoweredOn:
break;
case CBCentralManagerStatePoweredOff:
break;
case CBCentralManagerStateUnsupported:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"Device is Supported"
delegate:nil
cancelButtonTitle:@"Dismiss"
otherButtonTitles:nil];
[alert show];
break;
}
case CBCentralManagerStateResetting:
{
break;
}
case CBCentralManagerStateUnauthorized:
break;
case CBCentralManagerStateUnknown:
break;
default:
break;
}
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
DEACentralManager *centralManager = [DEACentralManager sharedService];
YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];
yp.delegate = self;
[yp readRSSI];
for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
{
if (cell.yperipheral == yp)
{
[cell updateDisplay];
break;
}
}
}
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
{
[cell updateDisplay];
}
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
DEACentralManager *centralManager = [DEACentralManager sharedService];
YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];
if (yp.isRenderedInViewCell == NO)
{
yp.isRenderedInViewCell = YES;
[self.peripheralsTableView reloadData];
}
if (centralManager.isScanning)
{
// if(advertisementData!=nil)
// {
// NSLog(@" ad is %@",advertisementData);
// }
for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
{
if (cell.yperipheral.cbPeripheral == peripheral)
{
if (peripheral.state == CBPeripheralStateDisconnected)
{
cell.rssiLabel.text = [NSString stringWithFormat:@"%ld dB", (long)[RSSI integerValue]];
cell.distanceLabel.text = [NSString stringWithFormat:@" distance : %0.3fm",[self calculateAccuracyWithRSSI:[RSSI doubleValue]]];
}
else
{
continue;
}
}
}
}
}
- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals {
DEACentralManager *centralManager = [DEACentralManager sharedService];
for (CBPeripheral *peripheral in peripherals)
{
YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];
if (yp)
{
yp.delegate = self;
}
}
[self.peripheralsTableView reloadData];
}
- (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals
{
DEACentralManager *centralManager = [DEACentralManager sharedService];
for (CBPeripheral *peripheral in peripherals)
{
YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];
if (yp)
{
yp.delegate = self;
}
}
[self.peripheralsTableView reloadData];
}
#pragma mark - CBPeripheralDelegate Methods
- (void)performUpdateRSSI:(NSArray *)args
{
CBPeripheral *peripheral = args[0];
[peripheral readRSSI];
}
- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error {
if (error)
{
NSLog(@"ERROR: readRSSI failed, retrying. %@", error.description);
if (peripheral.state == CBPeripheralStateConnected)
{
NSArray *args = @[peripheral];
[self performSelector:@selector(performUpdateRSSI:) withObject:args afterDelay:2.0];
}
return;
}
[self placeRSSI:peripheral];
DEACentralManager *centralManager = [DEACentralManager sharedService];
YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];
NSArray *args = @[peripheral];
[self performSelector:@selector(performUpdateRSSI:) withObject:args afterDelay:yp.rssiPingPeriod];
}
-(void)placeRSSI:(CBPeripheral *)per
{
for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
{
if (cell.yperipheral)
{
if (cell.yperipheral.isConnected)
{
if (cell.yperipheral.cbPeripheral == per)
{
cell.rssiLabel.text = [NSString stringWithFormat:@"%@", per.RSSI];
cell.distanceLabel.text = [NSString stringWithFormat:@" distance : %0.3fm",[self calculateAccuracyWithRSSI:[per.RSSI doubleValue]]];
break;
}
}
}
}
}
#pragma mark UITableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
DEACentralManager *centralManager = [DEACentralManager sharedService];
return centralManager.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"ListCell";
DEACentralManager *centralManager = [DEACentralManager sharedService];
YMSCBPeripheral *yp = [centralManager peripheralAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
TiBScanTableViewCell *pcell = (TiBScanTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[pcell configureWithPeripheral:yp];
yp.isRenderedInViewCell = YES;
cell = pcell;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DEACentralManager *centralManager = [DEACentralManager sharedService];
YMSCBPeripheral *yp = [centralManager peripheralAtIndex:indexPath.row];
TiBLocateViewController *locate = [self.storyboard instantiateViewControllerWithIdentifier:@"Locate"];
locate.cbPeripheral=yp.cbPeripheral;
[self.navigationController pushViewController:locate animated:YES];
}
-(void)timer_function
{
DEACentralManager *centralManager = [DEACentralManager sharedService];
for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
{
NSIndexPath *indexPath = [self.peripheralsTableView indexPathForCell:cell];
YMSCBPeripheral *yp = [centralManager peripheralAtIndex:indexPath.row];
[centralManager removePeripheral:yp];
[self.peripheralsTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
-(void)viewWillDisappear:(BOOL)animated
{
[self.timer_check invalidate];
self.timer_check = nil;
[self timer_function];
DEACentralManager *centralManager = [DEACentralManager sharedService];
[centralManager stopScan];
[super viewWillDisappear:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (double)calculateAccuracyWithRSSI:(double)rssi
{
if (rssi == 0) {
return -1.0;
}
double txPower = -70;
double ratio = rssi*1.0/txPower;
if (ratio < 1.0) {
return pow(ratio,10);
}
else {
double accuracy = (0.89976) * pow(ratio,7.7095) + 0.111;
return accuracy;
}
}
@end
-
第二个屏幕
#import "TiBLocateViewController.h" @import 核心位置;
@interface TiBLocateViewController ()<CLLocationManagerDelegate> @property (strong,nonatomic) CLLocationManager *locateManager; @end @implementation TiBLocateViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.locateManager = [[CLLocationManager alloc]init]; self.locateManager.delegate=self; self.locateManager.desiredAccuracy = kCLLocationAccuracyBest; } -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:YES]; } -(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized) { NSUUID *per_uuid = self.cbPeripheral.identifier; CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:per_uuid identifier:[[NSBundle mainBundle] bundleIdentifier]]; beaconRegion.notifyOnExit=YES; beaconRegion.notifyOnEntry=YES; beaconRegion.notifyEntryStateOnDisplay=YES; [manager startMonitoringForRegion:beaconRegion]; [manager startRangingBeaconsInRegion:beaconRegion]; } } -(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { if ([region isKindOfClass:[CLBeaconRegion class]]) { [manager startRangingBeaconsInRegion:(CLBeaconRegion *)region]; } } - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { if ([region isKindOfClass:[CLBeaconRegion class]]) { [manager startRangingBeaconsInRegion:(CLBeaconRegion *)region]; } } -(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region { for (CLBeacon *beacon in beacons) { NSLog(@" beacon %@",beacon); } } -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog(@" error is %@",error.localizedDescription); } - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { if ([region isKindOfClass:[CLBeaconRegion class]]) { [manager stopRangingBeaconsInRegion:(CLBeaconRegion *)region]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } -(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:YES]; [self.locateManager stopMonitoringSignificantLocationChanges]; } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end
【问题讨论】:
-
我试图实现的基本问题是定位 CBperipheral。由于 CB 以外围设备结尾,我想在 CLBeacons 中尝试
-
你从 CB 获取 uuid 并从 CL 开始测距 .. 听起来不错
-
用代码编辑过的帖子
-
didChangeAuthorizationStatus 在状态没有改变时不会被调用......如果是......它不应该是:D 不要依赖它
-
我一开始在 ViewDidAppear 块上遇到了同样的问题,所以我想把它移到其他地方;什么也没发生.....:(
标签: ios objective-c core-location core-bluetooth ibeacon