2012-10-24 17 views
16

Come sappiamo, iOS 6 supporta i dispositivi in ​​esecuzione (iPhone 4s e versioni successive e il nuovo iPad) come periferiche BLE. C'è una demo in WWDC 2012 Session 705 chiamata "core Bluetooth avanzato". Ho chiesto il codice sorgente di Apple. Mi hanno inviato una versione modificata del codice sorgente (BTLE_Transfer_Draft). Poi ho:Esegui dispositivo iOS 6 come periferica BLE

  • eseguire l'applicazione in iPhone 5 (iOS 6) in "modalità Peripheral" e iniziare a "Pubblicità"
  • Esegui l'applicazione nel nuovo iPad (iOS 5.1.1) in "modalità centrale"

Il problema è che la periferica non è mai stata scoperta. Quindi uso altre applicazioni di test, incluse alcune scaricate da App Store. Tutti non sono riusciti a scoprire le periferiche. Penso che il problema dovrebbe essere in BTLE_Transfer_Draft. Perché non sono sicuro di poter presentare l'intero codice sorgente. Così ho solo mostrare la parte "modalità di periferica" ​​qui:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // Start up the CBPeripheralManager 
    _peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil]; 
} 

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral { 
    // Opt out from any other state 
    if (peripheral.state != CBPeripheralManagerStatePoweredOn) { 
     return; 
    } 

    // We're in CBPeripheralManagerStatePoweredOn state... 
    NSLog(@"self.peripheralManager powered on."); 

    // ... so build our service. 

    // Start with the CBMutableCharacteristic 
    self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID] 
                    properties:CBCharacteristicPropertyNotify 
                     value:nil 
                   permissions:CBAttributePermissionsReadable]; 

    // Then the service 
    CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID] 
                    primary:YES]; 

    // Add the characteristic to the service 
    transferService.characteristics = @[self.transferCharacteristic]; 

    // And add it to the peripheral manager 
    [self.peripheralManager addService:transferService]; 
} 

/** Start advertising 
*/ 
- (IBAction)switchChanged:(id)sender 
{ 
    if (self.advertisingSwitch.on) { 
     // All we advertise is our service's UUID 
     [self.peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] }]; 
    } 
    else { 
     [self.peripheralManager stopAdvertising]; 
    } 
} 

Il BLE è alimentato dallo stato e la startAdvertising si chiama. Ma il centro BLE non potrà mai scoprirlo.

Post aggiornato:

Secondo mttrb 's suggerimento che ho aggiunto "CBAdvertisementDataLocalNameKey" quando startAdvertising. Ma il mio servizio non è ancora stato scoperto dalla maggior parte delle app, incluse alcune app da App Store. L'unica app in grado di scoprire il mio servizio è un'app dall'app store denominata "scanner BLE".

La mia domanda è: questo significa che la mia applicazione funziona come periferica? Ma perché il mio codice non può scoprire il servizio? Come faccio a debuggarlo?

Il mio codice in modalità centrale è come questo:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // Start up the CBCentralManager 
    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; 
} 

- (void)centralManagerDidUpdateState:(CBCentralManager *)central 
{ 
    if (central.state != CBCentralManagerStatePoweredOn) { 
     return; 
    } 
    [self.centralManager scanForPeripheralsWithServices:nil options:nil]; 
} 

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI 
{ 
...... 
} 

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error 
{ 
    if (error) { 
     NSLog(@"Error discovering services: %@", [error localizedDescription]); 
     return; 
    } 
} 

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error 
{ 
    // Deal with errors (if any) 
    if (error) { 
     NSLog(@"Error discovering characteristics: %@", [error localizedDescription]); 
     return; 
    } 
} 

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error 
{ 
    NSLog(@"Peripheral Disconnected"); 
    self.discoveredPeripheral = nil; 
} 

Il didDiscoverPeripheral e didDiscoverServices non vengono mai chiamati. Cosa potrebbe esserci di sbagliato? Qualche idea? Grazie

+0

Puoi verificare che la proprietà sia pubblicitaria per vedere se stai effettivamente facendo pubblicità quando ti aspetti o hai mai effettuato il callback di peripheralManagerDidStartAdvertising sul delegato? – yuklai

+0

Aggiungo peripheralManagerDidStart Metodo pubblicitario. E controllo la pubblicità in questo metodo. Ritorna SI. Ciò significa che la mia app pubblicizza correttamente? –

+0

Ho cambiato il mio codice per scansionare le periferiche in questo modo: [self.centralManager scanForPeripheralsWithServices: nil options: nil]; Ci sono comunque per indicare che la mia scansione è riuscita? –

risposta

3

Vorrei provare a spostare il metodo startAdvertising: e fino alla fine del tuo metodo delegato peripheralManagerDidUpdateState: e vedere se questo aiuta.

Vorrei anche aggiungere una coppia chiave-valore CBAdvertisementDataLocalNameKey alla chiamata del metodo startAdvertising:. Ho scoperto che le cose erano inaffidabili quando l'annuncio non aveva un nome.

Infine, vorrei investire nello BLExplr app disponibile nell'App Store per facilitare la scansione della periferica. Rimuove il presupposto che la tua centrale funzioni correttamente.

+0

C'è qualche applicazione gratuita può fare la stessa cosa? –

+0

Nessuna idea. Tre dollari mi sembravano abbastanza ragionevoli – mttrb

+0

Ne trovo uno chiamato BLE Scanner che è gratuito e l'unico in grado di scoprirmi. –

12

C'è anche un'applicazione gratuita di alta qualità chiamata LightBlue che puoi usare per testare il tuo codice con. Dovrebbe essere in grado di raccogliere tutti i dispositivi pubblicitari in modalità periferica e può persino trasformarsi in una periferica pubblicitaria se si desidera assicurarsi che il dispositivo funzioni correttamente.

+1

Ho usato LightBlue come periphral e la mia app l'ha trovato! Grazie! – Gal

+0

LightBlue funziona in modalità Sfondo? In caso contrario, hai qualche altro suggerimento per testare BLE in modalità Sfondo? –

3

Questo progetto hub Git getta luce sull'API CBPeripheralManager. Chiamato PeripheralModeTest. Questa linea è particolarmente utile per impostare i dati pubblicitari

NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey : @"Device Name", CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:CBUUIDGenericAccessProfileString]]}; 

Anche se non riesco a vedere alcuna documentazione ufficiale nella Biblioteca Developer Apple iOS ancora. Più in particolare qualcosa sull'impostazione del periodo di ripetizione per la pubblicità.

0

Non conosco la versione stregone di BTLE Central Peripheral Transfer che hai effettivamente testato ma la versione corrente ha iOS 6 come requisito.

Quindi vorrei suggerire di testare il collegamento con iOS 5.1 per vedere quali problemi di compatibilità mostra.

2

L'BTLE Transfer esempio ha questo pezzo di codice (dispari), che può causare alcuni problemi:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI 
{ 
    // Reject any where the value is above reasonable range 
    if (RSSI.integerValue > -15) { 
     return; 
    } 

    // Reject if the signal strength is too low to be close enough (Close is around -22dB) 
    if (RSSI.integerValue < -35) { 
     return; 
    } 

sufficiente rimuovere quei due se-dichiarazioni, come non ha senso!

Ho reso disponibile una versione semplificata here che può essere utilizzata per testare elevati volumi di messaggi inviati dalla periferica al centro.

Si prega di notare che la classe CBPeripheralManager è stata introdotta per la prima volta in iOS 6.0.

Problemi correlati