jordanebelanger / SwiftyBluetooth

Closures based APIs for CoreBluetooth
MIT License
209 stars 66 forks source link

Operation timed out: Discover services #17

Closed casperstorm closed 7 years ago

casperstorm commented 7 years ago

I am having an issue with timeouts: Bluetooth operation timed out: Discover services. I am currently connecting to a peripheral, writing some data to it, and then disconnecting again. The connect never fails, however when I am about to write it often (~80% of the times) times out. I can then try to redo the process, and be lucky to get through.

Below is a snippet of my code.

enum Bluetooth {
    enum serviceUUID: String {
        case standard = "FF00"
    }
    enum characteristicUUID: String {
        case wifiState      = "F000FF01-0451-4000-B000-000000000000"
        case wifiSSID       = "F000FF02-0451-4000-B000-000000000000"
        case wifiPassword   = "F000FF03-0451-4000-B000-000000000000"
    }
}

fileprivate func connect(completion: @escaping ((Error?) -> ())) {
    guard let config = config else { return }
    guard let peripheral = config.peripheral else { return }

    peripheral.connect(completion: completion)
}

fileprivate func disconnect(completion: @escaping ((Error?) -> ())) {
   guard let config = config else { return }
   guard let peripheral = config.peripheral else { return }

   peripheral.disconnect(completion: completion)
}

fileprivate func write(to service: Bluetooth.characteristicUUID, payload: String, completion: @escaping ((Error?) -> ())) {
   guard let config = config else { return }
   guard let peripheral = config.peripheral else { return }
   let data = Data(somedata)

   peripheral.writeValue(ofCharacWithUUID: service.rawValue,
                              fromServiceWithUUID: Bluetooth.serviceUUID.standard.rawValue,
                              value: data,
                              completion: completion)
}

I have tried to do discoverServices(...) instead of connect without any luck. My flow is as following: I call connect function, and in the completion i call write function and in that completion i call disconnect.

Have anyone had any similar experiences?

jordanebelanger commented 7 years ago

Hi Casper, first let me clarify to you what the library does when you try to write to a peripheral, the library will:

  1. Connect to the peripheral if not connected.
  2. Discover the service if it hasn't been discovered yet.
  3. Discover the service characteristic if it hasn't been discovered yet.
  4. Write to your peripheral's characteristic.

So the library is supposed to do these things for you when you attempt to write, technically you could initiate a write directly without any prior call, or at least thats the goal I set for the library.

The timeout error you're getting means that you did connect to the peripheral, but timed out while attempting to discover the service you're requesting. CoreBluetooth itself does not have operation timeouts internally that I am aware of, at least for a service discovery operation like this, but the SwiftyBluetooth itself has a timeout for these (10 seconds).

You may want to try your calls again with a longer timeout for peripheral operations, check out the PeripheralProxy class and increase the value for this static var and see if it helps.

static let defaultTimeoutInS: TimeInterval = 10
jordanebelanger commented 7 years ago

@casperstorm How are you doing?

casperstorm commented 7 years ago

Hi @tehjord, Thanks for the response. I had to do some testing before responding. I tried to remove the connectfunction, letting the writefunction handle it instead. I also tried to bump up the timeout as suggested, however both things didn't seem to change the timeout issue.

Then i tried to connect as soon as I discover the peripheral, and then delaying the write (waiting for user input) and that seem to do the trick. So, I think there might be a timing issue on he hardware and not a problem in your (awesome) library. I will now investigate and debug the hardware.

Thanks for taking the time, @tehjord - and keep up the good work.

jordanebelanger commented 7 years ago

@casperstorm Thanks caper. I actually created the library after getting frustrated while doing what you seem to be doing right now, which is, connect some custom made IOT device to wifi through bluetooth. I will be bringing in some change soon, mostly, I'lll switch the completion closures to have a "Result" type enum parameter instead of an optional Error to make things clearer.