Upgrade to Pro — share decks privately, control downloads, hide ads and more …

全部見せます!最前線エンジニアが語るBleアプリケーションのハマりどころ(iOS)

Takaaki Tanaka
February 20, 2016

 全部見せます!最前線エンジニアが語るBleアプリケーションのハマりどころ(iOS)

Developers.IO 2016 F-4 セッションでの発表資料です。

Takaaki Tanaka

February 20, 2016
Tweet

More Decks by Takaaki Tanaka

Other Decks in Technology

Transcript

  1. $PSF#MVFUPPUI w #-&୺຤ͱͷ઀ଓ w #-&୺຤ͱͷ઀ଓ͠ɺσʔλͷಡΈॻ͖Λߦ͏ɻ w όοΫάϥ΢ϯυͰ΋ಈ࡞͢Δɻ w #-&୺຤ͱͯ͠ৼΔ෣͏ w

    J04୺຤Λ#-&୺຤ͱͯ͠ଞͷ#-&୺຤ͱ઀ଓ͢Δ͜ͱ͕Ͱ ͖Δɻ w J04୺຤ಉ࢜΋઀ଓ͢Δ͜ͱ͕Ͱ͖Δɻ  ⡥$MBTTNFUIPE *OD
  2. ϋϚΓͲ͜Ζ w ໨ʹݟ͑ͳ͍΋ͷͱͷઓ͍ w ి೾͕ຊ౰ʹग़͍ͯΔͷ͔Θ͔Βͳ͍ɻ w σʔλ͕ૹ৴͞Ε͍ͯΔͷ͔Θ͔Βͳ͍ɻ w 1FSJQIFSBMଆͷಈ࡞ w

    ࡞੒͢ΔΞϓϦ͸$FOUSBMͱͯ͠ৼΔ෣͏΋ͷ͕ଟ͍ɻ w ݪҼͷ੾Γ෼͚ͷͨΊʹ͸1FSJQIFSBMଆͷ஌͕ࣝඞཁɻ  ⡥$MBTTNFUIPE *OD
  3. ಈ࡞֓ཁ w $FOUSBM w 1FSJQIFSBMͷεΩϟϯ w 1FSJQIFSBMͱ઀ଓ w 4FSWJDFͷݕग़ w

    $IBSBDUFSJTUJDTͷݕग़ w มߋ௨஌ઃఆ  ⡥$MBTTNFUIPE *OD w 1FSJQIFSBM w ΞυόλΠζ։࢝ w $FOUSBMͱ઀ଓ HJUIVCIUUQTHJUIVCDPNLPOHNJOHTUSBQ#-&4BNQMFS
  4. 66*%ͷઃఆ  ⡥$MBTTNFUIPE *OD static private let ServiceUUID = CBUUID(string:

    "A8C7922D-8849-4FBC-8692-4DBB291F99C8") static private let CharacteristicsUUID = CBUUID(string: "D2E2C5E2-B0B9-4AF6-9AD9-361A819FB30F") $ uuidgen A8C7922D-8849-4FBC-8692-4DBB291F99C8 w 4FSWJDFͱ$IBSBDUFSJTUJDTͷ66*%ΛܾΊΔ w VVJEHFOίϚϯυͰੜ੒ͨ͠66*%Λઃఆ͠·͢ɻ
  5. NBOBHFSͷੜ੒  ⡥$MBTTNFUIPE *OD self.peripheralManager = CBPeripheralManager( delegate: self, queue:

    nil, options: [CBPeripheralManagerOptionShowPowerAlertKey: true]) w 1FSJQIFSBM w $FOUSBM self.centralManager = CBCentralManager( delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: true]) NBOBHFSͷੜ੒͸εΩϟϯɺ઀ଓͷ௚લʹߦΘͳ͍͜ͱɻ
  6. NBOBHFSͷੜ੒  ⡥$MBTTNFUIPE *OD [CBPeripheralManagerOptionShowPowerAlertKey: true] w 1FSJQIFSBM w $FOUSBM

    [CBCentralManagerOptionShowPowerAlertKey: true] w ΞϥʔτͷΦϓγϣϯ w ࢦఆ͓ͯ͘͠ͱNBOBHFSੜ੒࣌ʹ୺຤ͷ #MVFUPPUI͕Φϑͩͬͨ৔߹ʹΞϥʔτ͕ දࣔ͞ΕΔɻ w ʮઃఆʯΛλοϓ͢Δͱ#MVFUPPUIͷઃఆ ը໘ʹભҠ͠·͢ɻ
  7. ʢ1FSJQIFSBMʣ4FSWJDFͷ௥Ճ  ⡥$MBTTNFUIPE *OD let service = CBMutableService( type: PeripheralViewController.ServiceUUID,

    primary: true) service.characteristics = [self.characteristic] self.peripheralManager?.addService(service) private let characteristic = CBMutableCharacteristic( type: PeripheralViewController.CharacteristicsUUID, properties: .Notify, value: nil, permissions: .Readable) w $IBSBDUFSJTUJDTΛઃఆ w 4FSWJDF͕࣋ͭ$IBSBDUFSJTUJDΛઃఆ͠·͢ɻ w $#1FSJQIFSBM.BOBHFSʹ4FSWJDFΛ௥Ճ w ࡞੒ͨ͠$IBSBDUFSJTUJDΛ௥Ճ͓͖ͯ͠·͢ɻ
  8. ʢ$FOUSBMʣ1FSJQIFSBMͷεΩϟϯ  ⡥$MBTTNFUIPE *OD self.centralManager?.scanForPeripheralsWithServices( [CentralViewController.ServiceUUID], options: nil) w 1FSJQIFSBMͷεΩϟϯ

    w ΞυόλΠζ͞Ε͍ͯΔ1FSJQIFSBMΛݕग़͠·͢ɻ PQUJPOTʹ $#$FOUSBM.BOBHFS4DBO0QUJPO"MMPX%VQMJDBUFT,FZΛ USVFͰࢦఆ͢Δͱಉ͡1FSJQIFSBM͕ Կ౓΋ݕग़͞ΕΔͷͰ஫ҙɻ
  9. ʢ$FOUSBMʣ1FSJQIFSBMͱ઀ଓ  ⡥$MBTTNFUIPE *OD func centralManager( central: CBCentralManager, didDiscoverPeripheral peripheral:

    CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) { let foundIds = self.foundPeripherals.map { peripheral in peripheral.identifier.UUIDString } if !foundIds.contains(peripheral.identifier.UUIDString) { self.foundPeripherals.append(peripheral) } } w 1FSJQIFSBMͷݕग़ w σϦήʔτϝιουʹݕग़ͨ͠1FSJQIFSBM͕ฦ͖ͬͯ·͢ɻ
  10. ʢ$FOUSBMʣ1FSJQIFSBMͱ઀ଓ  ⡥$MBTTNFUIPE *OD if peripheral.state != .Connected { self.centralManager?.connectPeripheral(

    peripheral, options: nil) } w ࢦఆͨ͠1FSJQIFSBMͱ઀ଓ w ݕग़ࡁΈͷ1FSJQIFSBM΁ͷ઀ଓΛ։࢝͠·͢ɻ
  11. ʢ$FOUSBMʣ4FSWJDFͷݕग़  ⡥$MBTTNFUIPE *OD func centralManager( central: CBCentralManager, didConnectPeripheral peripheral:

    CBPeripheral) { self.connectedPeripheral = peripheral self.connectedPeripheral?.delegate = self self.connectedPeripheral?.discoverServices( [CentralViewController.ServiceUUID]) w ઀ଓࡁΈͷ1FSJQIFSBMͷ4FSWJDFͷݕग़ w $#1FSJQIFSBM%FMFHBUFͷઃఆΛߦ͍·͢ɻ w ઀ଓࡁΈͷ1FSJQIFSBM͕ࢦఆͨ͠4FSWJDFΛݕग़͠·͢ɻ EJTDPWFS4FSWJDFTʹOJMΛࢦఆ͢Δͱෆඞཁͳ4FSWJDF·Ͱ ݕग़͢ΔͨΊɺඞཁͳ4FSWJDFͷΈࢦఆ͢Δ͜ͱɻ
  12. ʢ$FOUSBMʣ$IBSBDUFSJTUJDTͷݕग़  ⡥$MBTTNFUIPE *OD func peripheral( peripheral: CBPeripheral, didDiscoverServices error:

    NSError?) { if let services = peripheral.services { services.filter { service in service.UUID.data == CentralViewController.ServiceUUID.data }.forEach { service in peripheral.discoverCharacteristics( [CentralViewController.CharacteristicsUUID], forService: service ) } } } w $IBSBDUFSJTUJDTͷݕग़ w ݕग़ࡁΈͷ4FSWJDFʹରͯ͠$IBSBDUFSJTUJDTΛݕग़͠·͢ɻ
  13. ʢ$FOUSBMʣมߋ௨஌ઃఆ  ⡥$MBTTNFUIPE *OD func peripheral( peripheral: CBPeripheral, didDiscoverCharacteristicsForService service:

    CBService, error: NSError?) { if service.UUID.data == CentralViewController.ServiceUUID.data, let characteristics = service.characteristics { characteristics.filter { characteristic in characteristic.UUID.isEqual( CentralViewController.CharacteristicsUUID) }.forEach { [unowned self] characteristic in self.setNotify(true, peripheral: peripheral) } } w $IBSBDUFSJTUJDTͷมߋ௨஌ઃఆ w ݕग़ࡁΈͷ$IBSBDUFSJTUJDTʹରͯ͠มߋ௨஌ઃఆΛ͠·͢ɻ
  14. ʢ1FSJQIFSBMʣมߋ௨஌  ⡥$MBTTNFUIPE *OD guard let data = "foo".dataUsingEncoding(NSUTF8StringEncoding) else

    { fatalError("Failed dataUsingEncoding") } self.peripheralManager?.updateValue( data, forCharacteristic: self.characteristic, onSubscribedCentrals: nil) w $FOUSBMʹ௨஌ w $FOUSBMʹରͯ͠஋ͷมߋΛ௨஌͠·͢ɻ
  15. ʢ$FOUSBMʣมߋ௨஌ड৴  ⡥$MBTTNFUIPE *OD func peripheral( peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic:

    CBCharacteristic, error: NSError?) { if characteristic.UUID.data == CentralViewController.CharacteristicsUUID.data { guard let value = characteristic.value else { fatalError("invalid characteristic value.") } guard let string = String(data: value, encoding: NSUTF8StringEncoding) else { return } self.connectedPeripheralLabel.text = string } w 1FSJQIFSBMΑΓมߋ௨஌ w 1FSJQIFSBM͔Βͷมߋ௨஌Λड৴͠·͢ɻ
  16. ʢ$FOUSBMʣ੾அΠϕϯτͷݕग़  ⡥$MBTTNFUIPE *OD w ੾அΠϕϯτΛϋϯυϦϯά w ෺ཧతʹ੾Εͨ৔߹ʹདྷΔΠϕϯτͰ͸ͳ͍ͷͰ஫ҙɻ w ͋͘·Ͱ1FSJQIFSBM͕ʮ੾அͨ͠ͱΈͳͯ͠΋ྑ͍ʯঢ়ଶʹͳͬͨ͜ͱΛ௨஌͠·͢ɻ

    func centralManager( central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) { if error != nil { let controller = UIAlertController( title: nil, message: NSLocalizedString( "The connection to the device closed.", comment: ""), preferredStyle: .Alert) let okAction = UIAlertAction( title: NSLocalizedString("OK", comment:""), style: .Default, handler: nil) controller.addAction(okAction) self.presentViewController( controller, animated: true, completion: nil) } } }