Using XCode simulator to do device onboarding

During developing your iPhone client you may have to go through the onboarding process many times. Naturally, if you are developing your onboarding workflow that is all you do. But even when that is settled and you are working on other parts of the app you may find yourself wanting to wipe the device clean just to make sure all your defaults are prim and proper and you create the objects and constructs as you require them later on in your app. So you break out your extra developer phone(s) and put them through their paces - oh you don’t have a bag of phones?

Well I do normally have a few developer phones but not always have access to these so wouldn’t it be nice if you could use the Xcode simulator? Well… it doesn’t work that way - the Xcode simulator is capable of simulating a phone pretty close but some things it does not do. Geo location for one but also it has no clue what network you’re connecting to and that, my friends, means we cannot connect to a particle device during onboarding and connect back to our wifi.

I’ve been frustrated with this before but today decided to do something about it. Diving into the particle-setup-SDK, it is quickly clear that the ParticleSetupCommManager’s method checkParticleDeviceWifiConnection() is the culprit. Mind you, it works fine but the embedded call to CNCopySupportedInterfaces() fails with a nil everytime. Apple in their infinite wisdom decided that this method shall not work in the simulator. Normally, if you run all this on the iPhone, CNCopySupportedInterfaces() returns a dict with all the current networks available, particle’s code then loops through these in search of your provided device’s network prefix. If it finds it returns YES, else NO.

The checkParticleDeviceWifiConnection() call is made throughout the particle code - sort of as a means to figure out where the user is in the onboarding process. Initially the user is asked to be on their WiFi, then switch to the device “PREFIX-XXXX” with the XXXX being some random number, the particle-setup-SDK can then do its magic through softAP calls to get the networks the device can see, let you pick one and set user/pwd for it so the device can connect. So what we like to see from checkParticleDeviceWifiConnection() is:

  1. an initial NO (still connected to WiFi)
  2. followed by YES (user has switched to device), magic happens
  3. followed by NO again, device is rebooting/starting/connecting to wifi and particle so app can get device ID etc.

It seemed to me, all I need to do is to mess around with this method’s return value … without altering the particle code naturally. And whatdayaknow, the LLDB just allows for such thing:

A. Place a breakpoint on the "return NO" line with:
     condition: $ssidok > 0
     debugger command: thread return YES
     options: set auto continue to true
B. Place a break point in your AppDelegate:
    debugger command:  expression -l objc -- int $ssidok=10
C. Place a breakpoint in ParticleConnectingProgressViewcontroller.m/connectDeviceToNetwork on the first line that reads "self.disconnectRetries++;"  with:
   debugger command: expression $ssidok--

Now when you go through the onboarding steps in the debugger, create an account as usual (or type in the account you already have), when the app tells you to switch to the iphone setup, simply switch your computer’s WiFi to the device’s net. Watch the code struggle a bit and … yes! finds the device. Now you can finish the onboarding as usual. At some point the device connects to WiFi/particle at which point the computer loses the network and takes a bit of time to reconnect to your normal WiFi. It should then pickup the device’s ID from particle and you’re all set.

Perhaps this is kicking in an open door with you all but I had not seen this method deployed elsewhere and had some fun digging into the bowels of particle setup SDK. Hope it helps someone…