Skip to main content
Skip table of contents

Code

Introduction

The ClearBlade IoT Platform utilizes a microservices model powered by a Code Engine. The code engine allows for JavaScript (ES5) and has several built-in integrations to interact with your IoT assets. Following microservice practices, a new execution context is sandboxed and created upon invocation. Once the process is complete, it is destroyed.

There are four code asset types:

  • Microservice: A short-lived service expected to be completed within a fixed time (or is killed otherwise); default execution timeout is 60 seconds.

  • Stream service: A service configured to handle requests continuously with an infinite execution timeout.

  • Configuration: A library that contains a key-value object to be used as constants.

  • Library: A custom JavaScript library that can be imported into one or more code services.

Here is a code service tutorial.

Purpose

Microservices, a software development technique, allows for a high degree of modularity, scale, and parallelization – all essential for effectively building and running full-scale IoT applications.

Libraries

Libraries are reusable code sets that one or more code services can import.

Native libraries

Native libraries are available in every system and have an underlying Golang implementation. Each library is optimized for computational performance.

These libraries can be imported using requires.

Library

Description

Docs

clearblade

Interacts with collections, messaging, users, edges, and devices

View docs

log

Appends messages to a log

View docs

http

Makes outbound HTTPS requests

View docs

geo

Geospatial computation library

View docs

crypto

Creates cryptographical hashes

View docs

file_writer

Write files to host the filesystem

View docs

jsutil

JS utility library

View docs

mailer

Send an email directly from the host machine

View docs

net_cb

Net library

View docs

oauth2_lib

OAuth utility library

View docs

Custom libraries

A developer can create a custom library with custom logic.

Services

A service is a short-lived microservice expected to be completed in a finite time capped by the execution timeout field in its settings (it is killed after the timeout). The default is 60 seconds.

Lifecycle

Invocation

A service can be invoked by:

1. A REST request to the API endpoint

2. Trigger event

3. Timer event

Our SDKs can be used as a REST client to accomplish the first REST option.

Context

Each code service has a name corresponding to an autogenerated function name.

For example, a code service named analyze will have an autogenerated function like:

CODE
function analyze(req, resp) {}

This function will have two parameters, similar to Node’s Express library.

req

req is an object containing these contextual values:

Key

Description

Type

Example

userEmail

The user’s email who invoked the service

string

user@clearblade.com

params

JSON with parameters. The structure is based on the invocation type

object

{“key”:“value”}

systemKey

System key for the system in which the code service is running

string

e095a19d0b94e48dee9bff87e5fd01

systemSecret

System secret for the system in which the code service is running

string

E095A19D0B9ACD9EFA86AEEDFCC001

userToken

Invoking the user’s OAuth token

string

U1hNa7o4bEXpiE4aGhb-79MQv4…

isLogging

Whether logging is enabled

boolean

true

userid

Internal UID associated with the invoking user

string

fc8cfcea0a96ebebc7f5d4edd414

resp

resp is an object used to return values and exit the Code Service. These methods are available in the resp object:

  • resp.success

  • resp.error

  • resp.set

  • resp.status

  • resp.send

resp.success

resp.success = function (object | string){}

CODE
function analyze(req, resp) {
  var message = "Everything went well!";
  resp.success(output); // Service exits successfully with "Everything went well!"
}

resp.error

resp.error = function (object | string ){}

CODE
function analyze(req, resp) {
  var message = "It broke!";
  resp.error(error); // Service exits with failure with "It broke!"
}

resp.set This method has multiple signatures:

  • resp.set = function(string, string){}

resp.set(keyString, valueString): Adds or updates a header key to the HTTP response from a service. Example: resp.set("Content-Type", "text/html")

  • resp.set = function(object){}

  • resp.set({}): Sets the response headers to those in the map. Replaces the header object to remove any headers added with resp.set(k,v). Example:

CODE
resp.set({
  "Content-Type": "application/json",
  "ClearBlade-UserToken: req.userToken"
})

resp.status

resp.status = function(int){}

resp.status(int): Changes the HTTP response code from a service. Example: resp.status(400)

resp.send

resp.send = function(object|string){} resp.send(value): Exits the service and returns the value as the response body. value will be stringified if not already a string. value will be sent as-is and not wrapped in our typical JSON response object. Example: resp.send({valueA: "ABC-123-DEF", valueB: 123})

Exit

The service will terminate its execution with resp.success, resp.error, or resp.send. By default, if no exit method is called and the execution reaches the end, resp.success will be called to exit.

Logs

Logs record and store the service response history. Each service can store up to 25 of the latest logs with a max size of 100KB each.

Requires

A code service can import a library using the Requires feature. You can select one or more libraries to import within the code service in the Service settings.

The same library can be used for multiple code services.

Debugging

There is no native support for debugging line-by-line. It is recommended to use the log method extensively, like so:

CODE
function ServiceA(req, resp) {
  log("Something happened");
  resp.success("All done");
}

Events

Events are actions or occurrences that happen in the ClearBlade system, and it responds to them through the associated code service’s execution. ClearBlade supports timer and trigger events:

Timers

Timers provide a mechanism where a ClearBlade code service can be scheduled to execute at certain time intervals. Timers are similar to Unix cron jobs, with a similar scheduling mechanism.

Some example timer configurations:

  • Run every five minutes starting now forever

  • Run 26 times every two weeks starting Friday, May 5th, 2023

  • Run once at midnight

Triggers

Triggers are a mechanism that ties a Trigger Source action to invocate a code service. The trigger source and payload information can be accessed in the code service through the req.params object. Add log(req) to the Code Editor to log the payload information when creating a trigger.

CODE
"params": {
    "topic": "ClearBladeTopic",
    "body": "214.312",
    "userId": "8e89e2af0fc9cbeadfd6afb501",
    "trigger": "Messaging::Publish"
}

Event source

The platform publishes every event, regardless of whether the event is created programmatically in a service or externally in the console.

$trigger and $timer are custom ClearBlade topics. Using a stream service instead of a micro-service is advisable when working with $timer and $trigger topics that often fire to prevent overloading the platform.

For more information on publishing event topics, click here.

Asset

Category

Action

Topic

Messaging

Publish

Publish

$trigger/messaging/publish

Messaging

Subscriptions

Upon Subscribe

$trigger/messaging/subscribe

Messaging

Subscriptions

Upon Unsubscribe

$trigger/messaging/unsubscribe

Messaging

Connection

User Connected

$trigger/messaging/user/connected

Messaging

Connection

User Disconnected

$trigger/messaging/user/disconnected

Messaging

Connection

Device Connected

$trigger/messaging/device/connected

Messaging

Connection

Device Disconnected

$trigger/messaging/device/disconnected

Data

Table

Created

$trigger/collection/created

Data

Table

Updated

$trigger/collection/updated

Data

Table

Deleted

$trigger/collection/deleted

Data

Item

Created

$trigger/data/created

Data

Item

Updated

$trigger/data/updated

Data

Item

Deleted

$trigger/data/deleted

Data

Item

Upserted

$trigger/data/upserted

User

n/a

Created

$trigger/user/created

User

n/a

Updated

$trigger/user/updated

User

n/a

Deleted

$trigger/user/deleted

Device

n/a

Created

$trigger/device/created

Device

n/a

Updated

$trigger/device/updated

Device

n/a

Deleted

$trigger/device/deleted

Edge/Platform

Platform

Platform Started

$trigger/startconnectdisconnect/platformstarted

Edge/Platform

Platform

Platform Connected on Edge

$trigger/startconnectdisconnect/platformconnectedonedge

Edge/Platform

Platform

Platform Disconnected on Edge

$trigger/startconnectdisconnect/platformdisconnectedonedge

Edge/Platform

Edge

Edge Started

$trigger/startconnectdisconnect/edgestarted

Edge/Platform

Edge

Edge Connected on Platform

$trigger/startconnectdisconnect/edgeconnectedonplatform

Edge/Platform

Edge

Edge Disconnected on Platform

$trigger/startconnectdisconnect/edgedisconnectedonplatform

Timer

n/a

Create Timer

$timer/{timerName}

Incoming objects examples

Ensure code service-relevant permissions are set before using triggers and timers.

The following is a list of categories grouped by action types, showing structures for incoming objects:

Messaging (Publish/Subscribe/Unsubscribe):

When a publish/subscribe/unsubscribe is made to ClearBlade’s MQTT broker:

CODE
// Template
{
  "params": {
      "topic": "<message_topic>",
      "body": "<message_body>",
      "userId": "<user_id>",
      "trigger": "Messaging::<action_type>"
  }
}

CODE
// Example
{
  "params": {
      "topic": "ClearBladeTopic",
      "body": "example message",
      "userId": "8e89e2af0fc9cbeadfd6afb501",
      "trigger": "Messaging::Publish"
  }
}

Messaging (UserConnected/UserDisconnected):

When a user connects/disconnects to ClearBlade’s MQTT broker:

CODE
// Template
{
  "params": {
      "email": "<user_email>",
      "trigger": "Messaging::<action_type>"
  }
}

CODE
// Example

{
  "params": {
    "email": "example@clearblade.com",
    "trigger": "Messaging::MQTTUserDisconnected"
  }
}

Messaging (DeviceConnected/DeviceDisconnected):

When a device connects/disconnects to ClearBlade’s MQTT broker:

CODE
// Template

{
  "params": {
    "deviceName": "<device_name>",
    "trigger": "Messaging::<action_type>"
  }
}

CODE
// Example

{
  "params": {
    "deviceName": "exampleDevice",
    "trigger": "Messaging::MQTTDeviceDisconnected"
  }
}

Data-Table (CollectionCreated/CollectionUpdated/CollectionDeleted):

CODE
// Template 

{
  "params": {
    "collectionId": "<collection_id>",
    "collectionName": "<collection_name>",
    "trigger": "Data::<action_type>"
  }
}

CODE
// Example

{
  "params": {
    "collectionId": "ceafb4cf0bbaf5f4ddfbf1b48730",
    "collectionName": "ExampleCollection",
    "trigger": "Data::CollectionCreated"
  }
}

Data (ItemCreated):

CODE
// Template

{
  "params": {
    "items": [
      {
        "item_id": "<item_id>"
      }
    ],
    "collectionId": "<collection_id>",
    "collectionName": "<collection_name>",
    "trigger": "Data::ItemCreated"
  }
}

CODE
//Example

{
  "params": {
    "items": [
      {
        "item_id": "083196bf-8059-46c0-8280-38234aa73fc1"
      }
    ],
    "collectionId": "ceafb4cf0bbaf5f4ddfbf1b48730",
    "collectionName": "ExampleCollection",
    "trigger": "Data::ItemCreated"
  }
}

Data (ItemUpdated/ItemDeleted):

CODE
// Template

{
  "params": {
    "collectionId": "<collection_id>",
    "collectionName": "<collection_name>",
    "trigger": "Data::<action_type>",
    "items": [
    // First row
    // This includes all of the data from the row
      {
        "<column1_name>": <column1_data>,
        "item_id": "<item_id1>",
        "<column2_name>": <column2_data>
      }
    // A second row
      {
        "<column1_name>": <column1_data>,
        "item_id": "<item_id1>",
        "<column2_name>": <column2_data>
      }
    ]
  }
}

CODE
// Example

{
  "params": {
    "collectionId": "ceafb4cf0bbaf5f4ddfbf1b48730",
    "collectionName": "ExampleCollection",
    "trigger": "Data::ItemUpdated",
    "items": [
      {
        "hi": 6,
        "item_id": "14b12adf-4c32-4740-8461-546daa660393",
        "low": 3
      },
      {
        "hi": 7,
        "item_id": "3700fa91-ef49-41e8-9fe7-64e9ee6aa3b2",
        "low": 5
      }
    ]
  }
}

User (UserCreated):

CODE
// Template

{
  "params": {
    "user": {
      "creation_date": <date_time>,
      "email": "<user_email>",
      "user_id": "<user_id>"
    },
    "trigger": "User::UserCreated"
  }
}

CODE
//Example

{
  "params": {
    "user": {
      "creation_date": 2019-06-20T19:43:10Z,
      "email": "example@clearblade.com",
      "user_id": "9c87dfd00beefbd8a0f3cc82f0c001"
    },
    "trigger": "User::UserCreated"
  }
}

User (UserUpdated/UserDeleted):

CODE
// Template

{
  "params": {
    "query": {
      "FILTERS": [
        [
          {
            "EQ": {
              "user_id": "<user_id>"
            }
          }
        ]
      ],
      "PAGENUM": <page_number>,
      "PAGESIZE": <page_size>,
      "SELECTCOLUMNS": <columns_selected>,
      "SORT": []
    },
    // Includes all of the data from the row
    "user": {
      "email": "<user_email>"
      <column1_name>: <row_data>
      <column2_name>: <row_data>
      "user_id": "<user_id>"
    },
    "trigger": "User::<action_type>"
  }
}

CODE
// Example

{
  "params": {
    "query": {
      "FILTERS": [
        [
          {
            "EQ": {
              "user_id": "9c87dfd00beefbd8a0f3cc82f0c001"
            }
          }
        ]
      ],
      "PAGENUM": 0,
      "PAGESIZE": 0,
      "SELECTCOLUMNS": null,
      "SORT": []
    },
    "user": {
      "email": "example@clearblade.com"
      "name": "Example"
      "age": 22
      "user_id": "9c87dfd00beefbd8a0f3cc82f0c001"
    },
    "trigger": "User::UserUpdated"
  }
}

Device (DeviceCreated/DeviceDeleted):

CODE
// Template

{
  "params": {
    "trigger": "Device::<action_type>",
    "device": {
      "allow_certificate_auth": "<boolean>",
      "allow_key_auth": "<boolean>",
      "certificate": "<certificate>",
      "created_date":  "<date_time>",
      "description": "<device_description>",
      "device_key": "<device_key> :: <device_name>",
      "enabled": "<boolean>",
      "last_active_date":  "<date_time>",
      "<columnX_name>": "<columnX_data>",
      "<columnY_name>": "<columnY_data>",
      "system_key": "<system_key>",
      "type": "<device_type>"
    },
    "deviceName": "<device_name>"
  }
}

CODE
//Example 

{
  "params": {
    "trigger": "Device::DeviceCreated",
    "device": {
      "allow_certificate_auth": true,
      "allow_key_auth": true,
      "certificate": "",
      "created_date":  2019-06-20T19:43:10Z,
      "description": "",
      "device_key": "ccafb4cf0bd0dcbcadaccaf9ebba01 :: ExampleDevice",
      "enabled": true,
      "last_active_date":  2019-06-20T19:43:10Z,
      "name": "ExampleDevice",
      "state": "active",
      "system_key": "ccafb4cf0bd0dcbcadaccaf9ebba01",
      "type": "Sensor"
    },
    "deviceName": "ExampleDevice"
  }
}

Device (DeviceUpdated):

CODE
  // Template

  {
    "params": {
      "changes": {
        "description": "<device_description>"
      },
      "deviceName": "<device_name>",
      "trigger": "Device::DeviceUpdated"
    }
  }

CODE
  // Example
  
{
  "params": {
    "changes": {
      "description": "device description"
    },
    "deviceName": "example_device",
    "trigger": "Device::DeviceUpdated"
  }
}

Edge/Platform:

CODE
  // Template

  {
    "params": {
      "edgeName": "edge_name",
      "trigger": "StartConnectDisconnect::<action_type>"
    }
  }

CODE
  // Example

  {
    "params": {
      "edgeName": "example",
      "trigger": "StartConnectDisconnect::<Edge Started>"
    }
  }

Webhooks

A webhook is a mechanism that allows you to execute a code service by targeting a public endpoint. Any HTTP method, such as GET, POST, PUT, or DELETE, can be used and will result in executing the service. The URL we provide can be used by third parties to push real-time data to ClearBlade’s server. Multiple webhooks can invoke a code service and are syncable. See the tutorial.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.