This is the Neato Developer Network's official iOS SDK (Beta release). The Neato iOS SDK enables iOS apps to easily communicate with Neato connected robots and use its various features.
To boost your development, you can also check the sample application.
This is a beta version. It is subject to change without prior notice.
- Create the Neato user account via the Neato portal or from the official Neato App
- Link the robot to the user account via the official Neato App
To integrate the NeatoSDK into your Xcode project using Carthage, specify it in your Cartfile:
github "NeatoRobotics/neato-sdk-ios" ~> 0.10.0
Drag and drop the whole "NeatoSDK" folder into your Xcode project (remove the info.plist file).
The Neato SDK has 3 main roles:
- Handling OAuth authentications
- Simplifying access to users info
- Managing communication with Robots
These tasks are handled by 3 different classes: NeatoAuthentication
, NeatoRobot
and NeatoUser
The Neato SDK leverages on OAuth 2 to perform user authentication. The NeatoAuthentication
class gives you all the needed means to easily perform a login through your apps. Let’s go through the steps needed to setup an iOS App and complete a user authentication.
During the registration of your Neato App on the Neato Developer Portal you have defined a Redirect URI
. This is the URL where we redirect a user that completes a login with your Neato App Client ID. Your iOS App must be able to handle this Redirect URI using a dedicated Schema URL
. To register it, you can click on your app target on Xcode, select the info
tab under URL types
, and add a new URL that must be equal to your Redirect URI. We suggest to use something specific and unique like MyCompanyNeatoCommander://
to avoid conflicts with other applications that might have registered the same URL.
Just call the configuration method in the application:didFinishLaunchingWithOptions
function of your AppDelegate
, specifying the client ID, the scopes and the redirect URI.
[NeatoAuthentication configureWithClientID:@"YOUR_CLIENT_ID"
scopes:@[NeatoOAuthScopeControlRobots]
redirectURI:@"MyCompanyNeatoCommander://neato"];
You can choose when to present a login page to your users. The easiest way is to call the openLoginInBrowser
function from an instance of NeatoAuthentication
(This class is implemented as singleton, so you can easily access its shared instance):
[[NeatoAuthentication sharedInstance] openLoginInBrowserWithCompletion:^(NSError *error) {
if(error == nil){
// The user is logged! do something here
}else{
// oh… no :(
}
}];
The user will be presented with a login page (on Safari) and when it completes the login, it will redirect to your App thanks to the URL Schema
previously defined.
A slightly different way to present the login page is via presentLoginControllerWithCompletion
. This method pushes a new view controller into your app hierarchy. The presented controller is an instance of SFSafariViewController
that loads and presents the Neato Login page. The advantage of using this method is that your users don’t have to leave the App to perform the login.
[[NeatoAuthentication sharedInstance] presentLoginControllerWithCompletion:^(NSError * _Nullable error) {
if(error == nil){
// The user is logged! do something here
}else{
// oh… no :(
}
}];
In case you prefer to write your custom authentication flow, you can obtain the authentication URL calling the authenticationURL
method of a NeatoAuthentication
instance.
Now that the user has been redirected to the app, there is one last thing to do: Retrieving the generated access token
.
This is extremely simple since the NeatoAuthentication
class will handle it for you. Just call the handleURL
function inside application:(UIApplication *)application handleOpenURL:(NSURL *)url
of the AppDelegate
and pass the url received:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
[[NeatoAuthentication sharedInstance] handleURL:url];
return YES;
}
Now your users can perform authentication and you can get information about them.
With a NeatoUser
instance you can easily access the robot list for the currently logged in user.
NeatoUser *user = [NeatoUser new];
[user getRobotsWithCompletion:^(NSArray<NeatoRobot*> *robots, NSError * _Nonnull error) {
if(error == nil){
// do something with robots array
}
}];
and accessing user’s info:
[user getUserInfo:^(NSDictionary* userinfo, NSError * _Nullable error) {
if(!error){
NSLog(@"%@ %@ %@",
userinfo[@"first_name"],
userinfo[@"last_name"],
userinfo[@"email"]
);
}
}];
A new NeatoUser
doesn't need any configuration to be used. The authentication information will be automatically retrieved from the NeatoAuthentication
class. The only constraint before using a NeatoUser
is that a user has already completed the login process previously described.
Now that you have the robots for an authenticated user it’s time to communicate with them.
In the previous call, you've seen how easy it is to retrieve NeatoRobot
instances for your current user. Those instances are ready to receive messages from your iOS App, obviously a robot must be online to receive a message.
Each robot has a specific status that can be easily obtained using the function updateState
. When the functions completes, the robot instance properties will be filled with the current robot status, if the robot is currently offline you'll get an error with code 404
.
- (void)updateRobotState{
[self.robot updateStateWithCompletion:^(NSError * _Nonnull error) {
if(error){
// robot is offline
}else{
// Now you can read updated robot.state and robot.action… and many other robot properties.
// As example: if the robot has correctly received the cleanHouse command, `robot.action` will be `2` and `robot.state` will be `2`
}
}];
}
Important Note: An instance of the NeatoRobot
class doesn't update its state automatically. To get the updated robot state you need to call updateStateWithCompletion
anytime you want to refresh the state of a robot instance.
The robot state is automatically updated when some specific command completes (to get the list of commands, check the API documentation for the commands that respond with State Responses. Some examples of those commands are startCleaning
, stopCleaning
and pauseCleaning
).
An online robot is ready to receive commands like startCleaning
:
[self.robot startCleaningWithParameters:@{
@"category":@(RobotCleaningCategoryHouse),
@"modifier":@(RobotCleaningModifierNormal),
@"mode":@(RobotCleaningModeTurbo)}
completion:^(NSError * _Nullable error) {
if(!error){
// Robot is cleaning!
// now its state is "busy" and its action "cleaning house"
}
}];
The robot status is immediately available within the completion block of a command like startCleaning
. Accessing robot properties from there, you are sure to have the most recent robot status.
Example: You call pauseCleaning
on a robot that has a state equal toBusy
and House Cleaning
as action. Inside the completion block of pauseCleaning
(if the call succeeds without errors) robot.state
will now be equal to "Paused" and robot.action
to House Cleaning
.
When you ask to update robot state through the updateStateWithCompletion
function you also update the available commands list for the current robot state. These commands are start
, stop
, pause
, resume
and goToBase
and they are listed under the availableCommands
property (NSDictionary
) of each NeatoRobot
instance.
You can leverage on these elements to show or hide buttons in your user interface. As example, when the robot is cleaning, availableCommands
is equal to:
"start": 0,
"stop": 1,
"pause": 1,
"resume": 0,
"goToBase": 0
In this case, you might want to enable "stop" and "pause" buttons and disable "start" on your user interface as the robot is already cleaning.
To identify the services available for a robot you can rely on the availableServices
property returned by a getRobotState
call.
"availableServices":{
"houseCleaning": "basic-1",
"manualCleaning": "basic-1",
"spotCleaning": "basic-1",
"easyConnect": "basic-1",
"schedule": "basic-1",
}
A service
might have one or more versions. Take houseCleaning
as example: this service supports 3 different versions, basic-1
, minimal-2
and basic-2
. Each version might have completely different functions, or functions that require different parameters. You can read more about houseCleaning
service here.
Before sending a command to a robot you should verify the robot supports that command and, depending on the service supported, you decide which function to call and with which parameters.
The NeatoSDK uses Carthage to handle some dependencies.
Currently we are adopting specta/expecta
and OHTTPStubs
to write all the SDK tests. Those libraries are not included into the repository, hence you cannot download the SDK source and just compile but you have to pull and compile the missing frameworks.
The fastest way to go is to move into the project folder from terminal and launch the Carthage bootstrap command:
carthage bootstrap —use-submodules
This command will read the latest resolved frameworks version (you can check them into the cartfile.resolved), pull and compile the needed builds. Now you can compile and test the SDK.