NAV
cURL JavaScript

Authentication

Once you have retrieved your keys, you can verify whether your keys and the REST server work E2E by issuing the following command:

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/tasks"

Before you can start using the REST API, you must visit your profile page in the waylay application and fetch your API keys:

enter image description here

Task related calls

In waylay terminology, tasks are instantiated rules. There are two ways tasks can be instantiated:

Create a task

There are mainly 2 ways to create a task, either by specifying the rule in the request, or by specifying the template with which the task needs to be instantiated.

Create a task with rule defined in the request

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
  "sensors": [
    {
      "label": "currentWeather_1",
      "name": "currentWeather",
      "version": "1.0.3",
      "sequence": 1,
      "properties": {
        "city": "Gent, Belgium"
      },
      "position": [173, 158]
    },
    {
      "label": "isWeekend_1",
      "name": "isWeekend",
      "version": "1.0.3",
      "sequence": 1,
      "position": [179, 369]
    }
  ],
  "actuators": [
    {
      "label": "TwitterDM_1",
      "name": "sendTwitterDM",
      "version": "1.0.1",
      "properties": {
        "screenName": "pizuricv",
        "message": "Great weekend!"
      },
      "position": [600, 199]
    }
  ],
  "relations": [
    {
      "label": "ANDGate_1",
      "type": "AND",
      "position": [353, 264],
      "parentLabels": ["currentWeather_1", "isWeekend_1"],
      "combinations": [["Clear", "TRUE"]]
    }
  ],
  "triggers": [
    {
      "destinationLabel": "TwitterDM_1",
      "sourceLabel": "ANDGate_1",
      "statesTrigger": ["TRUE"],
      "invocationPolicy": 1
    }
  ],
  "notes": [
    {
      "position" : [10, 10],
      "text" : "This will send a tweet when the weather is great"
    }
  ],
  "task": {
    "type": "periodic",
    "start": true,
    "name": "Rule created on 12/8/2015, 1:38:56 PM by veselin@waylay.io",
    "pollingInterval": 900,
    "tags" : {
      "myRef" : "d8933cd4-7c70-11e9-8f9e-2a86e4085a59"
    }
  }
}' "https://sometenant.waylay.io/api/tasks"

You can create a task without a need to create a template first. In order to create a task you will need to specify the following in the request:

Sensor settings are:

Actuator settings are:

Trigger settings are:

If neither statesTrigger nor stateChangeTrigger is specified when the destination is a sensor, this means that the destination sensor will be triggered after successful execution of the source sensor.

Relations express logical gates that can be defined between sensors. There are 3 types of relations: AND, OR and GENERAL.

Relations settings are:

Note settings are:

Task settings are:

Create a task from a template

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
  "name": "test1",
  "template": "internet.json",
  "start": false,
  "type": "scheduled",
  "cron": "0/30 * * * * ?",
  "tags" : {
     "myRef" : "d8933cd4-7c70-11e9-8f9e-2a86e4085a59"
  },
  "variables" : {
    "a" : "resourceA",
    "b" : "resourceB"
  }
}' "https://sometenant.waylay.io/api/tasks"

In order to start a task from the template, you need to provide the following inputs:

Cron task

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
  "name": "test3",
  "template": "internet.json",
  "resetObservations" : false,
  "type": "scheduled",
  "cron": "0 30 * * * * ?",
  "timeZone": "Europe/Brussels"
}' "https://sometenant.waylay.io/api/tasks"

Cron specific input settings:

The schedule is expressed by one of below keys:

Periodic task

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
  "name": "test2",
  "template": "internet.json",
  "resource": "hello",
  "start": false,
  "type": "periodic",
  "frequency": 1000
}' "https://sometenant.waylay.io/api/tasks"

Periodic specific input settings:

Onetime task

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
  "name": "test3",
  "template": "internet.json",
  "resource": "hello",
  "type": "onetime"
}' "https://sometenant.waylay.io/api/tasks"

Onetime specific input settings:

Reactive task

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
  "name": "test3",
  "template": "internet.json",
  "resource": "hello",
  "type": "reactive"
}' "https://sometenant.waylay.io/api/tasks"

Reactive specific input settings:

Task tags

When creating a task, it is possible to specify tags for the task by which you can, later on, find the task back. You can specify this data in the tags object of the task settings. Any valid json is accepted. However, you can only search for task based on the toplevel tag keys with string, number or boolean values.

Create a task with sensor properties in the request

In this example, we change addresses of the Ping sensors and the resource of node Ping_2:

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
"name": "test4",
"template": "internet.json",
"resource": "hello",
"start": false,
"type": "scheduled",
"cron": "0/30 * * * * ?",
"nodes": [{
  "name": "Ping_1",
  "properties": {
    "sensor": {
      "name": "Ping",
      "version": "1.0.1",
      "label": "Ping_1",
      "requiredProperties": [
        {"address": "www.waylay.io"}
      ]
    }
  }
}, {
  "name": "Ping_2",
  "properties": {
    "resource": "newresource"
    "sensor": {
      "name": "Ping",
      "version": "1.0.1",
      "label": "Ping_2",
      "requiredProperties": [
        {"address": "sometenant.waylay.io"}
      ]
    }
  }
}]}' "https://sometenant.waylay.io/api/tasks"

You can also override node/sensor/actuator settings of the template before starting the task. These are the fields you can override:

Update a task

This allows you update the task configuration. See also the documentation on getting a task’s configuration.

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X PUT -d '{
  "name": "test1",
  "template": "internet.json",
  "resource": "hello",
  "start": false,
  "type": "scheduled",
  "cron": "0/30 * * * * ?"
}' "https://sometenant.waylay.io/api/tasks/1"

Delete a task

Delete a task

curl --user apiKey:apiSecret -X DELETE "https://sometenant.waylay.io/api/tasks/1"

Start a task

curl --user apiKey:apiSecret -X POST "https://sometenant.waylay.io/api/tasks/1/command/start"

Stop a task

curl --user apiKey:apiSecret -X POST "https://sometenant.waylay.io/api/tasks/1/command/stop"

Getting a single task by id

Get information about a single task. Response will include template definition and task’s type and settings.

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/tasks/{taskID}?format=simplified"

Query parameters:

Getting the configuration of an existing task

Using this resource you can get the original task configuration that was posted to /api/tasks. Useful if you want to:

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/tasks/{taskID}/conf?format=simplified"

Query parameters:

Query multiple tasks

This call gives first 10 tasks (default behaviour), and if you need to filter your tasks, you can use query parameters.

The optional format query parameter alows you to select the output format

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/tasks?format=simplified"

Query task by name. For instance in this call you can retrieve all tasks have name taskName.

curl --user apiKey:apiSecret \
  "https://sometenant.waylay.io/api/tasks?name=taskName"

Query to match tasks for resources with exactly the name

curl --user apiKey:apiSecret \
  "https://sometenant.waylay.io/api/tasks?resource=resource1"

Query tasks which have tag myRef equal to d8933cd4-7c70-11e9-8f9e-2a86e4085a59

curl --user apiKey:apiSecret \
  "https://sometenant.waylay.io/api/tasks?tags.myRef=d8933cd4-7c70-11e9-8f9e-2a86e4085a59"

Query tasks which have tag myRef equal to ‘building1’ or ‘building2`

curl --user apiKey:apiSecret \
  "https://sometenant.waylay.io/api/tasks?tags.myRef=building1&tags.myRef=building2"

Query tasks which have tag myRef

curl --user apiKey:apiSecret \
  "https://sometenant.waylay.io/api/tasks?tags.myRef"

You can also query for tasks.

Task querying filtering

Query parameters are:

Query parameters are combined with logical AND operator. That means that if you combine more than one parameter together you will only receive tasks that match all conditions.

If you query task by resource, input must match the resource name exactly. You can still receive more tasks in case they all have the same resource name.

If you specify a tags key multiple times, logical OR is applied for that key. If you don’t specify a value for a tags.<x> query parameter, all tasks which have a value for x in their tags are returned.

Quering tasks and paging

curl --user apiKey:apiSecret \
  "https://sometenant.waylay.io/api/tasks?startIndex=1"

Default number of returned results is 10, and you can change this using hits parameter. For instance, this call will retrieve maximum 50 tasks, starting search from the task index 50. (second page of 50-per-page results)

curl --user apiKey:apiSecret \
  "https://sometenant.waylay.io/api/tasks?startIndex=50&hits=50"

Paged result

If you want to retrieve the list as a paged list, add Accept header with value application/vnd.waylay.paged+json. The response will contain a JSON object with values, skip, limit and total fields.

To retrieve the next page, use skip+limit as startIndex and limit as hits

Get the total count of tasks

In order to retrieve the total task count, check the X-Count header of the response.

If you use the Accept: application/vnd.waylay.paged+json header, you will get the total count in the total field

In order to retrieve the total task count, check the header of the response (X-Count). In this example, we receive back 27 tasks:

curl --user apiKey:apiSecret -I "https://sometenant.waylay.io/api/tasks"
HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Wed, 07 Jan 2015 10:50:32 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
X-Count: 27
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, DELETE, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Expose-Headers: X-Count
Strict-Transport-Security: max-age=31536000; includeSubdomains

Example: get the total count of running tasks

curl --user apiKey:apiSecret -I \
  "https://sometenant.waylay.io/api/tasks?status=running"
HTTP/1.1 200 OK
Server: nginx/1.6.2
Date: Wed, 07 Jan 2015 10:50:32 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
X-Count: 5
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, DELETE, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Expose-Headers: X-Count
Strict-Transport-Security: max-age=31536000; includeSubdomains

Note on tasks and resources

Tasks and task nodes can be linked to a resource. There are some special node-related values you should know about:

As an example if you have 3 nodes with resource $ and the task has resource foo, all three node-sensors will be triggered when data is injected for resource foo.

Batch tasks operations

Posting an operation to delete task 1, 3 and 9 in batch

curl --user apiKey:apiSecret \
 -X POST "https://sometenant.waylay.io/api/batch" \
 -H "Content-Type:application/json" \
 -d '{ 
       "entity": "task",
       "action": "delete",
       "query" : {
         "ids" : [1, 3, 9]
       } 
     }'

The batch endpoint /api/batch allows you to post an operation to multiple tasks. This operation will be executed asynchronously. When posting an operation, the batch endpoint will return an url which you can use retrieve (GET) the status and results of the operation.

When posting an operation, you need to specify the action and the type of entities you want the operation to act on. You also specify a query that selects the entities and potentially (dependent on the action) also some parameters specific for the action.

For tasks, the entity type is task.

All supported actions allow to select the tasks on which they will be performed using the same query filters as querying for tasks, except the filter parameter which is not allowed because it’s not exact.

Result of above call

{
    "statusCode": 202,
    "uri": "/api/batch/afcea5a1-81df-44f6-bd34-e0b602a2cf3d",
    "entity": {
        "id": "afcea5a1-81df-44f6-bd34-e0b602a2cf3d",
        "queueTime": "2020-04-27T09:54:44.051Z",
        "operation": {
            "entity": "task",
            "action": "delete"
        }
    }
}

Result of GET https://sometenant.waylay.io/api/batch/afcea5a1-81df-44f6-bd34-e0b602a2cf3d

{
    "id": "afcea5a1-81df-44f6-bd34-e0b602a2cf3d",
    "user": "22f6dfdf-a50c-4eab-953e-8d2e56891dbe",
    "operation": {
        "entity": "task",
        "action": "remove",
        "description": "Modify tasks filtered by ids=1,3,9 REMOVE"
    },
    "queueTime": "2020-04-27T09:54:44.051Z",
    "finishedTime": "2020-04-27T09:54:44.129Z",
    "results": {
        "success": {},
        "failure": {
            "9": {
                "statusCode": 400,
                "error": "Task 9 can not be removed as it has not been stopped"
            },
            "3": {
                "statusCode": 400,
                "error": "Task 3 can not be removed as it has not been stopped"
            },
            "1": {
                "statusCode": 404,
                "error": "Task with id 1 can not found"
            }
        }
    }
}

When retrieving the status of the bulk operation (using the url from the response of the POST call), the response will contain the finishedTime when the operation has completely finished and a results object that has success and failure fields indicating (per queried entity if possible, else on a generic key) a statusCode and, for failure an error message

Below you can find the supported actions on the tasks

Delete multiple tasks

curl --user apiKey:apiSecret \
 -X POST "https://sometenant.waylay.io/api/batch" \
 -H "Content-Type:application/json" \
 -d '{ 
       "entity": "task",
       "action": "delete",
       "query" : {
         "ids" : [1, 3, 9]
       } 
     }'

Start/stop/restart/reload existing tasks

curl --user apiKey:apiSecret \
 -X POST "https://sometenant.waylay.io/api/batch" \
 -H "Content-Type:application/json" \
 -d '{
       "entity" : "task",
       "action": "stop",
       "query": {
          "status": "running",
          "resource": "myResource"
       } 
     }'

This allows to start/stop/… a bunch of tasks. Valid commands are

Plugin updates

curl --user apiKey:apiSecret \
  -X POST "https://sometenant.waylay.io/api/batch" \
  -H "Content-Type:application/json" \
  -d '{
        "entity": "task",
        "action": "updatePlugins",
        "query" : {
          "ids" : [ 4, 7, 300 ]
        },
        "actionParameters" : {
          "updates": [
            {
              "name": "myActuator",
              "fromVersion": "1.0.1",
              "toVersion": "1.0.3"
            },
            {
              "name": "mySensor",
              "fromVersion": "any",
              "toVersion": "2.0.0"
            }
          ]
        }
      }'

This will apply plugin version updates to a bunch of tasks and re-instantiate the tasks.

The actionParameters key of the POST /api/batch body must be a json object with an updates array of objects with following keys:

Modify task properties

curl --user apiKey:apiSecret \
  -X POST "https://sometenant.waylay.io/api/batch" \
  -H "Content-Type:application/json" \
  -d '{
        "entity": "tasks"
        "action": "updateProperties",
        "query": {
            "ids": [1,3,9]
        },
        "actionParameters" : {
            "nodes": [
             {
               "name" : "node1", 
               "properties" : {
                 "sensor" : {
                   "requiredProperties" : [ { "prop1" : "updatedValue"} ]
                 }
               }
             }, 
             {
               "name" : "node2",
               "properties" : {
                 "actions" : [ 
                   {
                     "label" : "actuator1",
                     "requiredProperties" : [ { "prop1" : "updatedValue"} ]
                   } 
                 ]
               }
             }
           ]
        }
      }'

This allows you to modify sensor / actuator properties while keeping the task Id.

The actionParameters object of the POST /api/batch body must contain a nodes key which is an array of objects. The format of these object is the same as the nodes array when you create a task from a template with sensor properties in the request.

Updates will be merged with any previously provided properties.

Templates

Templates are generic rules that have not yet been associated to a particular device/devices or instance. The same template can be instantiated many times as tasks, by associating device specific parameters to a specific template. This mechanism is operationally very efficient in the sense that templates only need to be developed once, but can then be instantiated many times. As an example, assume you generate a template for an appliance and in the field, you have 100k appliances deployed: then you would have one template and 100k tasks running on the waylay platform.

Create a new template

You can create a template using “simplified” logic representation (without Bayesian Network):

Template with sensors, actuators and relations

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
  "name" : "testSimpleJSON",
  "sensors": [
    {
      "label": "currentWeather_1",
      "name": "currentWeather",
      "version": "1.0.3",
      "sequence": 1,
      "properties": {
        "city": "Gent, Belgium"
      },
      "position": [173, 158]
    },
    {
      "label": "isWeekend_1",
      "name": "isWeekend",
      "version": "1.0.3",
      "sequence": 1,
      "position": [179, 369]
    }
  ],
  "actuators": [
    {
      "label": "TwitterDM_1",
      "name": "sendTwitterDM",
      "version": "1.0.1",
      "properties": {
        "screenName": "pizuricv",
        "message": "Great weekend!"
      },
      "position": [600, 199]
    }
  ],
  "relations": [
    {
      "label": "ANDGate_1",
      "type": "AND",
      "position": [353, 264],
      "parentLabels": ["currentWeather_1", "isWeekend_1"],
      "combinations": [["Clear", "TRUE"]]
    }
  ],
  "triggers": [
    {
      "destinationLabel": "TwitterDM_1",
      "sourceLabel": "ANDGate_1",
      "statesTrigger": ["TRUE"],
      "stateChangeTrigger": {
        "stateFrom": "*",
        "stateTo": "FALSE"
      },
      "invocationPolicy": 1
    }
  ],
  "notes": [
    {
      "position" : [10, 10],
      "text" : "This will send a tweet when the weather is great in Ghent"
    },
    {
      "position" : [10, 50],
      "text" : "Change the city property in the currentWeather sensor if you want the weather for another city"
    }
  ],
}' "https://sometenant.waylay.io/api/templates"

Sensor settings are:

Actuator settings are:

Trigger settings are:

If neither statesTrigger nor stateChangeTrigger is specified when the destination is a sensor, this means that the destination sensor will be triggered after successful execution of the source sensor.

Relations express logical gates that can be defined between sensors. There are 3 types of relations: AND, OR and GENERAL.

Relations settings are:

Note settings are:

Create a new template using BN

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST
-d '{
    posterior: [ {
                    nodes: [ "CONNECTION", "Ping_1", "Ping_2", "Ping_3" ],
                    function: [ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 ]
                  } ],
    nodes: [ {
                states: [ "OK", "NOK" ],
                name: "CONNECTION",
                properties: {
                    position: [ 497, 235 ],
                    comment: "created by waylay",
                    cost: 1
                },
                type: "discrete",
                mode: "nature"
              },
              {
                states: [ "Not Alive", "Alive" ],
                name: "Ping_1",
                properties: {
                  position: [ 214, 317 ],
                  comment: "created by waylay",
                  cost: 1,
                  sensor: {
                    name: "Ping",
                    version: "1.0.1",
                    label: "Ping_1",
                    requiredProperties: [ { address: "www.google.com" } ] }
                },
                type: "discrete",
                mode: "nature",
                priors: [ 0.5, 0.5 ]
              },
              {
                states: [ "Not Alive", "Alive" ],
                name: "Ping_2",
                properties: {
                  position: [ 144, 163 ],
                  comment: "created by waylay",
                  cost: 1,
                  sensor: {
                    name: "Ping",
                    version: "1.0.1",
                    label: "Ping_2",
                    requiredProperties: [ { address: "www.waylay.io" } ] }
                },
                type: "discrete",
                mode: "nature",
                priors: [ 0.5, 0.5 ]
              },
              {
                states: [ "Not Alive", "Alive" ],
                name: "Ping_3",
                properties: {
                  position: [ 359, 62 ],
                  comment: "created by waylay",
                  cost: 1,
                  sensor: {
                    name: "Ping",
                    version: "1.0.1",
                    label: "Ping_3",
                    requiredProperties: [ { address: "www.yahoo.com" } ] }
                  },
                type: "discrete",
                mode: "nature",
                priors: [ 0.5, 0.5 ]
              } ],
            name: "internet2.json"
          }' "https://sometenant.waylay.io/api/templates"

You can also create a new template that is defined as a Bayesian Network. Compared to previous call, this call allows you to define gates as a Conditional Probability Table (CPT) and also allows you to attach actuators to the likehood of a node being in a given state:

List all templates

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/templates"

Template listing filtering

Query parameters are:

All query parameters are combined with logical AND operator. That means that if you combine more than one parameter together you will only receive tasks that match all conditions.

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/templates?plugin=mySensor"

Get a template

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/templates/mytemplate?format=simplified"

Query parameters:

Will return the template properties, including the name, user and the Bayesian Network (nodes and posterior). If the template was created using simplified format, the simplified graph will be return in the simplifiedGraph property.

If the template uses multiple templated resources (using the $<variablename> format), the variablenames are returned in the variables property.

Update a template

Templates can be updated using the http PUT method. This however will not update any tasks using the template. You will need to do a batch reload operation on the tasks to accomplish that.

curl --user apiKey:apiSecret -X PUT "https://sometenant.waylay.io/api/templates/mytemplate"
-H "Content-Type:application/json" -d '{"name": "mytemplate", ...}'

Delete template

curl --user apiKey:apiSecret -X DELETE "https://sometenant.waylay.io/api/templates/internet.json"

Modifying existing templates (batch)

curl --user apiKey:apiSecret -X PATCH "https://sometenant.waylay.io/api/templates?plugin=myActuator"
-H "Content-Type:application/json" -d '{"operation": "xxx", ...}'

All the batch operations work with the same filters as querying for templates, except the filter parameter which is not allowed because it’s not exact. Some examples:

Plugin updates

This will apply plugin version updates to the templates. Optionally you combine this with a reload of all tasks instantiated from the updated templates. (reloadTasks optional boolean property that defaults to false)

The body should look like this (fromVersion can be an exact version or any)

{
  "operation": "updatePlugins",
  "updates": [
    {
      "name": "myActuator",
      "fromVersion": "1.0.1",
      "toVersion": "1.0.3"
    },
    {
      "name": "mySensor",
      "fromVersion": "1.1.0",
      "toVersion": "1.3.2"
    },
    {
      "name": "mySensor",
      "fromVersion": "any",
      "toVersion": "2.0.0"
    }
  ],
  "reloadTasks": true
}

Running a template over a batch dataset

curl --user apiKey:apiSecret -X POST "https://sometenant.waylay.io/api/templates/mytemplate/run" \
 -H "Content-Type:application/json" \
 -d '{
      "data": [
        [{
           "resource": "resource1",
           "temperature": 20
         },
         {
           "resource": "resource2",
           "co2": 100,
           "humidity": 0.4
         }],
        [{
           "resource": "resource1",
           "temperature": 21
         }
        ]
      ],
      "conf": {
        "resetObservations": false,
        "executeActuators": false,
        "resource": "resource1",
        "nodes":[
          {
            "name": "temp",
            "properties": {
              "resource":  "resource1"
            }
          }
        ]
      }
    }'

You can run a template without creating a task by providing it with groups of resource-based data to inject. This allows running a template on a backlog of data while getting the results back as a stream while they are being produced.

These are the options you can set:

The request contains 2 parts, the data which is an array of arrays and conf for providing the template overrides like you do when instantiating a task from a template. Data is provided as an array of arrays where the outer array will control the number of invocations performed on the task. The resulting stream will have as many items as this array. The inner array constitutes of all messages that should arrive at the task during that invovation. They will be mapped to nodes using the resource property.

The results are returned as a application/x-ndjson stream. Whenever an invocation ends you will receive a new json concatenated with a newline. The request will end once all data has been worked through. In case of a single invocation this response can also be parsed as application/json

{
  "nodes": {
    "alarm": {
      "state": "OK",
      "probability": 1
    },
    ...
  },
  "sensors":{
    "alarm": {
      "executed": true,
      "result": true,
      "state": "OK",
      "rawData": {},
      "log": []
    },
    ...
  },
  "actuators": {
    "alarm": {
      "sms_send": {
          "executed": true,
          "result": true,
          "message": "SMS sent",
          "log": []
        }
      },
      ...
    },
    ...
  }
}
\n
{
... second result here ...
}
\n

Running a batch dataset through a graph/BN

curl --user apiKey:apiSecret -X POST \
  https://sometenant.waylay.io/api/templates/run \
  -H 'Content-Type: application/json' \
  -d '{
    "graph": {
       "sensors": [
          {
             "label": "streamingDataSensor_1",
             "name": "streamingDataSensor",
             "version": "1.1.3",
             "dataTrigger": true,
             "resource": "$",
             "properties": {
                "parameter": "temperature",
                "threshold": "22"
             }
          }
       ],
       "actuators": [
          {
             "label": "debugDialog_1",
             "name": "debugDialog",
             "version": "1.0.5",
             "properties": {
                "message": "Temperature above threshold {{streamingDataSensor_1.threshold}} : {{streamingDataSensor_1.data.temperature}}"
             }
          }
       ],
       "triggers": [
          {
             "destinationLabel": "debugDialog_1",
             "sourceLabel": "streamingDataSensor_1",
             "invocationPolicy": 0,
             "statesTrigger": [
                "Above"
             ]
          }
       ]
    },
    "data": [
        [
            {
                "resource": "inside",
                "temperature": 20
            }
        ],
        [
            {
                "resource": "inside",
                "temperature": 30
            }
        ]
    ],
    "conf": {
        "resetObservations": false,
        "executeActuators": false,
        "resource": "inside"
    }
}'

Similarly to running a template over a batch dataset, you can also run a batch dataset through a graph or baysian network by POSTing a similar datastructure to /templates/run. Next to the data element and the optional conf element, the body should also contain a graph element which either contains a Simplified graph or a Bayesian network

The results are returned also as application/x-ndjson stream.

Discovery template

One (and only one) template can be marked as discovery template. This template will be run using the running a template over a batch dataset on any new discovered resource, i.e. the first time data is injected in the engine for this resource. This can be used to associate metadata (e.g. a resource type) to the newly discovered resource. Any actuators that are triggered in the template will be executed. A discovery template cannot have multiple templated resources.

Get the discovery template

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/discoveryTemplate"

This will return with status code 200 (OK) with the template in the body if there is a discovery template and with status code 204 (NoContent) if there is no discovery template

Set the discovery template

curl --user apiKey:apiSecret -X PUT \
   "https://sometenant.waylay.io/api/discoveryTemplate?name=<templateName>"

To mark a template as the discovery template, execute this PUT call with the template name as the name query parameter. If the call was successfull, the template templateName will be returned in the body of the response.

To unmark the discovery template (set no discovery template), execute this PUT call without specifying the name query parameter.

Plugs (Sensors, Actuators and Transformers)

Note: More about how to write plugs can be found here

Plug types

Sensors

Sensors can be considered a generalized form of input connector for the waylay platform. You can create sensors to acquire data from physical devices, databases, applications or online services. You do this by means of writing Javascript and defining metadata. Waylay provides many examples which you can use as a baseline to create your own sensors, specific to your application. On a technical level, a sensor can be considered as a function that, when called, returns the state it is in.

Actuators

Based on the outcome of the logic, you may want to take action, such as sending an alert, writing something in a database or acting on a physical system. You can take action based on any node being in a particular state, by attaching actuators to the particular node. As for the sensors, the waylay framework allows you to add your own definitions of actuators.

Transformers

Transformers can be used to transforming incoming messages, like decoding, transforming or validation.

Get list of all sensors

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/sensors"

Upload a sensor

With this API call, Waylay will store or update a new sensor for the selected Waylay tenant

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST 
-d '{
    "metadata":{
      "author":"",
      "category":"",
      "description":"A simple heads or tails sensor",
      "iconURL":"https://dummyimage.waylay.io/160&text=somefakesensor",
      "supportedStates":["heads","tails"],
      "requiredProperties":["guess"],
      "requiredRawData":[],
      "rawData":[{"parameter":"message","dataType":"string"},{"parameter":"random","dataType":"double"}]
      },
      "dependencies":{},
      "script":"const guess = waylayUtil.getProperty(options, 'guess');\nif (!guess) {\n  send(new Error('Missing property: guess'));\n}\nconst randomValue = Math.random();\nconst state = randomValue > 0.5 ? 'heads' : 'tails';\nconst correctOrIncorrect = state === guess ? 'correct' : 'incorrect';\nconst message = `You guessed ${correctOrIncorrect}! The coin flip turned out ${state}.`;\nconst value = {\n  observedState: state,\n  rawData: {\n    message: message,\n    random: randomValue\n  }\n};\nsend(null, value);\n",
    "name":"somefakesensor",
    "version":"1.0.4",
    "type":"sensor"
    }' \
  https://sometenant.waylay.io/api/sensors

note: if Waylay detects a version conflict, the API will return a HTTP 409

Delete a sensor

curl --user apiKey:apiSecret -X DELETE "https://sometenant.waylay.io/api/sensors/fakesensor"

note: if Waylay detects that this sensor is in use by a task, the API will return HTTP ERROR 400.

Execute sensor

curl --user apiKey:apiSecret -H "Content-Type:application/json" \
 -X POST \
 -d '{
    "properties": {
      "city": "Gent"
    }
  }' \
  "https://sometenant.waylay.io/api/sensors/currentWeather/versions/1.0.8"
curl --user apiKey:apiSecret -H "Content-Type:application/json" \
  -X POST \
  -d '{
    "properties": {
      "parameter": "temperature",
      "threshold": 20
    },
    "resource": "temperatureSensor",
    "streamData" : {
      "temperature" : 21,
      "timestamp": 1582988389
    }
  }' \
  "https://sometenant.waylay.io/api/sensors/streamingDataSensor"

You can specify the sensor specific input parameters in the properties of the body, like in this example where we provide city name to the weather sensor.

Optionally, you can also specify resource and streamData

If the version is omitted, the latest version of the sensor will be called.

Get list of all actuators

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/actions"

Upload an actuator

With this API call, Waylay will store or update a new actuator for the selected Waylay tenant

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST 
-d '{
    {"metadata":
      {
      "author":"",
      "category":"",
      "description":"Test actuator",
      "iconURL":"https://dummyimage.waylay.io/160&text=testactuator",
      "supportedStates":[],
      "requiredProperties":["testProperty1"],
      "requiredRawData":[]
      },
      "dependencies":{},
      "script":"var input = waylayUtil.getProperty(options, \"testProperty1\")\nconsole.log(\"input\", input)\nsend()",
      "name":"testactuator",
      "version":"1.0.4",
      "type":"actuator"}
    }' \
  https://sometenant.waylay.io/api/actions

note: if Waylay detects a version conflict, the API will return a HTTP 409

Delete an actuator

curl --user apiKey:apiSecret -X DELETE "https://sometenant.waylay.io/api/actions/fakeactuator"

note: if Waylay detects that this sensor is in use by a task, the API will return HTTP ERROR 400.

Execute actuator

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
    "properties": {
      "address": "veselin@waylay.io",
      "subject": "test",
      "message": "hello world"
    }
  }' \
  "https://sometenant.waylay.io/api/actions/Mail/versions/1.0.1"
curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
    "properties": {
      "address": "veselin@waylay.io",
      "subject": "test",
      "message": "hello world"
    }
  }' \
  "https://sometenant.waylay.io/api/actions/Mail"

You can specify the actuator specific input parameters in the properties of the body, like in this example where we provide e-mail address and message to mail actuator.

Optionally, you can also specify resource

If the version is omitted, the latest version of the actuator will be called.

Get list of all transformers

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/transformers"

Execute a specific transformer version

The payload to transform should be provided as string in properties.data

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
    "properties": {
      "data": "{\"temperature\": 123.4}",
      "resource": "resource1"
    }
  }' \
  "https://sometenant.waylay.io/api/transformers/transformTemperatureFloat/versions/1.2.1"

Execute the latest transformer version

The payload to transform should be provided as string in properties.data

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
    "properties": {
      "data": "{\"temperature\": 123.4}",
      "resource": "resource1"
    }
  }' \
  "https://sometenant.waylay.io/api/transformers/transformTemperatureFloat"

Node related calls

In waylay terminology, sensor is it attached to the node. During the runtime of the tasks, you can either inspect the node, or set the state, or execute attached sensors.

Get current states

Get current states(posteriors) and raw data for the node

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/tasks/759/nodes/Ping_1"

Get supported states

curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/tasks/759/nodes/Ping_1/states"

Set the state

curl --user apiKey:apiSecret -X POST  -d 'state=Alive' "https://sometenant.waylay.io/api/tasks/759/nodes/Ping_1"

Execute attached sensor

In this call below, we will execute Ping sensor on the task 759:

curl --user apiKey:apiSecret -X POST  -d 'operation=start' "https://sometenant.waylay.io/api/tasks/759/nodes/Ping_1"

At any time you can execute a sensor attached to the node. Please be aware that the state change will be inferred in that task right after the sensor execution.

Streaming (Real-time) data

Streaming data is data that is periodically updated and injected into a task so it can update it’s state. Injection of streaming data can happen directly to the api as shown below or by sending a message to the WaylayBroker which will then automatically be forwarded to the engine nodes linked to the same resource.

Streaming data is linked to a resource, this is a unique identifier that for example could be linked to a device or sensor. You can create as many tasks as you want that listen to this resource identifier.

Push Streaming (real-time) data

Below a direct REST call that pushes temperature:

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST -d '{
        "resource": "home_X_room1",
        "data":{
          "parameterName": "temperature",
          "value": 23.0,
          "collectedTime": 1420629467,
        }
      }' "https://sometenant.waylay.io/api/data"

If you need to process data in your sensors (like location, temperature etc.), you have two options:

In the case that streaming data is injected into the sensor that is linked to the same resource (option 1), the sensor will be executed. It can then access the injected data using waylayUtil.

When making use of this API call, you must use the resource parameter as the identifier of your device (or any other “thing”). This is the same resource identifier that is associated with the task/node when you create it. In this way, the waylay framework can link the pushed raw data and the tasks(and sensors) that require this data.

Here is the app view where you can test this feature(designer in debug mode):

Injected data view

You can also push several parameters at once, and you can as well skip most of the parameter’s attributes. For instance, with this call, we are pushing geolocation to the waylay platform, by specifying only longitude and latitude values. By default, waylay puts the collectedTime to the time the data was received:

curl --user apiKey:apiSecret -H "Content-Type:application/json" -X POST
-d '{
  "resource": "datasource",
  "data": [ {
            "parameterName": "latitude",
            "value": 51
          },
          {
            "parameterName": "longitude",
            "value": 3.73
          }
        ]
  }' "https://sometenant.waylay.io/api/data"

For related information also see the Plugin SDK documentation

Pushing states to the task

You can inject the state directly to the particular node in the task (as described before in the node section).

curl --user apiKey:apiSecret  --data "state=OPEN" -X POST https://sometenant.waylay.io/api/tasks/4/nodes/Door

For example, if you have a door with two states OPEN/CLOSED, you can push a state change from an external system to the task.