Connections

Also see Connecting A Robot for the consumer connection experience.

Overview

The Sphero Robot SDKs all connect to robots using the same DiscoveryAgent concept. In order to connect, simply register for robot connection state change notifications and start Discovery. If your App is specific to one type of robot (Sphero or Ollie), use the DiscoveryAgent specific to the protocol.

Import Sphero Robot SDK

#import <RobotKit/RobotKit.h>
#import <RobotUIKit/RobotUIKit.h> // optional UI classes

This should be in your bridging header. If you don't have a bridging header see Getting Started

#import <RobotKit/RobotKit.h>
import com.orbotix.le.DiscoveryAgentLE;
import com.orbotix.le.RobotLE;
import com.orbotix.common.RobotChangedStateListener;

Register for Connection State Changes

[[RKRobotDiscoveryAgent sharedAgent] addNotificationObserver:self 
                                        selector:@selector(handleRobotStateChangeNotification:)];
RKRobotDiscoveryAgent.sharedAgent().addNotificationObserver(self, selector: "handleRobotStateChangeNotification:")
DualStackDiscoveryAgent.getInstance().addRobotStateListenernew( RobotChangedStateListener() {
    @Override
    public void handleRobotChangedState( Robot robot, RobotChangedStateNotificationType type ) {

    }
});

Note that DualStackDiscoveryAgent supports both Bluetooth Classic and Bluetooth LE. DiscoveryAgentClassic can be used if your app only needs to support Sphero, or DiscoveryAgentLE if your application only needs to support Ollie.

Handle the Connection State Change
- (void)handleRobotStateChangeNotification:(RKRobotChangedStateNotification *)n {
    switch(n.type) {
        case RKRobotOnline: // robot is online and ready for commands
            break;
        case RKRobotDisconnected:
            break;
        case RKRobotFailedConnect:
            break;
    }
}
func handleRobotStateChangeNotification(notification: RKRobotChangedStateNotification) {
    switch (notification.type) {
        case .Online:
            break
        case .Disconnected:
            break
        case .FailedConnect:
            break
        default:
    }
}
@Override
public void handleRobotChangedState(Robot robot, RobotChangedStateNotificationType type) {
    switch (type) {
        case Online:
            break;
        case Disconnected:
            break;
    }
}
// changedState

Start Discovery

Warning: Discovering devices uses substantial resources. Do not leave discovery running when you are not about to connect to a robot.

- (void)appDidBecomeActive:(NSNotification *)n {
  [RKRobotDiscoveryAgent startDiscovery];
}
func appDidBecomeActive(n: NSNotification) {
    RKRobotDiscoveryAgent.startDiscovery()
}
@Override
protected void onStart() {
    super.onStart();
    // This line assumes that this object is a Context
    try {
        DualStackDiscoveryAgent.getInstance().startDiscovery(this);
    } catch( DiscoveryException e ) {
        //handle exception
    }
}
// todo

Caching a Robot

When robot connects, you will get an object with the type id<RKRobotBase>. This protocol encompasses the basics of a Bluetooth robot, but does not do much robot-specific functionality. To get some neat built-in functionality, we will create a RKConvenienceRobot object when we receive the connected notification. The classes RKOllie and RKSphero provide even more functionality specific to each of the robots and are subclasses of RKConvenienceRobot.

// AppDelegate.h
#import <RobotKit/RobotKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow* window;
@property (strong, nonatomic) id<RKRobotBase> robot;

@end
// AppDelegate.mm
-(void) handleRobotStateChange:(RKRobotChangedStateNotification *) n{
    switch(n.type){
        case RKRobotOnline:
            _robot = n.robot;
            break;
        case RKRobotDisconnected:
            break;
    }
}

When robot connects, you will get an object with the type RKRobotBase. This protocol encompasses the basics of a Bluetooth robot, but does not do much robot-specific functionality. To get some neat built-in functionality, we will create a RKConvenienceRobot object when we receive the connected notification. The classes RKOllie and RKSphero provide even more functionality specific to each of the robots and are subclasses of RKConvenienceRobot.

var robot: RKConvenienceRobot!

{...}

func handleRobotStateChangeNotification(notification: RKRobotChangedStateNotification) {
    switch (notification.type) {
        case .Online:
            robot = RKConvenienceRobot(robot: notification.robot)
            break
        case .Disconnected:
            break
        default:
    }
}

When robot connects, you will get an object with the type Robot. This protocol encompasses the basics of a Bluetooth robot, but does not do much robot-specific functionality. To get some neat built-in functionality, we will create a ConvenienceRobot object when we receive the connected notification. The classes Ollie and Sphero provide even more functionality specific to each of the robots and are subclasses of ConvenienceRobot.

private ConvenienceRobot mRobot;

{...}

@Override
public void handleRobotChangedState(Robot robot, RobotChangedStateNotificationType type) {
    switch (type) {
        case Online:
        // Bluetooth Classic (Sphero)
        if (robot instanceof RobotClassic) {
            mRobot = new Sphero(robot);
        }
        // Bluetooth LE (Ollie)
        if (robot instanceof RobotLE) {
            mRobot = new Ollie(robot);
        }
        break;
    }
}
// changedState

Disconnecting a Robot

When you are done with the robot, it is important to disconnect it so that the next application can use it. There are two methods to accomplish this:

The easiest way to disconnect any of the Sphero Robots is to 'sleep' the robot. There is a sleep function on both the convenience robot object and on the robot base object.

[_robot sleep];  // sleeps and disconnects a robot.
robot.sleep() // sleeps and disconnects a robot.

Convenience Robot Method

If a RKConvenienceRobot is available, disconnection is accomplished by calling the method - [RKConvenienceRobot disconnect] and the robot will take care of the rest for you.

@property (strong, nonatomic) RKConvenienceRobot *robot; // Assume that this is set when the robot connects

{...}

- (void)disconnectRobot {
    [_robot disconnect];
}
var robot: RKConvenienceRobot!  // Assume that this is set when the robot connects

{...}

func disconnectRobot() {
    robot.disconnect()
}
private ConvenienceRobot mRobot; // Assume that this is set when the robot connects

{...}

@Override
protected void onStop() {
    if( mRobot != null )
        mRobot.disconnect();
    super.onStop();
}
// onStop

Robot Method

If you have a id<RKRobotBase>, disconnection is a bit more manual. RKRobotLE objects need to have - [RKRobotLE sleep] called on them as to avoid leaving the processor awake while the robot is not connected. Disconnection will be automatic from the sleep. RKRobotClassic objects can just have - [RKRobotClassic disconnect] called on them.

@property (strong, nonatomic) id<RKRobotBase> robot; // Assume this is set when the robot connects

{...}

- (void)disconnectRobot {
    if ([_robot isKindOfClass:[RKRobotLE class]]) {
        [_robot sleep];
    }
    else if ([_robot isKindOfClass:[RKRobotClassic class]]) {
        [_robot disconnect];
    }
}

If you have a RKRobotBase, disconnection is a bit more manual. RKRobotLE objects need to have sleep() called on them as to avoid leaving the processor awake while the robot is not connected. Disconnection will be automatic from the sleep. RKRobotClassic objects can just have disconnect() called on them.

var robot: RKRobotBase! // Assume this is set when the robot connects

{...}

func disconnectRobot() {
    if (robot.isKindOfClass(RKRobotLE)) {
        robot.sleep()
    } else if (robot.isKindOfClass(RKRobotClass)) {
        robot.disconnect()
    }
}

If you have a Robot, disconnection is a bit more manual. RobotLE objects need to have sleep() called on them as to avoid leaving the processor awake while the robot is not connected. Disconnection will be automatic from the sleep. RobotClassic objects can just have disconnect() called on them.

private Robot mRobot;

{...}

@Override
public void onStop() {
    if (mRobot instanceof RobotLE) {
        mRobot.sleep();
    }
    else if (mRobot instanceof RobotClassic) {
        mRobot.disconnect();
    }
    super.onStop();
}
// Coming soon