Sphero.playgroundbook Unable to Connect Sphero 2.0

I'm currently setting up a project for my coding class with Sphero and Swift Playgrounds. I'm using the playground from Apple's Swift Demo: https://developer.apple.com/swift/blog/?id=38


However, we're having issues with the code. The playground is unable to find the peripheral. We receive this prompt:

"Unable to find a Sphero device", message: "No Sphero devices were in range."


However, we have the device powered, Bluetooth connected and with a foot of the iPad.


We've tried to connect through a different function we found in the source files:

public class func named(_ name: String)


With String = to the Bluetooth name for the Sphero (Sphero-RGW) but sphero returns nil.


/

var sphero: Sphero?

/

let viewController = SpheroViewController()

viewController.joystickMoved = { angle, magnitude in

let rollForce = UInt8(magnitude * 0.5 * Double(UInt8.max))

let rollAngle = UInt16(radiansToDegrees(angle))


sphero?.roll(speed: rollForce, heading: rollAngle)

}

viewController.colorSelected = { color in

sphero?.setColor(color)

}

import PlaygroundSupport

PlaygroundPage.current.liveView = viewController

/

/

import UIKit

DispatchQueue.main.async {

/

sphero = Sphero.nearest()

/

if sphero == nil {

let alertController = UIAlertController(title: "Unable to find a Sphero device", message: "No Sphero devices were in range.", preferredStyle: .alert)

alertController.addAction(UIAlertAction(title: "OK", style: .default) { _ in

PlaygroundPage.current.finishExecution()

})

viewController.present(alertController, animated: true, completion: nil)

}

}

//#-end-hidden-code


/

/

/

/

/

/

import Foundation

private let sharedManager: SpheroManager = SpheroManager()

extension Sphero {

public class func named(_ name: String, timeout: TimeInterval = 15) -> Sphero? {

class Delegate: SpheroManagerDelegate {

var sphero: Sphero? = nil

let name: String

let timeout: TimeInterval

init(name: String, timeout: TimeInterval) {

self.name = name

self.timeout = timeout

}

func spheroManager(_ spheroManager: SpheroManager, didDiscover spheroDescription: SpheroDescription) {

guard spheroDescription.name == self.name else { return }

spheroManager.connectTo(spheroDescription)

}

func spheroManager(_ spheroManager: SpheroManager, didConnect sphero: Sphero) {

self.sphero = sphero

CFRunLoopStop(CFRunLoopGetMain())

}

func spheroManager(_ spheroManager: SpheroManager, didFailToConnect spheroDescription: SpheroDescription, error: Error?) {

self.sphero = nil

CFRunLoopStop(CFRunLoopGetMain())

}

var timer: Timer?

@objc func timerFired(_ timer: Timer) {

self.timer = nil

CFRunLoopStop(CFRunLoopGetMain())

}

func waitForConnection() {

sharedManager.scanForDevices()

timer = Timer.scheduledTimer(timeInterval: timeout, target: self, selector: #selector(Delegate.timerFired(_:)), userInfo: nil, repeats: false)

CFRunLoopRun()

sharedManager.stopScanning()

timer?.invalidate()

timer = nil

}

}

let delegate = Delegate(name: name, timeout: timeout)

sharedManager.delegate = delegate

defer { sharedManager.delegate = nil }

delegate.waitForConnection()

return delegate.sphero

}

public class func nearest(timeout: TimeInterval = 5) -> Sphero? {

class Delegate: SpheroManagerDelegate {

var sphero: Sphero? = nil

let timeout: TimeInterval

init(timeout: TimeInterval) {

self.timeout = timeout

}

var knownSpheros: [UUID: SpheroDescription] = [:]

func spheroManager(_ spheroManager: SpheroManager, didDiscover spheroDescription: SpheroDescription) {

knownSpheros[spheroDescription.identifier] = spheroDescription

}

func spheroManager(_ spheroManager: SpheroManager, didConnect sphero: Sphero) {

self.sphero = sphero

CFRunLoopStop(CFRunLoopGetMain())

}

func spheroManager(_ spheroManager: SpheroManager, didFailToConnect spheroDescription: SpheroDescription, error: Error?) {

self.sphero = nil

CFRunLoopStop(CFRunLoopGetMain())

}

var timer: Timer?

@objc func timerFired(_ timer: Timer) {

let spheroDescriptions = knownSpheros.values

guard let closestSpheroDescription = spheroDescriptions.sorted(by: { $0.rssi > $1.rssi && $0.rssi != 127 / invalid RSSI */ }).first else {

CFRunLoopStop(CFRunLoopGetMain())

return

}

sharedManager.connectTo(closestSpheroDescription)

}

func waitForConnection() {

sharedManager.scanForDevices()

timer = Timer.scheduledTimer(timeInterval: timeout, target: self, selector: #selector(Delegate.timerFired(_:)), userInfo: nil, repeats: false)

CFRunLoopRun()

sharedManager.stopScanning()

timer?.invalidate()

timer = nil

}

}

let delegate = Delegate(timeout: timeout)

sharedManager.delegate = delegate

defer { sharedManager.delegate = nil }

delegate.waitForConnection()

return delegate.sphero

}

}

Liger,


I have run into the same issue with my Sphero. I don't know if you've solved your problem, but I think I know why it's happening in my case. I have a bunch of Sphero SPRK robots for my robotics / programming workshops. These are SPRK non "+" models and not the newer SPRK+ models. The description in the Apple developer blog post mentions compatibility with SPRK+ (and BB-8). These newer models have Bluetooth LE and this is probably the cause of my connection problem.


However, the ios application "Tickle" works with older Spheros and does allow the user to see the generated Swift code. I therefore suppose it is written in Swift and assume they're using the official Sphero API. I just need to figure out how to establish the connection.


I'll post back if I find anything new.

I'm trying to resolve different kind of problem. If you have many Sphero SPRK+:s and you want to connect your Swift code with certain Sphero. Can you use somekind of ID to make it happen? The nearest Sphero is problematic, because there is lot of confusion and iPad - Sphero connection changes.

Sphero.playgroundbook Unable to Connect Sphero 2.0
 
 
Q