我正在努力了解CLBeacons的工作原理。我之前曾与CBPeripherals合作过,这实际上是BLE设备的核心蓝牙框架实现。
我所做的是以下步骤:
没有信标出现。
令人惊讶的是,当我使用[NSUUID alloc] initWithUUIDString:@" E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"]作为uuid(我从AirLocate项目中收集)时,会出现多个信标。 / p>
根据我读过的文档,邻近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&#34; TiBLocateViewController.h&#34; @import CoreLocation;
@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
答案 0 :(得分:1)
尽管iBeacons使用Bluetooth Low Energy,但它们并未与iOS中的Core-Bluetooth库一起使用。它们通过Core Location处理。
信标区域是根据三个参数定义的 - UUID,主要和次要。
iBeacon UUID与蓝牙MAC地址不同 - 它更像是&#34;供应商ID&#34;。给定供应商或所有者的所有信标都将具有相同的UUID - 例如Acme Dept商店将为自己分配一个UUID并将其分配给所有信标,而Big Bank Corp将分配一个不同的信标并将其分配给他们。然后,他们可以使用主要和次要来指示不同的位置。例如,百货商店可能有主要=商店编号和次要=部门编号(鞋子= 1,食物= 2等等)。银行专业可能是分支机构,辅修专业可能是分支机构(1 =出纳员,2 = ATM,3 =后台)。
还有一些&#34;众所周知的&#34;正在使用的UUID - 例如,您找到了AirLocate。 Estimote也有一个默认情况下他们的信标附带。
如果要扫描信标区域,则必须至少指定UUID。您还可以选择指定主要和次要。当检测到与您正在扫描的信标区域匹配的信标时,您将收到通知(取决于您已激活的模式,输入/退出区域或didRangeBeacon)。
某些信标可能另外实现BLE外围服务和特性以设置其参数(UUID,主要,次要,传输级别),但这不是iBeacon规范的一部分,因此不同的供应商将有不同的方法来执行此操作。要使用这些设置,您可以使用Core-Bluetooth。
因此,总而言之,如果您只是处理iBeacon方面的事情,那么您不需要对Core-Bluetooth做任何事情。您只需要Core-Location。