Description

thsq is a node.js interface for the Thingsquare REST API. Thingsquare is a software platform for IoT systems that allow connecting low-power devices over wireless networks to read or write information. The Thingsquare REST API allow developing server-side applications that operate on the data provided by the wireless devices.

The thsq module serves a dual purpose: to help develop server-side applications that work with Thingsquare device, and to help develop frontend applications that work with Thingsquare devices.

The Thingsquare native and web apps are based on the thsq module.

Installation

Server-side installation

npm install thsq

Examples

Print out the platform names of all claimed devices for a user.

var thsq = require('thsq');
var token; // User API token, acquired via web app

thsq.init({ token: token }, function (devices) {
   var id;

   for (id in devices) {
       console.log('Device with id ' + id + ' has platform ' + thsq.devicePlatform(devices[id]));
   }
});

Print out a message when a button is pushed on a device.

var thsq = require('thsq');
var token; // User API token, acquired via web app

thsq.on('device-updated', function (device, unique, update)) {
    if (update.s && update.s.button) {
        console.log('Button changed, value is ' + update.s.button.value);
    }
});

thsq.init({ token: token });

Detect nearby devices and print out their name, if set, and platform.

var thsq = require('thsq');

thsq.on('device-nearby-seen', function (device) {
    var name, platform;

    name = 'unknown';
    if (device.s.name) {
        name = device.s.name.value;
    }

    platform = thsq.devicePlatform(device);

    console.log('Nearby device with name ' + name + ' and platform ' + platform + ' seen');
});

thsq.init();

Concepts

  • device: the representation of a wireless device and its variables.

  • variables: devices have a set of variables that are either of three types, d, s, and meta. d variables can be set either by the device or via the API, and are pushed to the device. s variables can be set either by the device or via the API, but are not pushed to the device. meta variables can not be set by neither the device nor the via the API, and contain meta information about the device. Each variable has a value and a timestamp. The values and timestamps of variables are directly accessible via the device object. For example, the value of the s variable called name is accessed via device.s.name.value and its timestamp as device.s.name.time. Variables are set with the thsq.setVariable() method.

  • unique: each device is identified by a unique identity, contained in the meta.unique device variable. The thsq module uses this unique number when referring to a device.

  • update: when the thsq module sees that a device has been updated, it will post the new variables in an update object, which contains all the new values of the variables.

  • user: a user account and its associated data. A user account has a login name, a set of devices, and a data structure that can be used to store user-specific application data.

  • token: an API token. API tokens give access for a specific user and can be used as an alternative to login/password pairs for running server-side applications.

  • Nearby device: Thingsquare devices with BLE transmitters send out a short-ranged BLE beacon that is picked up by nearby smartphones and laptops. This beacon is encrypted and changes over time. When a beacon is picked up by a smartphone or laptop, the Thingsquare system knows that the device and the smartphone or laptop are in close proximity of each other. This is typically used during installation phases, when devices are deployed.

  • Network device: when a Thingsquare device and a smartphone or laptop are on the same physical network (WiFi, Ethernet), the smartphone or laptop sends out an encrypted message over the network that the devices pick up. The Thingsquare system can then determine that the device and the smartphone or laptop are on the same network. This is used to prove proximity in a similar way as with BLE beacons, but can also be used for devices that does not have BLE beacon capabilities.

Theory of operation

The thsq module sets up and maintains a connection with its backend server. This lets applications receive notifications in the form of events when devices are updated, which relieves them from the need to poll the backend for updates.

The thsq module requires a user session. The application receives updates for devices that are claimed by the user account. A user account can be either identified with a login/password pair, which is typical for frontend applications, or an API token, which is typical for server-side applications. Starting the thsq module without a user account results in an anonymous user session to be created.

When running inside native app frontend, the thsq module is able to detect and interact with nearby devices. Nearby devices are detected via Bluetooth Low Energy (BLE) beacons.

API

Events

Server events

  • server-connected - Emitted when thsq is connected with its backend server.
  • server-disconnected - Emitted is thsq becomes disconnected from its backend server. This can be used to indicate to a user that the system is currently offline.

  • server-loading (url, method) - Emitted when thsq is currently loading data via the REST API. Can be used to indicate to a user that the system is currently doing work. The url argument contains the URL that is currently being processed and method contains the REST verb that is being used.

  • server-loading-done (url, method) - Emitted is thsq has completed a REST API transaction. The url and method arguments are the same as for the server-loading event.

User events

  • logged-in - Emitted when a user account has logged in. This can be used to indicate to a user that the user is now logged in.
  • logged-out - Emitted when a user account has logged out. This can be used to indicate to a user that the user is now logged out.

Bluetooth events

  • ble-enabled - Emitted when Bluetooth Low Energy (BLE) ability has been enabled. This can be used to indicate to a user that BLE is turned on and that nearby devices now can be detected.
  • ble-disabled (ble, location) - Emitted when BLE ability has been disabled. This can be used to indicate to a user that BLE is turned off or disabled, which will make it impossible to detect nearby devices. The ble argument is true if BLE is turned on and the location argument is true if location access is available. On most platforms, both BLE and location access is needed to be able to detect nearby devices. This can be used to display a user-friendly message telling the user to enable either BLE or location services, or both.

Device events

  • device-claimed (device, unique) - Emitted when a device has been claimed by the logged in user. The device argument contains the device data and the unique argument is the device's unique identifier.
  • device-removed (unique) - Emitted when a device has been removed from the logged in user. The user no longer has access to the device and the device's data. The unique argument is the unique identifier for the device.

  • device-updated (device, unique, update) - Emitted when a device has been updated. The device object contains all the current device variables, the unique argument is the unique identifier for the device, and update holds the variable values that were updated. An update may contain multiple variables being updated.

Nearby devices events

  • device-nearby-first-seen (device, unique, state) - Emitted when a new nearby device has been detected. The device argument contains the device information that the user has access to, the unique argument is the unique identifier for the device, and the state argument is the device's current state. The state can be fed into the thsq.deviceStateName() method to translate the number into a human-readable string.

  • device-nearby-seen (device, unique, state) - Emitted when a nearby device is seen again. This is emitted periodically when a device is nearby, after the device-nearby-first-seen event has been posted. The arguments are the same as for the device-nearby-first-seen event.

  • device-nearby-gone (device, unique) - Emitted when a nearby device has not been seen for a while and therefore is determined to be gone. The device argument contains the last known information about the device and the unique argument is the device's unique identifier.

  • device-unknown-nearby-seen (key, platform, state) - Emitted when a nearby device that has not yet registered with the backend system is seen. The key is an opaque string that the device has generated that later can be used to identify this device with a device object, once the device has registered itself with the backend system. The platform argument is the name of the device's platform and the state argument is the device's current state. The state can be fed into the thsq.deviceStateName() method to translate the number into a human-readable string.

Methods

Initialization

  • thsq.init([ options, ] callback) - initialize the thsq module. This must be done after registering event handlers. The options argument is optional and can be a combination of the options below. The callback will be called once everything is initialized and will receive the list of claimed devices by the user.

The available options are:

  • token: the user API token (default: none)
  • server: the address of the backend server to use for REST API calls (default: developer.thingsquare.com)
  • frontend: the frontend ID to use for REST API calls (default: 0ac48bf3-9fab-4bad-8455-e394808eda6b)

User methods

  • thsq.login(username, password, callback) - login with the username provided by the username argument and the password provided by the password argument. The callback will be called with a string that indicates the result:
  • login-ok: the user was successfully logged in.
  • login-fail: the user could not be logged in.

  • thsq.logout(callback) - log out the currently logged in user. The callback function callback will be called when the user has been logged out.

  • thsq.userSignup(username, password, callback) - sign up a new user with the username username and password password. The callback function callback is called with a string that indicates the result of the operation:

  • signup-ok: a new user account was successfully created.
  • signup-fail-already-exists: a user account with the same name already exists.
  • signup-fail-no-email: the username was not an email address.

  • thsq.userResendConfirmationEmail(callback) - request a new user account confirmation email to be sent. The calback function callback will be called with a string that indicates the result of the operation:

  • resend-ok: a user confirmation email was successfully sent.
  • resend-fail: the user confirmation email could not be sent.

  • thsq.userSendPasswordRecoveryEmail(username, callback) - request a password recover email to be send to the user with the user name username. The password recover email will contain a password token that later can be used as a parameter to the recoverNewPassword() function. The callback function callback will be called with a string that indicates the result of the operation:

  • recover-ok: a password reset email was successfully sent
  • recover-fail: a password reset email could not be sent.

  • thsq.recoverNewPassword(username, passwordtoken, newpassword, callback) - set a new password for the user account. The username is the username of the user, and must match the username that previously requested the password reset, the passwordtoken is a password token that was previously generated as a result of a call to userSendPasswordRecoveryEmail(), newpassword is the new password, and callback is a callback function that gets called with a string that indicates the result of the operation:

  • recover-ok: the new password was successfully set.
  • recover-fail: the new password was not set.

  • thsq.getUser(callback) - get the user data and application data associated with the user account. The callback function callback will be called with an object that represents the user information. The user object has the following fields:

  • login: the user login name.
  • data: the application user data that was previously stored with storeUserData().

  • thsq.storeUserData(data, callback) - store new user data for the user account. The argument data is an object that holds the data to be stored and the callback function callback will be called once the data has been stored, with a string that indicates the result of the operation:

  • user-data-ok: user data was successfully stored.
  • user-data-fail: user data could not be stored.
  • user-fail: no user account was logged in.

  • thsq.createAccessToken(callback) - create a new user API access token for the logged in user. The function callback will be called with a string that contains the new access token, or an error message that indicates the result of the operation:

  • user-token-fail: user token could not be created.

  • thsq.deleteAccessToken(token, callback) - delete a user API access token. The token argument should be a token that was previously created with createAccessToken(). The callback function callback will be called with a string that indicates the result of the operation:

  • user-token-deleted: the user API access token was successfully deleted.
  • user-token-fail: the user API access token could not be deleted.

Device methods

  • thsq.claimDevice(unique, callback) - claim a device for the logged in user account. This makes the device available for this user only. Any updated for the device will be received as device-updated events. The unique argument is the unique device identifier and callback is a callback function that is called to indicate the result of the operation:
  • device ID: the device was successfully claimed
  • claim-fail: the device could not be claimed
  • claim-fail-no-auth: bad user account

  • thsq.removeDevice(unique, callback) - remove the device from the user account. The user will no longer have access to its data. The unique argument is the device's unique identifier and callback is a callback function that gets called with a string that indicates the result of the operation:

  • delete-ok: the device was successfully removed
  • delete-fail: the device could not be removed

  • thsq.shareDevice(unique, username, callback) - share the device with another user. This makes the device also be available for the other user. The uniqueargument is the device's unique identifier, the username argument is the username of the user with which the device should be shared, and callback is a callback function that is called with a string that indicates the result of the operation:

  • add-user-ok: the new user was successfully added
  • claim-fail: the new user could not be added

  • thsq.getVariable(unique, type, variable, callback) - get the current value of a specified variable. The unique argument is the unique identifier for the device, the type can be either d, s, or meta, and variable is the name of the variable. The callback function will be called with an object that contains the value and time for the variable, or undefined if the variable does not exist.

  • thsq.setVariable(unique, type, variable, value, [options,] callback) - set a device variable. The unique argument is the unique identifier for the device, the type can be either d or s, variable is the name of the variable, and value is the value of the variable. The optional options argument can take one { timestamp: timestamp } value, which sets a specific timestamp, in seconds since the Unix epoch, for the variable. The callback function will be called with an object that indicates the result of the operation:

  • device-ok: the variable could be set
  • device-fail: the variable could not be set

  • thsq.deleteVariable(unique, type, variable, callback) - delete a device variable. The unique argument is the unique identifier for the device, the type can be either d or s, and variable is the name of the variable. The callback function will be called with an object that indicates the result of the operation:

  • delete-ok: the variable could be deleted
  • delete-fail: the variable could not be deleted

  • thsq.getVariableHistory(unique, type, variable, [options,] callback) - get the variable history for a specific variable. The unique argument is the unique identifier for the device, the type can be either d, s, or meta, and variable is the name of the variable. The optional options argument is used to delimit the number of history items to be returned, per below. The callback function will be called with an array of items from the data history, with each item as per below.

The possible options are:
* num: the number of elements to request in total (default: 100)
* chunksize: the maximum number of elements to retrieve per request (default: 1000)
* progress(num): a callback function that gets called on each request, with the num argument being the number of bytes read so far (default: none).

The callback will receive an array with objects with the following properties:
* value: the value of the data object. For binary data, this is a Javascript object with the field type set to the string Buffer. In this case, the data field will be an array of integers that represent the binary data value.
* time: the timestamp of the value

  • thsq.sendCommand(unique, command, callback) - send a command to the device identified by unique. The command is a string that will be sent to the device. Commands are sent in a best-effort fashion and there is no guarantee that it will be received by the device. The callback function callback will be called with a string that indicates the result of the API call, but does not indicate anything regarding the command propagation itself. Possible results are:
  • device-ok: command was sent towards the device
  • device-fail: the command could not be sent

  • thsq.getDevice(unique, callback) - get the device object for the unique identifier unique. The callback function callback will be called with the device object, or undefined if the device does not exist.

  • thsq.getDevicelist(callback) - get all devices claimed by the user. The callback function callback will receive a Javascript object that is indexed by defice ID and where each item represents a device.

  • thsq.deviceStateName(state) - returns a human-readable string representation of a nearby device's state, as given by the state argument that has previously been received received via the device-nearby-seen, device-nearby-first-seen, and device-unknown-nearby-seen events.

  • thsq.deviceEUI(device) - returns the EUI for the device in the device argument.

  • thsq.deviceId(device) - returns the device ID for the device in the device argument.

  • thsq.devicePlatform(device) - returns the platform for the device in the device argument.

Firmware update methods

  • thsq.getFirmwarelist(callback) - retreive the list of firmware updates that the user has access to. The callback function callback will be called with an array that contains items with the following structure:
  • name: the filename of the firmware file, which later can be used with the updateFirmware() method.
  • version: the version of the firmware file.
  • platform: the platform that the firmware file was compiled for.
  • info: a free-form information object contained in the firmware update's corresponding .json file. This information object typically includes:

    • fromversion: a string with information about what firmware versions that can load this firmware update
    • platforms: an object that contains:
    • from: an array of strings of platform names that can load this firmware update
    • to: an object that describes what this firmware update contains:
      • platform: the platform name that the device will have after the update.
      • name: a human-readable representation of the platform name
      • power: the power configuration (high or low) of this firmware update
    • warning: a string with a warning message to be displayed to a user, if any
    • experimental: a boolean value that indicates if this is an experimental version or not
  • thsq.startFirmwareUpdate(unique, firmwarename, callback) - start a firmware update on the device identified by the unique argument and with the firmware update file name firmwarename, which was previously retrieved from the list of available firmware updates in getFirmwarelist(). The callback function callback will receive a string that indicates the status of the operation:

  • device-ok: the firmware update was successfully started
  • firmware-fail: the firmware update could not be started

  • thsq.stopFirmwareUpdate(unique, callback) - stop an ongoing firmware update for the device identified by unique. The callback functioncallback`will receive a string that indicates the status of the operation:

  • delete-ok: the firmware update was successfully stopped
  • delete-fail: the firmware update could not be stopped

Nearby and network device methods

  • thsq.getNetworkDevices(callback) - get a list of devices that are in the same network as the user. The callback function callback will receive a Javascript object which is indexed by device IDs and where each item is a device object.

  • thsq.scanBLE(milliseconds) - tell the underlying OS to listen for BLE devices for milliseconds milliseconds. This must be called repeatedly to receive notifications of nearby devices (device-nearby-first-seen, device-nearby-seen, device-unknown-nearby-seen events).

Status methods

  • thsq.sendPing() - send a ping to the backend to check that the backend connection is alive.