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:
In waylay terminology, tasks are instantiated rules. There are two ways tasks can be instantiated:
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.
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:
sensors
: list of sensors with required propertiesactuators
: list of actuators with required propertiesrelations
: list of relations(gates) between sensorstriggers
: list of conditions under which actuators/sensors get executed.notes
: list of notes as explanation for userstask
: task related settingsSensor settings are:
label
: node labelname
: sensor/actuator nameversion
position
: [X,Y] coordinates, e.g. [245, 205]
properties
: key-value object of required propertiesresource
: resourcesequence
: sequence number - applicable only for sensors, if omitted default is 1dataTrigger
: Boolean to indicate if sensor needs to be executed if data for resource
is receivedtickTrigger
: Boolean to indicate if sensor needs to be executed on task tickevictionTime
: time (in milliseconds) after which sensor goes back to default statepollingPeriod
: time (in milliseconds) to give sensor it’s own tickActuator settings are:
label
: node labelname
: sensor/actuator nameversion
position
: [X,Y] coordinates, e.g. [245, 205]
properties
: key-value object of required propertiesTrigger settings are:
sourceLabel
: label of the sensor / relationdestinationLabel
: label of the actuator / sensorinvocationPolicy
: time (in seconds) that defines how long to wait before firing the same actuator again, even if the condition is met.statesTrigger
: array of states under which to fire the actuatorstateChangeTrigger
: object containing stateFrom
and stateTo
which can be a specific state or *
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:
label
: gate label e.g. “ANDGate_1”type
: AND
, OR
or GENERAL
parentLabels
: array of labels of sensors that are attached to this relationcombinations
: array of arrays, such as [["Above", "Above"], ["Below", "Below"]]
. Only GENERAL gate will have more than one array of combinationsposition
: [X,Y] coordinates, e.g. [245, 205]
Note settings are:
position
: [X,Y] coordinates, e.g. [10, 10]
text
: the text of the info boxTask settings are:
name
start
flag to start a task, default yes
type
: onetime
, scheduled
, reactive
or periodic
resetObservations
: whether to clear observation before next invocation (default true
)parallel
: whether to run sensors in parallel or sequentially (default true
)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:
name
: task nametemplate
: template nameresource
: resource name orvariables
: associate multiple resources to the task (json object/hashmap where the key is the variablename that is referenced in the template with $<variablename>
)start
: boolean to indicate whether task must be started after creationresetObservations
: whether to clear observation before next invocation (default true
)parallel
: whether to run sensors in parallel or sequentially (default true
)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:
type
: scheduled
timeZone
: optional identifier of the time zone (e.g. “America/Los_Angeles” or “GMT-8:00”) in which the schedule expression is to be interpretedThe schedule is expressed by one of below keys:
cron
: cron expression as defined in Cron formatrrule
: rrule expression as defined in RFC5545 3.8.5.3curl --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:
type
: periodic
frequency
: polling frequency in millisecondscurl --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:
type
: onetime
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:
type
: reactive
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.
In this example, we change addresses of the
Ping
sensors and the resource of nodePing_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:
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
curl --user apiKey:apiSecret -X DELETE "https://sometenant.waylay.io/api/tasks/1"
curl --user apiKey:apiSecret -X POST "https://sometenant.waylay.io/api/tasks/1/command/start"
curl --user apiKey:apiSecret -X POST "https://sometenant.waylay.io/api/tasks/1/command/stop"
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:
format
(optional, bn
(default) or simplified
) Lets you select the template format to returnUsing 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:
format
(optional, bn
(default) or simplified
) Lets you select the template format to returnThis 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
bn
(default)simplified
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.
Query parameters are:
filter
(fuzzy search on multiple properties)name
resource
type
(scheduled, periodic, …)status
(running, stopped, failed)ids
(comma separated string)id
(can be added multiple times)plugin
(mySensor
or mySensor:1.0.3
)template
(use 'null'
for selecting tasks that don’t have a template)tags.<x>
(can be added multiple times)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"
startIndex
hits
(default 10, max. 100)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
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
Tasks and task nodes can be linked to a resource
. There are some special node-related values you should know about:
$
- resource name will be inherited from the task resource name$<variablename>
- node will be linked to the resource specified at task startup in the variable variablename
$taskId
- resource name will be inherited from the task IDAs 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
.
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
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]
}
}'
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
start
stop
restart
reload
(This is mainly for applying template updates to existing tasks)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:
name
: name of the plugfromVersion
: the version of the plug (can be an exact version or any)toVersion
: the (exact) version of the plug to upgrade tocurl --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 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.
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"
sensors
: list of sensors with required propertiesactuators
: list of actuators with required propertiesrelations
: list of relations(gates) between sensorstriggers
: list of conditions under which actuators get executed.notes
: list of notes as explanation for usersname
: the name of the templateSensor settings are:
label
: node labelname
: sensor/actuator nameversion
position
: [X,Y] coordinates, e.g. [245, 205]
properties
: key-value object of required propertiesresource
: resource (can be specified using $
or $<variablename>
)sequence
: sequence number - applicable only for sensors, if omitted default is 1dataTrigger
: Boolean to indicate if sensor needs to be executed if data for resource
is receivedtickTrigger
: Boolean to indicate if sensor needs to be executed on task tickevictionTime
: time (in milliseconds) after which sensor goes back to default statepollingPeriod
: time (in milliseconds) to give sensor it’s own tickActuator settings are:
label
: node labelname
: sensor/actuator nameversion
position
: [X,Y] coordinates, e.g. [245, 205]
properties
: key-value object of required propertiesTrigger settings are:
sourceLabel
: label of the sensor / relationdestinationLabel
: label of the actuator / sensorinvocationPolicy
: time (in seconds) that defines how long to wait before firing the same actuator again, even if the condition is met.statesTrigger
: array of states under which to fire the actuatorstateChangeTrigger
: object containing stateFrom
and stateTo
which can be a specific state or *
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:
label
: gate label e.g. “ANDGate_1”type
: AND
, OR
or GENERAL
parentLabels
: array of labels of sensors that are attached to this relationcombinations
: array of arrays, such as [["Above", "Above"], ["Below", "Below"]]
. Only GENERAL gate will have more than one array of combinationsposition
: [X,Y] coordinates, e.g. [245, 205]
Note settings are:
position
: [X,Y] coordinates, e.g. [10, 10]
text
: the text of the info boxcurl --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:
curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/templates"
Query parameters are:
mySensor
or mySensor:1.0.3
)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"
curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/templates/mytemplate?format=simplified"
Query parameters:
format
(optional, bn
(default) or simplified
) Lets you select the template format to returnWill 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 variablename
s are returned in the variables
property.
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", ...}'
curl --user apiKey:apiSecret -X DELETE "https://sometenant.waylay.io/api/templates/internet.json"
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:
/templates?ids=mytemplate,myothertemplate
(specific templates)/templates?plugin=mySensor
(mySensor any version)/templates?plugin=mySensor%3A1.0.1
(mySensor 1.0.1)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
}
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:
resetObservations
(default true
) reset observations before injecting dataexecuteActuators
(default false
) by default we do not execute actuators, set this to true
if you want actuation to happen.resource
(optional) sets the global resource for the running of the template or variables
if the template has multiple templated resources. Relates to note on tasks and resources.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
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 POST
ing 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.
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.
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
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.
Note: More about how to write plugs can be found here
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.
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 can be used to transforming incoming messages, like decoding, transforming or validation.
curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/sensors"
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
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.
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.
curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/actions"
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
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.
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.
curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/transformers"
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"
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"
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(posteriors) and raw data for the node
curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/tasks/759/nodes/Ping_1"
curl --user apiKey:apiSecret "https://sometenant.waylay.io/api/tasks/759/nodes/Ping_1/states"
curl --user apiKey:apiSecret -X POST -d 'state=Alive' "https://sometenant.waylay.io/api/tasks/759/nodes/Ping_1"
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 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.
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:
streamingDataSensor
sensor)waylayGetLatestItem
sensor)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):
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
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.