Wednesday, 15 May 2013

iphone - How to detect nearby devices with Bluetooth LE in iOS 7.1 both in background and foreground? -



iphone - How to detect nearby devices with Bluetooth LE in iOS 7.1 both in background and foreground? -

i have app needs observe nearby (in range bluetooth le) devices running same application , ios 7.1. i've considered 2 alternatives detection:

having devices deed ibeacons , observe ibeacons in range using corebluetooth (like in vicinity implementation here) create ble peripheral, advertise , scan peripherals

it seems alternative 1 out of question because:

it may take @ to the lowest degree 15 minutes ios observe entering beacon part when application running background (ios 7.1)

option 2 seems way go, there difficulties regarding implementation:

ios seems alter peripheral uuid in advertisement packets after period of time (around 15 minutes?). means it's not straight possible identify advertising device advertisement broadcast signal.

regarding this, have next questions:

are there other methods of implementing nearby device detection haven't considered? is possible identify device through advertising (or other means) alternative 2 work?

i found way create work core bluetooth (option 2), procedure following:

the application advertises itself encoded device unique identifier in cbadvertisementdatalocalnamekey (when broadcasting application runs foreground) , characteristic provides device unique identifier through bluetooth le service (when broadcasting application runs background) at same time, application scans other peripherals same service.

the advertising works follows:

for other devices able identify device, utilize per-device unique uuid (i'm using urban airship's [uautils deviceid], because it's device identifier in other parts of program, - might utilize unique id implementation).

when application running foreground, can pass device unique id directly in advertisement packet using cbadvertisementdatalocalnamekey. standard uuid representation long, utilize shortened form of uuid follows:

+ (nsstring *)shorteneddeviceid { nsstring *deviceid = [uautils deviceid]; nsuuid *uuid = [[nsuuid alloc] initwithuuidstring:deviceid]; uuid_t uuidbytes; [uuid getuuidbytes:uuidbytes]; nsdata *data = [nsdata datawithbytes:uuidbytes length:16]; nsstring *base64 = [data base64encodedstringwithoptions:0]; nsstring *encoded = [[[base64 stringbyreplacingoccurrencesofstring:@"/" withstring:@"_"] stringbyreplacingoccurrencesofstring:@"+" withstring:@"-"] stringbyreplacingoccurrencesofstring:@"=" withstring:@""]; homecoming encoded; }

when application running background, advertisement packet gets stripped , cbadvertisementdatalocalnamekey not passed along anymore. this, application needs publish characteristic provides unique device identifier:

- (void)peripheralmanagerdidupdatestate:(cbperipheralmanager *)peripheral { if (peripheral.state == cbperipheralmanagerstatepoweredon) { [self startadvertising]; if (peripheralmanager) { cbuuid *serviceuuid = [cbuuid uuidwithstring:device_identifier_service_uuid]; cbuuid *characteristicuuid = [cbuuid uuidwithstring:device_identifier_characteristic_uuid]; cbmutablecharacteristic *characteristic = [[cbmutablecharacteristic alloc] initwithtype:characteristicuuid properties:cbcharacteristicpropertyread value:[[myutils shorteneddeviceid] datausingencoding:nsutf8stringencoding] permissions:cbattributepermissionsreadable]; cbmutableservice *service = [[cbmutableservice alloc] initwithtype:serviceuuid primary:yes]; service.characteristics = @[characteristic]; [peripheralmanager addservice:service]; } } }

the scanning works follows:

you start scan peripherals service uuid follows (notice need specify service uuid, because otherwise background scan fails find device):

[self.centralmanager scanforperipheralswithservices:@[[cbuuid uuidwithstring:device_identifier_service_uuid]] options:scanoptions];

when device discovered @ - (void)centralmanager:(cbcentralmanager *)central diddiscoverperipheral:(cbperipheral *)peripheral advertisementdata:(nsdictionary *)advertisementdata rssi:(nsnumber *)rssi check if advertisementdata[cbadvertisementdatalocalnamekey] exists , seek convert uuid form this:

+ (nsstring *)deviceidfromshorteneddeviceid:(nsstring *)shorteneddeviceid { if (!shorteneddeviceid) homecoming nil; nsstring *decoded = [[[shorteneddeviceid stringbyreplacingoccurrencesofstring:@"_" withstring:@"/"] stringbyreplacingoccurrencesofstring:@"-" withstring:@"+"] stringbyappendingstring:@"=="]; nsdata *data = [[nsdata alloc] initwithbase64encodedstring:decoded options:0]; if (!data) homecoming nil; nsuuid *uuid = [[nsuuid alloc] initwithuuidbytes:[data bytes]]; homecoming uuid.uuidstring; }

if conversion fails know broadcasting device in background, , need connect device read characteristic provides unique identifier. need utilize [self.central connectperipheral:peripheral options:nil]; (with peripheral.delegate = self; , implement chain of delegate methods follows:

- (void)centralmanager:(cbcentralmanager *)central didconnectperipheral:(cbperipheral *)peripheral { [peripheral discoverservices:@[[cbuuid uuidwithstring:device_identifier_service_uuid]]]; } - (void)peripheral:(cbperipheral *)peripheral diddiscoverservices:(nserror *)error { if (!error) { (cbservice *service in peripheral.services) { if ([service.uuid.uuidstring isequaltostring:device_identifier_service_uuid]) { nslog(@"service found uuid: %@", service.uuid); [peripheral discovercharacteristics:@[[cbuuid uuidwithstring:device_identifier_characteristic_uuid]] forservice:service]; } } } } - (void)peripheral:(cbperipheral *)peripheral diddiscovercharacteristicsforservice:(cbservice *)service error:(nserror *)error { if (!error) { (cbcharacteristic *characteristic in service.characteristics) { if ([characteristic.uuid isequal:[cbuuid uuidwithstring:device_identifier_characteristic_uuid]]) { [peripheral readvalueforcharacteristic:characteristic]; } } } } - (void)peripheral:(cbperipheral *)peripheral didupdatevalueforcharacteristic:(cbcharacteristic *)characteristic error:(nserror *)error { if (!error) { nsstring *shorteneddeviceid = [[nsstring alloc] initwithdata:characteristic.value encoding:nsutf8stringencoding]; nsstring *deviceid = [myutils deviceidfromshorteneddeviceid:shorteneddeviceid]; nslog(@"got device id: %@", deviceid); } }

ios iphone bluetooth bluetooth-lowenergy core-bluetooth

No comments:

Post a Comment