2013-10-23 6 views
10

sto sperimentando un problema in cui il tempo tra la scrittura di un valore ad una caratteristica utilizzando ilcore Bluetooth rallentare quando l'invio di pacchetti

[peripheral writeValue:dataPacket forCharacteristic:writeChar type:CBCharacteristicWithResponse] 

e il dispositivo iOS in realtà l'invio fisicamente il pacchetto bluetooth sta progressivamente prendendo più tempo e più a lungo.

Ciò può essere illustrato nel seguente uscita dal debugger:

2013-10-23 14:12:17.510 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:12:17.595 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:12:17.598 Test App iOS[1561:60b] Packet response received 

2013-10-23 14:12:17.611 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:12:17.656 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:12:17.657 Test App iOS[1561:60b] Packet response received 

2013-10-23 14:12:22.601 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:12:23.123 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:12:23.125 Test App iOS[1561:60b] Packet response received 

2013-10-23 14:12:27.601 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:12:28.111 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:12:28.113 Test App iOS[1561:60b] Packet response received 

2013-10-23 14:12:32.611 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:12:34.595 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:12:34.597 Test App iOS[1561:60b] Packet response received 


2013-10-23 14:12:37.611 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:12:39.582 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:12:39.585 Test App iOS[1561:60b] Packet response received 

2013-10-23 14:12:42.611 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:12:44.570 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:12:44.573 Test App iOS[1561:60b] Packet response received 

2013-10-23 14:12:47.611 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:12:49.558 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:12:49.560 Test App iOS[1561:60b] Packet response received 

// Several packets omitted... 

2013-10-23 14:13:07.610 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:13:09.508 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:13:09.511 Test App iOS[1561:60b] Packet response received 

2013-10-23 14:13:12.610 Test App iOS[1561:60b] Packet sent 
2013-10-23 14:13:14.496 Test App iOS[1561:60b] Packet sent confirmation, error = (null) 
2013-10-23 14:13:14.498 Test App iOS[1561:60b] Packet response received 

// E così via ...

Il pacchetto messaggio inviato viene emesso sulla linea immediatamente dopo il comando writeValue a scrivi il pacchetto di dati sulla caratteristica.

La conferma del pacchetto inviato viene emessa nella prima riga del metodo delegato didWriteValueForCharacteristic.

Il messaggio di risposta al pacchetto ricevuto viene emesso nel file didUpdateValueForCharacteristic che viene chiamato quando il dispositivo BTLE invia il pacchetto di risposta (tramite una caratteristica di notifica secondaria) per confermare la ricezione del pacchetto inviato.

Come si può osservare inizialmente il tempo tra la mia chiamata al metodo writeValue forCharacteristic e il callback per confermare il pacchetto è stato inviato in didWriteValueForCharacteristic è inizialmente 85ms (che è già lento ma sopportabile). Invio questi pacchetti circa ogni 5 secondi, e dopo solo un piccolo numero di pacchetti inviati questo aumenta a ~ 2 secondi dopo di che sembra essere statico continuamente a 2 secondi. Il pacchetto di risposta inviato dal dispositivo BTLE è sempre ~ 2ms dopo la conferma del pacchetto inviato.

Non capisco perché sto ricevendo questo ritardo nelle librerie CoreBluetooth tra la chiamata di writeValue e il callback di conferma didWriteValueForCharacteristic.

In tutti gli altri aspetti il ​​codice funziona perfettamente (il dispositivo BTLE sta facendo esattamente ciò che viene istruito a fare e nessuno dei pacchetti scompare).

Ho un'app di esempio fornita dal produttore del modulo BT4.0 (inclusa la sorgente) che non presenta questo ritardo crescente - sfortunatamente l'app di esempio è progettata per far fronte a una vasta gamma di implementazioni del modulo, non solo la nostra implementazione specifica e quindi è enormemente complessa e contiene molto codice che non è rilevante per la nostra implementazione - ho inserito i punti di interruzione in ogni funzione del campione e ho fatto un passaggio manualmente per determinare esattamente quali comandi stanno emettendo, e credo di essere copiandoli perfettamente (ma ovviamente non).

Non riesco a vedere nulla di quello che stanno facendo che non sto facendo e viceversa. L'unica differenza che posso individuare tra i due progetti è che la mia utilizza ARC e la loro utilizza il conteggio dei riferimenti manuale.

Altre informazioni: Tutto è in esecuzione sul thread principale (come è con il produttori di moduli applicazione del campione) creo il Direttore Centrale utilizzando la coda principale (in modo simile a produttori di moduli applicazione del campione) carico della CPU sul iOS dispositivo è solo al 3% mentre la mia app è in esecuzione e nulla sembra essere in ritardo a causa del carico della CPU ecc.

Mi sto strappando i capelli con questo, e se qualcuno può suggerire eventuali cause o soluzioni per questo problema Ne sarei eternamente grato!

Grazie, Rich

+0

E 'davvero, davvero interessante che la loro applicazione del campione non presenta questo ritardo, ma la tua fa. Non ho una buona ragione per cui sia così. È un voodoo, ma per escluderlo, puoi provare a fare una semplice app di conteggio dei ritardi manuale per vedere se ARC lo sta influenzando? – cbowns

+0

È qualcosa che stavo considerando. Non ho mai avuto problemi con ARC prima d'ora, ma poiché escludo altre possibilità, sono giunto alla conclusione che dovrò dimostrare che ARC non causa il problema e fare qualcosa come suggerisci tu. –

+0

Ho pensato un po 'a questo: potrebbe valere la pena di profilare sia l'app CoreBluetooth che l'app di esempio con Instruments per vedere quali oggetti vengono creati quando. Se la tua app ha un insetto bug intorno alla creazione di risorse che non rilascia mai, CoreBluetooth potrebbe passare più tempo ad aggiornare gli oggetti che non vengono più utilizzati, e questo potrebbe essere il motivo del rallentamento. – cbowns

risposta

7

mi hanno fatto qualche progresso su questo e la notizia non è buona. Si scopre che la mia descrizione originale del problema non è corretta. Avevo pensato (sempre una brutta cosa da fare) che l'app di esempio prodotta dal fornitore del modulo fosse corretta, tuttavia i dati temporali che riportavano erano errati - quando segnalano ~ 3ms per inviare il pacchetto e recuperare la risposta, sono solo i tempi da -didWriteValueForCharacteristic e non includono il tempo che intercorre tra la chiamata a writeValueForCharacteristic e il didWriteValueForCharacteristic - una volta inclusa questa volta la loro app si comporta lentamente come la mia.

Dopo tutte le ulteriori indagini, sembra che le librerie CoreBluetooth iOS stiano causando il ritardo tra la richiesta di invio del pacchetto e l'invio effettivo - questi ritardi arbitrari possono essere ovunque tra 80 ms e 2 secondi. Qualcuno sa perché le librerie iOS sono così lente nell'inviare il pacchetto vero e proprio? Il nostro codice equivalente in esecuzione su Android è più o meno istantaneo.

Se avessi il mio cinico cappello direi che Apple sta deliberatamente facendo questo per impedire che applicazioni che richiedono una risposta rapida vengano sviluppate usando BTLE e quindi costringono gli sviluppatori hardware a usare Bluetooth 3 che richiede il chip di sicurezza Apple e quindi efficacemente comporta un costo di licenza mela sulla unità prodotte ...

+1

Ho lo stesso problema. Hai trovato qualcos'altro? – mohkhan

+0

Ho riscontrato anche lo stesso problema con iOS 9. Qualcuno ha mai scoperto qualcosa? – Pierre

1

Prima di tutto controllare quello che si ottiene in:

-(void) peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic 
error:(NSError *)error { 

} 

se il codice di errore è 0 che significa che si sta inviando valore alla periferica senza confermare esso. Verificare che il periheral implementa questo metodo:

//assuming 
@property (strong, nonatomic) CBPeripheralManager  *peripheralManager; 

- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests 
{ 
    NSLog(@"WRITE REQUEST!!! %lu",(unsigned long)requests.count); 
    //check if there are data 

    for (CBATTRequest * req in requests) { 
    //send reposnse to Central that you recivied write value and eg/accept/reject the write request 
    [self.peripheralManager respondToRequest:req 
              withResult:CBATTErrorSuccess]; 
    } 


}