Javascript Client
Setup and Install
The Basics
Canopy (global object)
CanopyContext
CanopyRemote
CanopyUser
CanopyDevice
CanopyDeviceQuery
CanopyVariable
CanopyBarrier
Setup and Install

The Canopy Javascript Client (canopy.js) provides easy-to-use Javascript bindings for Canopy.

Currently only browser-based Javascript is supported, with Node.js support on its way.

Using a CDN
The Canopy Javascript Client (canopy.js) is hosted on our servers. You can reference the file directly with:
<script src='http://code.canopy.link/adk/js/latest/canopy.js'></script>
Downloading
Alternatively, you can download canopy.js on our Release Package Downloads page.
Cloning Source

You can clone the git repository with:

git clone https://github.com/canopy-project/canopy-js-client

The cloned directory contains the file:

canopy-js-client/canopy.js
The Basics
Object Types
The Canopy Javascript Client provides the following object types.
Canopy (global object)

    Singleton object containing the global routines exposed by this
    library.

CanopyContext

    Outermost object that holds runtime state.

CanopyRemote

    Contains settings used to connect a remote Canopy Server, along
    with connection-related state when persistent connections are
    in use.

CanopyUser

    Represents a human user who has a Canopy account on the
    configured CanopyRemote.

CanopyDevice

    Represents a Canopy-enabled "thing" that has been registered on
    the configured Remote.  This may be a physical device or a
    simulator program.

CanopyDeviceQuery

    Represents a selection of Devices that can be filtered, sorted,
    counted and paged through.

CanopyVariable

    Represents a "Cloud Variable", which is a Device property that
    is tracked and stored on the server.  Cloud Variables are
    useful for sensor data, real-time control, and Device
    configuration.

CanopyBarrier

    Used to wait for the results of an asynchronous operation.
    Also known as a "Promise".
Local vs Remote Operations

Some of the routines in this library operate on locally cached copies of data (a "local operation"), whereas other routines interact with the remote Canopy server ("a remote operation").

All local operations return immediately.

All remote operations are asynchronous by nature and return a CanopyBarrier object. The CanopyBarrier object is used to wait for and obtain the results of the operation.

Initialization

The library initialization code depends on whose credentials (if any) your program has access to. The process differs slightly if you will be using the library on behalf of a human User or on behalf of a Device.

Initializing Library with a Signed-in User

If the user has an active session on the remote Canopy server (for example if they went to https://sandbox.canopy.link and logging in), you can initialize the library with:

Canopy.initUserClient({
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        // An error occured.
        // If the user is not logged in then result==CANOPY_ERROR_NOT_LOGGED_IN
        alert(responseData.errorMsg);
        return;
    }

    // Success!
    // responseData.user contains the CanopyUser object for the
    // signed in user.
    var user = responseData.user;
    ...
});

You may want to change http://sandbox.canopy.link in the above example to your Canopy remote.

The Canopy.initUserClient() call accepts many additional parameters described in the documentation for (CanopyContext).initRemote().

Initializing Library with User Credentials using BASIC AUTH

To instead use BASIC AUTH to interact with the remote Canopy server on behalf of a User, provide ther User's credentials to Canopy.initUserClient():

Canopy.initUserClient({
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        // An error occurred.
        // If the credentials are incorrect then result==CANOPY_ERROR_BAD_CREDENTIALS
        alert(responseData.errorMsg);
        return;
    }

    // Success!
    // responseData.user contains the CanopyUser object for the
    // authenticated user.
    var user = responseData.user;
    ...
});
Initializing Library with Device Credentials using BASIC AUTH

To instead use the library on behalf of a Device, use Canopy.initDeviceClient() and provide the Device's ID and Secret Key.

Canopy.initDeviceClient({
    "auth_username" : "8f0dad00-2f45-4726-bd08-ceb0530f70c8", /* Your Device's ID */
    "auth_password" : "h/1zaP3SrYGqCE2/Ior7ZbMDNVkIExVp",     /* Your Devices' Secret Key */
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        // An error occurred.
        // If the credentials are incorrect then result==CANOPY_ERROR_BAD_CREDENTIALS
        alert(responseData.errorMsg);
        return;
    }

    // Success!
    // responseData.device contains the CanopyDevice object for the
    // authenticated device.
    var device = responseData.device;
    ...
});
Initializing Library without Credentials
Some routines, such as (CanopyRemote).createUser() do not require authentication. To use these routines, you must create a CanopyContext and CanopyRemote manually.
var ctx = Canopy.initContext();

var remote = ctx.initRemote({
    "host" : "sandbox.canopy.link"
});

// You can now call remote.createUser({...}) for example.
A Simple Example
This webpage lists the Canopy Devices that are accessible to a User.
<html>

<head>
    <title>
        Canopy Example
    </title>
    TODO JQUERY
    <script src='http://code.canopy.link/adk/js/latest/canopy.js'></script>
</head>

<body id='main'>
</body>

<script>

Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        $("#main").html("Error: " + responseData.errorMsg)
        return;
    }
    responseData.user.devices().getMany(0, 40).onDone(function(result, deviceData) {
        if (result != CANOPY_SUCCESS) {
            $("#main").html("Error: " + deviceData.errorMsg)
            return;
        }
        var i;
        for (i = 0; i < deviceData.devices.length) {
            var device = deviceData.devices[i];
            $("#main").append(device.Name() + "(" + device.ID() + "));
        }
    });
});
</script>

</html>
Canopy (global object)

The Canopy global object is a singleton object containing the global routines exposed by this library.

Canopy.initContext()

Initializes a new CanopyContext.

This is the first routine your application must call unless you are using one of the alternatives such as Canopy.initUserClient() or Canopy.initDeviceClient().

Parameters
None
Return Value
CanopyContext object
Example
Canopy.initDeviceClient()

Helper routine that initializes the library when you plan to make API requests on behalf of a Device. This routine:

  • Initializes a Context
  • Configures a Remote
  • Fetches the authenticated Device

Implemented as:

function initDeviceClient(params) {
    var ctx = Canopy.initContext();
    var remote = canopy.initRemote(params);
    return remote.getSelfDevice();
}

This is the first routine your application must call unless you are using one of the alternatives such as Canopy.initContext() or Canopy.initUserClient().

Usage
Canopy.initDeviceClient(params)
Parameters
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.device Device object representing authenticated user.
Example
Canopy.initDeviceClient({
    "auth_username" : "8f0dad00-2f45-4726-bd08-ceb0530f70c8", /* Your Device's UUID */
    "auth_password" : "h/1zaP3SrYGqCE2/Ior7ZbMDNVkIExVp",     /* Your Devices' Secret Key */
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }
    alert("Hi " + responseData.device.name());
});
Canopy.initUserClient()

Helper routine that initializes the library when you plan to make API requests on behalf of a User. This routine:

  • Initializes a Context
  • Configures a Remote
  • Fetches the authenticated User

Implemented as:

function initUserClient(params) {
    var ctx = Canopy.initContext();
    var remote = canopy.initRemote(params);
    return remote.getSelfUser();
}

This is the first routine your application must call unless you are using one of the alternatives such as Canopy.initContext() or Canopy.initDeviceClient().

Usage
Canopy.initUserClient(params)
Parameters
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.user CanopyUser object representing authenticated user.
Example
Canopy.initUserClient({
    "auth-username" : "myUsername", 
    "auth-password" : "myPassword",
    "host" : "dev02.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }
    alert("Hi " + responseData.user.username());
});
CanopyContext

A CanopyContext is an outermost object that holds runtime state for the library. You must initialize a CanopyContext before you can do anything else by calling either Canopy.initContext(), Canopy.initUserClient() or Canopy.initDeviceClient().

(CanopyContext).initRemote()
Initializes a Remote object.

Typically you can call Canopy.initUserClient() or Canopy.initDeviceClient() to initialize a Remote without calling this directly.

Usage
Canopy.initRemote(params)
Parameters

Takes a single object as its only parameter. This object may have the following members:

Parameter Required? Datatype Description
params.auth_password Optional string User's password for authentication. Required if "auth_type" is "basic" or if you plan to call (CanopyRemote).login(). Otherwise ignored. Defaults to "".
params.auth_type Optional string Type of authentication to use. Must be one of:
  • "basic" - Send BASIC AUTH credentials with each request.
  • "session" - Send session cookies with each request.
Defaults to "session".
params.auth_username Optional string Username to authenticate with if using BASIC AUTH or when .login() is called. This may be a user's username or email address (TBD: or a Device's ID). Defaults to "".
params.host Optional string Hostname or IP address of remote Canopy Server. Defaults to "sandbox.canopy.link".
params.http_port Optional integer Port to use if using HTTP. Otherwise ignored. Defaults to 80.
params.https_port Optional integer Port to use if using HTTPS. Otherwise ignored. Defaults to 443.
params.skip_cert_check Optional boolean When true, skips the validation of the Canopy Server's SSL certificate, if such skipping is possible. Note that most browsers do not allow this check to be skipped and will display a warning to the user. WARNING: This option is highly insecure and should never be used in production. Defaults to false.
params.use_http Optional boolean When true, forces the use of HTTP instead of HTTPS. WARNING: This option is highly insecure and should never be used in production. Defaults to false.
Return Value
CanopyContext object
Example
(CanopyContext).shutdown()
Shuts down a CanopyContext closing and freeing all resources that can be closed or freed. Let's face it: you are writing a web application and it is unlikely that you will ever actually call this. But we provide it here anyway for completeness.
Parameters
None
Return Value
Integer error code. CANOPY_SUCCESS on success.
Example
// Silly example:
Canopy.initContext().shutdown();
CanopyRemote
(CanopyRemote).apiBaseUrl()
Get the base URL used for making REST API requests to the remote Canopy server.

The returned value does not have a trailing slash.

It is unlikely that you will ever need to call this because the client library handles all API requests for you.

Parameters
None
Return Value
String containing URL prefix, such as "https://sandbox.canopy.link/api".
(CanopyRemote).baseUrl()
Get the base URL used for making general HTTP requests to the remote Canopy server.

The returned value does not have a trailing slash, and is typically a substring of (CanopyRemote).apiBaseUrl()'s return value.

It is unlikely that you will ever need to call this because the client library handles all API requests for you.

Parameters
None
Return Value
String containing URL prefix, such as "https://sandbox.canopy.link".
(CanopyRemote).createUser()
Create a new User on the remote Canopy server.

(TBD) On successful completion, this CanopyRemote is still not authenticated with the newly created user's credententials, so only local operations on the responseData.User will be permitted.

Usage
(CanopyRemote).createUser(params)
Parameters

Takes a single object as its only parameter. This object must have the following members:

Parameter Required? Datatype Description
params.username Required String. Must satisfy the following:
  • 5-24 characters.
  • Characters a-z, A-Z, 0-9 and underscore(_) allowed.
  • Must start with a letter.
New user's username.
params.email Required String. Must be a valid email address. New user's email address.
params.password Required String. Must satisfy the following:
  • 6-120 characters.
  • All characters allowed.
  • Case sensitive.
New user's password.
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.user CanopyUser object representing newly created user.
(CanopyRemote).getSelfDevice()
Get the CanopyDevice object corresponding to the currently authenticated device.

The currently authenticated device is the device whose credientials were supplied to (CanopyContext).initRemote() in the "auth_username" and "auth_password" parameters.

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.data CanopyDevice object representing authenticated device.
Example
var ctx = Canopy.initContext();

var remote = ctx.initRemote({
    "auth_username" : "8f0dad00-2f45-4726-bd08-ceb0530f70c8", /* Your Device's ID */
    "auth_password" : "h/1zaP3SrYGqCE2/Ior7ZbMDNVkIExVp",     /* Your Devices' Secret Key */
    "host" : "sandbox.canopy.link"
});

remote.getSelfDevice().onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }
    alert("You are a device named " + responseData.device.name());
});
(CanopyRemote).getSelfUser()
Get the CanopyUser object corresponding to the currently authenticated user.

If the Remote's "auth_type" is "session", then the currently authenticated user is the currently logged in user, if any.

If the Remote's "auth_type" is "basic", then the currently authenticated user is the user whose credientials were supplied to (CanopyContext).initRemote() in the "auth_username" and "auth_password" parameters.

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.user CanopyUser object representing authenticated user.
Example
var ctx = Canopy.initContext();

var remote = ctx.initRemote({
    "auth_type" : "basic",
    "auth_username" : "myUsername",
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
});

remote.getSelfUser().onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }
    alert("Hi " + responseData.user.username());
});
(CanopyRemote).login()
Login a User to the remote Canopy Server using the credentials supplied to (CanopyContext).initRemote() in the "auth_username" and "auth_password" parameters.

This can only used if the Remote object's "auth_type" was configured to be "session".

If successful, the response will include a session cookie that will be included in subsequent requests made by the browser to the Remote's host.

NOTE: Currently only one User can be logged in at a time and this call has a global effect. Calling this on one Remote object will have the effect of logging in that User across all other Remote objects configured with the same host and auth_type="session".

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.user CanopyUser object representing authenticated user.
Example
var ctx = Canopy.initContext();

var remote = ctx.initRemote({
    "auth_username" : "myUsername",
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
});

remote.login().onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }
    alert("Hi " + responseData.user.username());
});
(CanopyRemote).logout()
Logout the currently authenticated User on the remote Canopy Server.

This can only used if the Remote object's "auth_type" was configured to be "session".

NOTE: Currently only one User can be logged in at a time and this call has a global effect. Calling this on one Remote object will cause the user to be logged out across all other Remote objects configured with the same host and auth_type="session".

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

Example
var ctx = Canopy.initContext();

var remote = ctx.initRemote({
    "host" : "sandbox.canopy.link"
});

remote.logout().onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }
    alert("You've been logged out ");
});
(CanopyRemote).requestPasswordReset()
Requests a password reset on behalf of a user who has forgotten their password.

If the remote Canopy server has a mail service configured, then the user will recieve an email with instructions at their registered email address.

Usage
(CanopyRemote).requestPasswordReset(params)
Parameters

Takes a single object as its only parameter. This object must have the following members:

Parameter Required? Datatype Description
params.username Required String. Username or email address of user requesting password reset.
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

(CanopyRemote).resetPassword()
Resets a user's password.

To perform this operation, you need to know the "password reset code" that is encoded in the URL link in the instruction email that was sent to the user when the password reset was requested.

Usage
(CanopyRemote).resetPassword(params)
Parameters

Takes a single object as its only parameter. This object must have the following members:

Parameter Required? Datatype Description
params.username Required String. Username of user who requested the password reset.
params.password Required String. New password.
params.confirmPassword Required String. Must match params.password
params.code Required String. Password reset code that is encoded in the URL link in the instruction email that was sent to the user when the password reset was requested.
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

CanopyUser

A CanopyUser represents a human user who has a Canopy account on the configured CanopyRemote.

(CanopyUser).changePassword()
Change this CanopyUser's password.

This method communicates with the remote.

Usage
(CanopyUser).changePassword(params)
Parameters

Takes a single object as its only parameter. This object must have the following members:

Parameter Required? Datatype Description
params.oldPassword Required String User's old password.
params.newPassword Required String User's new password.
params.confirmPassword Required String Must match params.newPassword.
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

(CanopyUser).createDevices()
Create one or more device resources on the remote.

This method communicates with the remote.

Usage
(CanopyUser).createDevices(params)
Parameters

Takes a single object as its only parameter. This object must have the following members:

Parameter Required? Datatype Description
params.quantity Required Integer Number of devices to create.
params.names Required List of strings List of string names to assign the newly created devices. The list must have params.quanitity number of items.
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.devices (DEPRECATED) Array of CanopyDevice objects corresponding to the newly created devices.

Note: This is likely to change to become a DeviceQuery object in subsequent library revisions.

Example
// Initialize library and authenticate
Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert("Error: " + responseData.errorMsg);
        return;
    }

    // Create 3 new devices
    responseData.user.createDevices({
        quantity: 3,
        names: ["Toaster", "Lightbulb", "Refridgerator"]
    }).onDone(function(result, responseData) {
        if (result != CANOPY_SUCCESS) {
            alert("Error creating devices: " + responseData.errorMsg);
            return;
        }

        alert("Devices created!");
    }
}
(CanopyUser).devices()
Obtains CanopyDeviceQuery object corresponding to all devices that this CanopyUser has access to.
Paramters
None.
Return Value
CanopyDeviceQuery object corresponding to all devices that this CanopyUser has access to.
Example
Canopy.initUserClient({
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }
    responseData.user.devices().getMany(0, 10).onDone(function(result, deviceData) {
        if (result != CANOPY_SUCCESS) {
            alert(deviceData.errorMsg);
            return;
        }
        for (var i = 0; i < deviceData.devices.length; i++) {
            var device = deviceData.devices[i];
            console.log(device.name() + "(" + device.id() + ")");
        }
    });
});
(CanopyUser).email()
Get or set User's email address.

This method will get or set the cached local copy of the User's email address. To synchronize with the remote call (CanopyUser).updateFromRemote(), (CanopyUser).updateToRemote() or (CanopyUser).syncWithRemote().

When setting the User's email address this method does not perform any validation on the input. Validation occurs server-side the next time synchronization is performed.

Usage
To retrieve the User's email address:
(CanopyUser).email()

To set the User's email address:

(CanopyUser).email(newEmail)
Parameters
Optionally takes a new email address.
Parameter Required? Datatype Description
newEmail Optional string New email address for user.
Return Value
String email address.

Returns the newly-assigned email address if any.

Example
var myNewEmail = "canopytest@mailinator.com";

Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert("Error: " + responseData.errorMsg);
        return;
    }

    var user = responseData.user;
    var oldEmail = user.email();
    user.email(myNewEmail);

    // Push change to remote:
    user.updateToRemote().onDone(function(result, responseData) {
        if (result != CANOPY_SUCCESS) {
            alert("Error changing email: " + responseData.errorMsg);
            return;
        }

        alert("Email changed from " + oldEmail + " to " + newEmail);
    }
}
(CanopyUser).isValidated()
Get User's validation status, which signifies whether or not the user has confirmed their email address.

This method will get the cached local copy of the User's validation status. To synchronize with the remote call (CanopyUser).updateFromRemote() or (CanopyUser).syncWithRemote().

Parameters
None
Return Value
Boolean. true means the user has confirmed their email address, false means the user has not.
Example
Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert("Error: " + responseData.errorMsg);
        return;
    }
    if (responseData.user.isValidated()) {
        alert("You're a good person!"));
    } else {
        alert("Please check your email!"));
    }
}
(CanopyUser).remote()
Get the CanopyRemote object that this CanopyUser object uses to communicate with the remote.
Parameters
None
Return Value
CanopyRemote object
Example
Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert("Error: " + responseData.errorMsg);
        return;
    }

    var remote = canopy.user.remote();
}
(CanopyUser).syncWithRemote()
Synchronizes certain properties of this CanopyUser object with the remote Canopy server.

This is similar to calling (CanopyUser).updateToRemote() followed by (CanopyUser).updateFromRemote().

This method pushes:

and updates locally (with data from the remote):

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

(CanopyUser).updateFromRemote()
Updates certain properties of this CanopyUser object with data fetched from the remote Canopy server.

Typically (CanopyUser).syncWithRemote() should be used instead, unless you absolutely want uni-directional communication.

This method updates:

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

(CanopyUser).updateToRemote()
Pushes certain local modifications to this CanopyUser object to the remote Canopy server.

Typically (CanopyUser).syncWithRemote() should be used instead, unless you absolutely want uni-directional communication.

This method pushes:

For all other remote changes (such as device creation, password changes, etc) you must use the appropriate specific routines. See:

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

Example
var myNewEmail = "canopytest@mailinator.com";

Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert("Error: " + responseData.errorMsg);
        return;
    }

    var user = responseData.user;
    var oldEmail = user.email();
    user.email(myNewEmail);

    // Push change to remote:
    user.updateToRemote().onDone(function(result, responseData) {
        if (result != CANOPY_SUCCESS) {
            alert("Error changing email: " + responseData.errorMsg);
            return;
        }

        alert("Email changed from " + oldEmail + " to " + newEmail);
    }
}
(CanopyUser).username()
Get User's username.

This method will get the cached local copy of the User's username. To synchronize with the remote call (CanopyUser).updateFromRemote() or (CanopyUser).syncWithRemote().

Parameters
None
Return Value
String username.
Example
Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert("Error: " + responseData.errorMsg);
        return;
    }

    alert("Hello " + responseData.user.username());
}
(CanopyUser).validate()
"Validate" the user in response to them confirming their email address.

It is unlikely that you will ever need to call this.

Usage
(CanopyUser).validate(params)
Parameters

Takes a single object as its only parameter. This object must have the following members:

Parameter Required? Datatype Description
params.code Required String Activation code from the activation email that was sent to the user.
params.username Required String Username from the activation email. Must match the currently authenticated user's username.
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

CanopyDevice

A CanopyDevice represents a Canopy-enabled "thing" that has been registered on the configured Remote. This may be a physical device or a simulator program.

(CanopyDevice).id()
Get Device's Canopy ID.
Parameters
None
Return Value
String. Typically contains a type-4 UUID such as "8f0dad00-2f45-4726-bd08-ceb0530f70c8".
Example
Canopy.initDeviceClient({
    "auth_username" : "8f0dad00-2f45-4726-bd08-ceb0530f70c8", /* Your Device's UUID */
    "auth_password" : "h/1zaP3SrYGqCE2/Ior7ZbMDNVkIExVp",     /* Your Devices' Secret Key */
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert("Error: " + responseData.errorMsg);
        return;
    }

    alert(responseData.device.id());
    /* OUTPUT: 8f0dad00-2f45-4726-bd08-ceb0530f70c8 */
}
(CanopyDevice).isActive()
(Deprecated) This routine is likely to be removed or modified in future versions of the libary.

Get whether this CanopyDevice has interacted with the remote Canopy server within the past 60 seconds.

Parameters
None
Return Value
Boolean:
  • true if this CanopyDevice has interacted with the remote Canopy server within the past 60 seconds, as of the most recent synchronization with the remote Canopy server.
  • false otherwise.
(CanopyDevice).isInactive()
(Deprecated) This routine is likely to be removed or modified in future versions of the libary.

Get whether this CanopyDevice has not interacted with the remote Canopy server within the past 60 seconds.

Parameters
None
Return Value
  • false if this CanopyDevice has interacted with the remote Canopy server within the past 60 seconds, as of the most recent synchronization with the remote Canopy server.
  • true otherwise.
(CanopyDevice).isNewlyCreated()

Get whether this CanopyDevice is newly created, meaning it has never interacted with the remote Canopy server.

Parameters
None
Return Value
  • true if this CanopyDevice is newly created, meaning it has never interacted with the remote Canopy server, as of the most recent synchronization with the remote Canopy server.
  • false otherwise.
(CanopyDevice).lastActivitySecondsAgo()
(Deprecated) This routine is likely to be removed or modified in future versions of the libary.

Get the number of seconds since this device last interacted with the remote Canopy server.

The returned value will be correct as of the most recent synchronization by this CanopyDevice with the remote.

The response depends on both the remote's clock and the client's clock. If either is inaccurate, the returned value will be correspondingly incorrect.

Parameters
None
Return Value
Returns floating point number of seconds, for example 5.32 for 5.32 seconds.
(CanopyDevice).lastActivityTime()
Get the time when this device last interacted with the remote Canopy server.

The returned value will be correct as of the most recent synchronization by this CanopyDevice with the remote.

Parameters
None
Return Value
Returns a RFC3339-encoded timestamp string, such as "2015-04-15T04:32:02Z".
(CanopyDevice).locationNote()
Get or set the the user-assigned location note for this device.

This method will get or set the cached local copy of the device's location note. To synchronize with the remote call (CanopyDevice).syncWithRemote(), ((CanopyDevice).updateFromRemote() or (CanopyDevice).updateToRemote().

When setting the device's location note this method does perform any validation on the input. Validation occurs server-side the next time synchronization is performed.

Usage
To retrieve the device's location note:
(CanopyDevice).locationNote()

To set the device's location note:

(CanopyDevice).locationNote(newLocationNote)
Parameters
Optionally takes a new device location note.
Parameter Required? Datatype Description
newLocationNote Optional string New device location note.
Return Value
String device location note.

Returns the newly-assigned location note if any.

(CanopyDevice).name()
Get or set the the user-assigned name of this device.

This method will get or set the cached local copy of the device's name. To synchronize with the remote call (CanopyDevice).syncWithRemote(), ((CanopyDevice).updateFromRemote() or (CanopyDevice).updateToRemote().

When setting the device's name this method does perform any validation on the input. Validation occurs server-side the next time synchronization is performed.

Usage
To retrieve the device's name:
(CanopyDevice).name()

To set the device's name:

(CanopyDevice).name(newName)
Parameters
Optionally takes a new device name.
Parameter Required? Datatype Description
newName Optional string New device name.
Return Value
String device name.

Returns the newly-assigned name if any.

(CanopyDevice).secretKey()
Get the device's secret key, or null if the secret key is hidden.

This method will get the cached local copy of the device's secret key. To synchronize with the remote call (CanopyDevice).syncWithRemote() or ((CanopyDevice).updateFromRemote().

Parameters
None.
Return Value
String device secret key, or null if the secret key is hidden.
(CanopyDevice).syncWithRemote()
Synchronizes certain properties of this CanopyDevice object with the remote Canopy server.

This is similar to calling (CanopyDevice).updateToRemote() followed by (CanopyDevice).updateFromRemote().

This method pushes:

and updates locally (with data from the remote):

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

(CanopyDevice).updateFromRemote()
Updates certain properties of this CanopyUser object with data fetched from the remote Canopy server.

Typically (CanopyDevice).syncWithRemote() should be used instead, unless you absolutely want uni-directional communication.

This method updates this CanopyDevice object locally with data from the remote Canopy server just like (CanopyDevice).syncWithRemote(). However, it does not push any data to the remote.

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

(CanopyDevice).updateToRemote()
Pushes certain local modifications to this CanopyDevice object to the remote Canopy server.

Typically (CanopyDevice).syncWithRemote() should be used instead, unless you absolutely want uni-directional communication.

This method pushes to the remote Canopy server just like (CanopyDevice).syncWithRemote(). However, it does not update the local CanopyDevice object with data from the remote.

Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain an empty object {}.

CanopyDeviceQuery

A CanopyDeviceQuery represents a selection of Devices that can be filtered, sorted, counted, and paged through.

(CanopyDeviceQuery).count()
Obtain from the remote the total number of devices that satisfy this query.
Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.count Device object representing authenticated user.
Example
Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        $("#main").html("Error: " + responseData.errorMsg)
        return;
    }

    responseData.user.devices().count().onDone(function(result, countData) {
        if (result != CANOPY_SUCCESS) {
            $("#main").html("Error: " + countData.errorMsg)
            return;
        }

        alert("You have access to " + countData.count + " devices");
    });
})
(CanopyDeviceQuery).filter()
Obtain a new DeviceQuery representing a filtered subset of this DeviceQuery's selection. The original DeviceQuery is unmodified.
Usage
(CanopyDeviceQuery).filter(expr)
Parameters
This takes a single parameter expr.
Parameter Required? Datatype Description
expr Required string Filter expression. For example "HAS temperature && temperature >= 45" See description of filter expressions here: Device Filter Documentation
Return Value
CanopyDeviceQuery object representing the filtered selection.
Example
Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        $("#main").html("Error: " + responseData.errorMsg)
        return;
    }

    dq = responseData.user.devices();
    dq = dq.filter("HAS latitude").filter("HAS longitude");
    dq.count().onDone(function(result, countData) {
        if (result != CANOPY_SUCCESS) {
            $("#main").html("Error: " + countData.errorMsg)
            return;
        }

        alert(" " + countData.count + " devices are reporting geo coords");
    });
})
(CanopyDeviceQuery).get()
Fetch a single device from the remote, selected by either row index or ID.

This method communicates with the remote.

Usage
(CanopyDeviceQuery).get(idOrIndex)
Parameters
Takes a single parameter which must be either a:
  • String - to select by device ID, or
  • Integer - to select by row index into this CanopyDeviceQuery's selection.
Return Value
CanopyBarrier object.

On success, if the requested device is found, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.device New local CanopyDevice object representing the requested device.

If the device is not found as part of this CanopyDeviceQuery's selection, then the result parameter will be CANOPY_ERROR_NOT_FOUND.

Example
Canopy.initUserClient({
    "auth_type" : "basic",
    "auth_username" : "myUsername", 
    "auth_password" : "myPassword",
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        $("#main").html("Error: " + responseData.errorMsg)
        return;
    }

    // Get user's first device
    responseData.user.devices().get(0).onDone(function(result, deviceData) {
        if (result != CANOPY_SUCCESS) {
            $("#main").html("Error: " + countData.errorMsg)
            return;
        }

        alert("Your first device is:" + deviceData.device.name());
    });
})
(CanopyDeviceQuery).getMany()
Fetch multiple devices from the remote, selected by row index range.

A CanopyDeviceQuery represents an ordered selection of potentially large number of devices. This method fetches a subset of those devices based on the start and count parameters.

This method communicates with the remote.

Usage
(CanopyDeviceQuery).getMany(start, count)
Parameters
Takes two parameters:
Parameter Required? Datatype Description
start Required Integer Row offset to start fetching from. Use 0 to start from the beginning of the selection.
count Required Integer Maximum of devices to fetch.
Return Value
CanopyBarrier object.

On success the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Description
responseData.devices List of new local CanopyDevice objects representing the requested devices. This will be an empty list [] if no devices are found.
CanopyVariable

A CanopyVariable represents a "Cloud Variable", which is a Device property that is tracked and stored on the server. Cloud Variables are useful for sensor data, real-time control, and Device configuration.

(CanopyVariable).datatype()
Get the Cloud Variable's datatype.
Parameters
None
Return Value
String containing the Cloud Variable's datatype.

Will be one of the following:

Value Description
"bool" Boolean value
"int8" 8-bit signed integer
"int16" 16-bit signed integer
"int32" 32-bit signed integer
"uint8" 8-bit unsigned integer
"uint16" 16-bit unsigned integer
"uint32" 32-bit unsigned integer
"datetime" 64-bit unsigned integer representing microseconds from Epoch
"float32" 32-bit floating point number
"float64" 64-bit floating point number
"string" string value
TBD composite objects TBD
Example
// Initialize library and authenticate device
Canopy.initDeviceClient({
    "auth_username" : "8f0dad00-2f45-4726-bd08-ceb0530f70c8", /* Your Device's UUID */
    "auth_password" : "h/1zaP3SrYGqCE2/Ior7ZbMDNVkIExVp",     /* Your Devices' Secret Key */
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }

    // Loop over cloud variables and say their datatypes
    var cloudVars = responseData.device.vars();
    for (var i = 0; i < cloudVars.length; i++) {
        alert("Cloud Var " + cloudVars[i].name() + "has datatype " + cloudVars[i].datatype());
    }
});
(CanopyVariable).device()
Get the CanopyDevice object that this Cloud Variable belongs to.
Parameters
None
Return Value
Returns a CanopyDevice object.
Example
// Initialize library and authenticate device
Canopy.initDeviceClient({
    "auth_username" : "8f0dad00-2f45-4726-bd08-ceb0530f70c8", /* Your Device's UUID */
    "auth_password" : "h/1zaP3SrYGqCE2/Ior7ZbMDNVkIExVp",     /* Your Devices' Secret Key */
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }

    // Loop over cloud variables and confirm their device object is
    // correct.
    var cloudVars = responseData.device.vars();
    for (var i = 0; i < cloudVars.length; i++) {
        if (cloudVars[i].device() != responseData.device) {
            // This will never happen
            alert("Something is seriously broken!");
        }
    }
});
(CanopyVariable).direction()
Get the Cloud Variable's direction.
Parameters
None
Return Value
Returns a string direction. The direction determines who can modify the value:
Direction Who Can Modify Value
"out" Can only be set by the device that the cloud variable belongs to.
"in" Can only be set by users and other devices (i.e. not the device that the cloud variable belongs to).
"inout" Anyone with access to the cloud variable can set it.
Example
// Initialize library and authenticate device
Canopy.initDeviceClient({
    "auth_username" : "8f0dad00-2f45-4726-bd08-ceb0530f70c8", /* Your Device's UUID */
    "auth_password" : "h/1zaP3SrYGqCE2/Ior7ZbMDNVkIExVp",     /* Your Devices' Secret Key */
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }

    // Loop over cloud variables and say their directions
    var cloudVars = responseData.device.vars();
    for (var i = 0; i < cloudVars.length; i++) {
        alert("Cloud Var " + cloudVars[i].name() + "has direction " + cloudVars[i].direction());
    }
});
(CanopyVariable).historicData()
Fetch historic data for a Cloud Variable.
Usage
(CanopyVariable).historicData(startTime, endTime)
Parameters
None
Return Value
CanopyBarrier object.

On success, the responseData parameter of the Barrier's .onDone() callback will contain the following fields:

Field Datatype Description
responseData.samples List of Objects:

[{
    t : "2015-04-15T04:32:02Z",
    v : 143.2
}, ...]

List of sample data points. The "t" field of each object contains the RFC3339-encoded timestamp when the sample was reported to the remote. The "v" field contains the sample's value at that time. The value's datatype is determined by the Cloud Variable's datatype.
Example
// Initialize library and authenticate device
Canopy.initDeviceClient({
    "auth_username" : "8f0dad00-2f45-4726-bd08-ceb0530f70c8", /* Your Device's UUID */
    "auth_password" : "h/1zaP3SrYGqCE2/Ior7ZbMDNVkIExVp",     /* Your Devices' Secret Key */
    "host" : "sandbox.canopy.link"
}).onDone(function(result, responseData) {
    if (result != CANOPY_SUCCESS) {
        alert(responseData.errorMsg);
        return;
    }

    // Get temperature cloud variable, if any.
    var temperature = responseData.device.varByName("temperature");
    if (!temperature) {
        console.log("This device does not have cloud var \"temperature\"");
        return;
    }

    // Fetch historic temperature data for this device
    temperature.historicData().onDone(function(result, historicData) {
        if (result != CANOPY_SUCCESS) {
            console.log("Error: " + historicData.errorMsg);
            return;
        }

        // Dump all samples:
        for (var i = 0; i < historicData.samples.length; i++) {
            console.log("Time: " + historicData.samples[i].t);
            console.log("Value: " + historicData.samples[i].v);
        }
    });
});
(CanopyVariable).isModified()
Get whether this Cloud Variable's value has been set locally since the last synchronization with the remote.

This method will return true if the most recent call to (CloudVariable).value(newValue) is later than the most recent successful response from a (CanopyDevice).syncWithRemote() or (CanopyDevice).updateFromRemote() call for this Cloud Variable's Device.

This method returns true even if the newValue passed to (CloudVariable).value(newValue) matches the Cloud Variable's previous value. That is to say, the value does not have to actually change for it to be considered "modified".

Parameters
None
Return Value
Returns a boolean.
  • true - This Cloud Variable has been set locally since the last synchronization with the remote.
  • false - Otherwise.
(CanopyVariable).lastRemoteUpdateTime()
Get the time when this Cloud Variable was last changed on the remote.

The returned value will be correct as of the most recent synchronization with the remote.

Parameters
None
Return Value
Returns a RFC3339-encoded timestamp string, such as "2015-04-15T04:32:02Z".
(CanopyVariable).lastRemoteValue()
Get this Cloud Variable's value as of the most recent synchronization with the remote.
Parameters
None
Return Value
Returns the Cloud Variable's value, or null if the Cloud Variable has never been set on the remote.

The datatype of the return value depends on the Cloud Variable's datatype.

(CanopyVariable).lastRemoteUpdateSecondsAgo()
Get the number of seconds since this Cloud Variable was last changed on the remote.

The returned value will be correct as of the most recent synchronization with the remote.

The response depends on both the remote's clock and the client's clock. If either is inaccurate, the returned value will be correspondingly incorrect.

Parameters
None
Return Value
Returns floating point number of seconds, for example 5.32 for 5.32 seconds.
(CanopyVariable).name()
Get the name of this Cloud Variable.
Parameters
None
Return Value
String name of this Cloud Variable.
(CanopyVariable).value()
Get or set the Cloud Variable's value.

This method will get or set the cached local copy of the Cloud Variable's value. To synchronize with the remote call (CanopyDevice).updateFromRemote(), (CanopyDevice).updateToRemote() or (CanopyDevice).syncWithRemote().

Usage
To retrieve the Cloud Variable's value:
(CanopyVariable).value()

To set the Cloud Variable's value:

(CanopyVariable).value(newValue)
CanopyBarrier

A CanopyBarrier is used to wait for the results of an asynchronous operation. Also known as a "Promise".

(CanopyBarrier).onDone()

Register a callback that will be triggered when the results of an asynchronous operation are complete.

Usage
(CanopyBarrier).onDone(function(result, responseData) { ... })
Parameters

Takes a single callback function as a parameter. This callback must accept two parameters:

Parameter To Callback Datatype Description
result Integer (error enum value) CANOPY_SUCCESS if the operation completed successful.

CANOPY_ERROR_xxx value if an error occurred.

responseData Object Contents varies depending on which request was made and whether or not there was an error. Details are provided in each asynchronous method's documentation.
CanopyBarrier Error Response

If an error occurs while carrying out an asynchronous operation, the barrier's onDone callback will be called as follows:

The result parameter will contain a CANOPY_ERROR_xxx value, such as CANOPY_ERROR_BAD_CREDENTIALS.

The responseData parameter will contain the following fields:

Field Datatype Description
responseData.errorMsg String Human-readable description of the error.