2016-09-24 2 views
0

J'implémente un CentralManager avec le framework CoreBluetooth afin d'extraire les valeurs fournies par les périphériques.CBPeripheral Service semble être invisible

Je recherche d'abord les périphériques qui ont un service avec un UUID spécifique ("52486FA8-FF0B-4A91-A344-D642D0E91AD0"). Le CentralManager trouve le périphérique mais lorsque j'essaie d'imprimer les Services de ce périphérique, j'obtiens un tableau vide.

Voici mon code

// 
// ViewController.swift 
// centralLearn 
// 
// Created by Francesco Vanduynslager on 24/09/2016. 
// Copyright © 2016 Francesco Vanduynslager. All rights reserved. 
// 

import UIKit 
import CoreBluetooth 

class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate { 
    var centralManager: CBCentralManager! 
    var discoveredPeripherals: [CBPeripheral]! 

    let serviceUUID = CBUUID(string:"52486FA8-FF0B-4A91-A344-D642D0E91AD0") 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     centralManager = CBCentralManager(delegate: self, queue: nil) 
     discoveredPeripherals = [] 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    func centralManagerDidUpdateState(_ central: CBCentralManager) { 
     if central.state == .poweredOn { 
      print("Central Started") 
      centralManager.scanForPeripherals(withServices: [serviceUUID], 
               options: nil) 
     } else if central.state == .poweredOff { 
      centralManager.stopScan() 
     } 
    } 

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { 
     print("Discovered Peripheral: \(peripheral.name)") 
     self.discoveredPeripherals.append(peripheral) 
     centralManager.connect(peripheral, options: nil) 
     centralManager.stopScan() 
    } 

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { 
     print("Connected to peripheral!! \(peripheral)") 
     print("count: \(peripheral.services?.count)") 
     peripheral.delegate = self 

     if (peripheral.services == nil) { 
      peripheral.discoverServices([serviceUUID]) 
     } 
    } 

    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { 
     if error != nil { 
      print("Discover service Error: \(error)") 
     } else { 
      print("Discovered Service") 
      for service in peripheral.services!{ 
       print("SERV: \(service)") 
       peripheral.discoverCharacteristics([CBUUID(string: "5A5E5393-4505-471C-BA90-7AD044FFFD9C")], for: service) 
      } 
      print(peripheral.services) 
      print("DONE") 
     } 
    } 

    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { 
     let characteristic = service.characteristics?[0] 
     print("Discovered Characteristic") 
     peripheral.readValue(for: characteristic!) 
    } 


    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { 
     if error != nil { 
      print("Read value service Error: \(error)") 
     } else { 
      print("Value of Characteristic: \(characteristic.value)") 
     } 
    } 
} 

Et les impressions qui en résultent sont les suivantes:

Central Started 
Discovered Peripheral: Optional("-ShEsKo-") 
Connected to peripheral!! <CBPeripheral: 0x1740f7d00, identifier = A9B3F888-99E1-C62B-DF93-87F1F99AE847, name = -ShEsKo-, state = connected> 
count: nil 
Discovered Service 
Optional([]) 
DONE 

EDIT

Voici mon code périphérique:

// 
// ViewController.swift 
// peripheralLearn 
// 
// Created by Francesco Vanduynslager on 24/09/2016. 
// Copyright © 2016 Francesco Vanduynslager. All rights reserved. 
// 

import UIKit 
import CoreBluetooth 
import CoreLocation 

class ViewController: UIViewController, CBPeripheralManagerDelegate { 
    var localBeacon: CLBeaconRegion! 
    var beaconPeripheralData: NSDictionary! 
    var peripheralManager: CBPeripheralManager! 

    var services: [CBMutableService]! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     initLocalBeacon() 
     // Do any additional setup after loading the view, typically from a nib. 
    } 

    func initLocalBeacon() { 
     if localBeacon != nil { 
      stopLocalBeacon() 
     } 

     let localBeaconUUID = "B65D79F6-74A2-482F-A669-FA5AB35CD3B8" 
     let localBeaconMajor: CLBeaconMajorValue = 123 
     let localBeaconMinor: CLBeaconMinorValue = 456 

     let uuid = UUID(uuidString: localBeaconUUID)! 
     localBeacon = CLBeaconRegion(proximityUUID: uuid, major: localBeaconMajor, minor: localBeaconMinor, identifier: "Your private identifer here") 

     beaconPeripheralData = localBeacon.peripheralData(withMeasuredPower: nil) 
     peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil) 



     /// FIRST SERVICE 
     let serviceUUID = CBUUID(string: "52486FA8-FF0B-4A91-A344-D642D0E91AD0") 
     let characteristicUUID = CBUUID(string: "5A5E5393-4505-471C-BA90-7AD044FFFD9C") 

     let characteristic = CBMutableCharacteristic(type: characteristicUUID, 
                properties: .read, 
                value: "hello".data(using: .utf8), 
                permissions: .readable) 

     let service = CBMutableService(type: serviceUUID, primary: true) 

     service.characteristics = [characteristic] 

     services=[service] 
     peripheralManager.add(service) 
    } 

    func stopLocalBeacon() { 
     peripheralManager.stopAdvertising() 
     peripheralManager = nil 
     beaconPeripheralData = nil 
     localBeacon = nil 
    } 

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) { 
     if peripheral.state == .poweredOn { 
      print("peripheral Started") 
//   peripheralManager.startAdvertising(beaconPeripheralData as! [String: AnyObject]!) 
      peripheralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey: [services[0].uuid, services[1].uuid]]) 
     } else if peripheral.state == .poweredOff { 
      peripheralManager.stopAdvertising() 
     } 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) { 
     if (error != nil){ 
      print("ERROR starting advertising") 
     }else{ 
      print("Did Start advertising") 
     } 
    } 

    func peripheralManager(_ peripheral: CBPeripheralManager, willRestoreState dict: [String : Any]) { 
     print("Restoring state") 
    } 

    func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) { 
     if (error != nil) { 
      print("ERROR adding service: \(error)") 
     }else{ 
      print("Service added: \(service)") 
     } 
    } 
} 
+0

Quel est le périphérique? Est-ce à la fois l'offre et la publicité du service spécifié? Avez-vous essayé l'application Light Blue pour voir si elle peut voir le service. – Paulw11

+0

que diriez-vous d'imprimer l'UUID de service avec 'print (" SERV: \ (service.UUID.UUIDString) ")'? – Enix

+0

@Enix Cela ne sert à rien puisque peripherique.services est un tableau vide, ce qui signifie que le programme n'interviendra pas dans cette boucle. – ShEsKo

Répondre

1

Votre problème est dans votre code périphérique. Vous ne pouvez pas ajouter le service au CBMutablePeripheral jusqu'à ce que le CBPeripheralManager soit à l'état sous tension.

Je vous suggère de déplacer votre service vers sa propre fonction et d'appeler cette fonction lorsque vous êtes sous tension.

func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) { 
    if peripheral.state == .poweredOn { 
     print("peripheral Started") 
     //   peripheralManager.startAdvertising(beaconPeripheralData as! [String: AnyObject]!) 
     self.setupService() 
    } else if peripheral.state == .poweredOff { 
     peripheralManager.stopAdvertising() 
    } 
} 

func setupService() { 
    let serviceUUID = CBUUID(string: "52486FA8-FF0B-4A91-A344-D642D0E91AD0") 
    let characteristicUUID = CBUUID(string: "5A5E5393-4505-471C-BA90-7AD044FFFD9C") 

    let characteristic = CBMutableCharacteristic(type: characteristicUUID, 
               properties: .read, 
               value: "hello".data(using: .utf8), 
               permissions: .readable) 

    let service = CBMutableService(type: serviceUUID, primary: true) 

    service.characteristics = [characteristic] 

    services=[service] 
    peripheralManager.add(service) 
    peripheralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey: [services[0].uuid]]) 

} 
+0

Paul vous le patron !! – ShEsKo

+0

Je viens d'ajouter le périphérique de fonction délégué: DidRecieveReadRequest et il n'est pas appelé même si mon périphérique lit le message. Une idée pourquoi? – ShEsKo

+0

Vous avez spécifié une valeur pour votre caractéristique lorsque vous l'avez créée, elle a donc une valeur fixe. Si vous définissez sa valeur initiale à 'nil', la méthode déléguée sera appelée. – Paulw11