Search code examples
swiftxcodebluetoothaes

CBPeripheral being disconnected with UnknownError Code=0 after calling writeValue


I'm developing an app that uses Bluetooth to communicate with Smart Devices. It needs to authorise iPhone with such scheme:

  1. Scanning devices with some filters of services UUIDs
  2. Connecting to a device, discovering services, discovering characteristics
  3. Calling read operation to retrieve public keys
  4. Exchange received public keys (using ECDH)
  5. Generate token
  6. Write encrypted token (using AES) to device using writeValue

That's all, after that I have stable connection and able to interact with my Smart Device (writing values to protected properties).

The question is that when I restart my app and do all of the steps above, except Step_5 (because I have my token generated and validated previous time), on Step_6 delegate method didWriteValueFor: doesn't even get called, instead of this delegate method didDisconnectPeripheral being called with Error Domain=CBErrorDomain Code=0 "Unknown error." UserInfo={NSLocalizedDescription=Unknown error.} and I can't write values to protected characteristics.

I can't get what I'm doing wrong. Any help would be nice.

UPD[0]: Sometimes I can get a callback for didWriteValueFor: on Step_6 but IMMEDIATELY (like less than a 0.5 sec) iPhone is being disconnected with an error from above.

UPD[1]: Also I was trying to cancelPeripheralConnection() before closing my app because Smart Device does not handle multiple connections in hardware reasons, but no luck here.

UPD[2]: Well, after three days of searching for information, I realized that I was digging in the wrong direction at all. The problem was that I interrupted the application with the “Stop” button in Xcode, and didn’t close it manually via iPhone, therefore, willTerminate was not called, and even if it was called, it had a very limited amount of time to execute all the processes that were supposed to be executed, as a result, the connection didn’t interrupt (the cancelPeripheralConnection method was not called), and the next time I started the App, I tried to establish a connection with a device that already has a connection to my App.

At least it started connecting often, but I'm still getting this error sometimes. The main question is: how properly disconnect from the device? For now I’m unsubscribing from all the properties that have isNotify: true (setting to false) and call cancelPeripheralConnection. Do I need to wait the “unsubscribe” process before disconnecting?

UPD[3]: It doesn't matter if I wait for unsubscribe finished or not. At least it have no effect.


Solution

  • Well, I found the reason why disconnects are appears: Since Smart Device has several characteristics of public keys that need to be read, encrypted and then sent back, the order keys I read and write was important. Since writeValue and readValue are asynchronous, my order went astray. As soon as I began to keep order, everything worked like a clock.