title: Receive string data via Bluetooth
body: <p>I'm creating a simple BLE app that communicates with a single peripheral. The phone acts as the central. I have an iPad which I'm using as the peripheral for testing. It has the app <a href="https://itunes.apple.com/us/app/lightblue-explorer/id557428110?mt=8" rel="nofollow noreferrer">LightBlue</a> installed to simulate a peripheral. The peripheral is supposed to send a string of data in this format.</p>
  
  <blockquote>
    <p>TEM:25.11 | HUM:70 | PM10:43 | PM25:32</p>
  </blockquote>
  
  <p>So I created a blank virtual peripheral in LightBlue with one service.</p>
  
  <p><a href="https://i.stack.imgur.com/FT2SG.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/FT2SG.jpg" alt="enter image description here"></a></p>
  
  <p><a href="https://i.stack.imgur.com/mWwow.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/mWwow.jpg" alt="enter image description here"></a></p>
  
  <p>Below is my code for Bluetooth connectivity handling.</p>
  
  <pre><code>import UIKit
  import CoreBluetooth
  
  class ViewController: UIViewController {
  
      fileprivate let serviceUUID = CBUUID(string: "19B10010-E8F2-537E-4F6C-D104768A1214")
      fileprivate let characteristicUUID = CBUUID(string: "19B10011-E8F2-537E-4F6C-D104768A1214")
  
      fileprivate var manager: CBCentralManager!
      fileprivate var peripheral: CBPeripheral!
      fileprivate var characteristic: CBCharacteristic!
  
      override func viewDidLoad() {
          super.viewDidLoad()
          manager = CBCentralManager(delegate: self, queue: nil)
      }
  
      override func viewWillDisappear(_ animated: Bool) {
          super.viewWillDisappear(animated)
          stopScan()
      }
  
      fileprivate func startScan() {
          manager.scanForPeripherals(withServices: [serviceUUID], options: nil)
      }
  
      fileprivate func stopScan() {
          manager.stopScan()
      }
  
      fileprivate func disconnectFromDevice() {
          guard let peripheral = peripheral else { return }
          manager.cancelPeripheralConnection(peripheral)
      }
  
      fileprivate func restoreCentralManager() {
          manager.delegate = self
      }
  
  }
  
  // MARK: - CBCentralManagerDelegate
  extension ViewController: CBCentralManagerDelegate {
      func centralManagerDidUpdateState(_ central: CBCentralManager) {
          switch central.state {
          case .unsupported:
              print("Unsupported")
          case .unauthorized:
              print("Unauthorized")
          case .poweredOn:
              print("Powered On")
              startScan()
          case .resetting:
              print("Resetting")
          case .poweredOff:
              print("Powered Off")
          case .unknown:
              print("Unknown")
          }
      }
  
      func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
          print("Discovered \(String(describing: peripheral.name)) at \(RSSI)")
  
          if peripheral.name == nil || peripheral.name == "" {
              return
          }
  
          if self.peripheral == nil || self.peripheral.state == .disconnected {
              stopScan()
  
              self.peripheral = peripheral
              central.connect(peripheral, options: nil)
          }
      }
  
      func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
          peripheral.delegate = self
          peripheral.discoverServices([serviceUUID])
      }
  
      func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
  
          self.peripheral = nil
          central.scanForPeripherals(withServices: nil, options: nil)
      }
  
      func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
          self.peripheral = nil
      }
  
      func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
      }
  }
  
  // MARK: - CBPeripheralDelegate
  extension ViewController: CBPeripheralDelegate {
      func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
          guard let services = peripheral.services else { return }
          print("No. of services: \(services.count)")
  
          for service in services {
              print(service.uuid)
              if service.uuid == serviceUUID {
                  peripheral.discoverCharacteristics(nil, for: service)
              }
          }
      }
  
      func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
          guard let characteristics = service.characteristics else { return }
  
          for characteristic in characteristics {
              print("characteristic: \(characteristic.uuid)")
              if characteristic.uuid == characteristicUUID {
                  self.characteristic = characteristic
                  peripheral.setNotifyValue(true, for: characteristic)
                  peripheral.readValue(for: characteristic)
              }
          }
      }
  
      func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
          print(error)
      }
  
      func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {        
          if characteristic.uuid == characteristicUUID {
              print("Got reply from: \(characteristic.uuid)")
              print(characteristic.value)
              if let data = characteristic.value, let string = String(data: data, encoding: String.Encoding.utf8) {
                  print(string)
              } else {
                  print("No response!")
              }
          }
      }
  
  }
  </code></pre>
  
  <p>The discovering and connecting part works just fine. The problem is I don't receive that data string from the peripheral.</p>
  
  <p>The method <code>peripheral(_:didUpdateValueFor:error:)</code> does get fired. I get the <em>Got reply from: 19B10011-E8F2-537E-4F6C-D104768A1214</em> output in the console. However when I tried to see if there's any data by printing out the <code>characteristic.value</code>, it returns <code>nil</code>.</p>
  
  <p>Not sure if it's something wrong with my code. Or I've configured the peripheral on LightBlue wrong. Does LightBlue send out data automatically? I don't see any <em>Send</em> button or anything anywhere either.</p>
  
  <p>I uploaded a demo project <a href="https://www.dropbox.com/s/hkkoa85a6r3j039/BLEDemo.zip?dl=0" rel="nofollow noreferrer">here</a> as well.</p>