Resource types provide a link to set of tasks that can run on the group of resources. It can also be used to define a metrics interface (which is linked to the sensory information) and a command interface which allows you to abstract actual actuators implementation (see later). With most of the IoT platforms, you would find a ResourceType called a “template”, since they refer to this sort of modelling as a way to model different device categories using the same JSON template. In our case, we use a template in the rules context. More importantly, our abstraction allows to model both “object templating” together with rules associations, as described further.
The provisioning API allows you to associate metadata with a resource. Resources are either discovered by Waylay (as soon as data is pushed towards Waylay Broker), or you can create them using REST call.
Next to the resource CRUD related calls, Waylay allows you to Type entities, and let you link resource to a type using metadata (please see example below). As soon as a resource is linked to a resource type, all metadata values of that type are inherited by that resource. Resource can still overwrite any specific attribute in its metadata model.
Waylay also allows you to associate a resource to a parent resource (by setting the parentId
). Using this feature, you can organise your resources in a hierarchical structure.
Currently, Waylay does NOT check for cyclic references. Also parentId
can NOT be inherited from the linked resource type.
Let’s see how api works in practice:
In this example, we create a resource mydevice_id and add two additional attributes: customer and label:
curl --user apiKey:apiSecret \
-X POST "https://tenant.waylay.io/api/resources" \
-H "Content-Type: application/json" \
-d '{
"id": "mydevice_id",
"customer": "tenant1",
"label": "helloWorld"
}'
Example of creating a resource and immediately linking it to the resource type:
curl --user apiKey:apiSecret \
-X POST "https://tenant.waylay.io/api/resources" \
-H "Content-Type: application/json" \
-d '{
"id": "myDevice_id",
"resourceTypeId": "resourceType_Id",
"customer": "tenant1",
"name": "helloWorld"
}'
Reserved keywords for metadata:
Symbol | Type | Meaning |
---|---|---|
resourceTypeId |
optional[String] | id of the linked resource type |
parentId |
optional[String] | id of the parent resource |
name |
optional[String] | name of the resource, like testresource |
alias |
optional[String] | alias for the name of the resource, like testresource-alias |
owner |
optional[String] | owner of the resource |
provider |
optional[String] | LoRA, Sigfox.. |
providerId |
optional[String] | provder_123 |
customer |
optional[String] | customer tenant name |
tags |
optional[List[String]] | (sequence of strings) // example [“Proximus”, “myTag”, “locationC”] |
location |
optional [Location type] | see below |
firmware |
optional[String] | 1.2_1234 |
lastMessageTimestamp |
optional[Integer] | (epoch time of the last contact) |
metrics |
optional[list[ResourceMetric]] | see below |
commands |
optional[Commands] | see Commands |
sensors |
optional[Sensors] | see Sensors |
Example of creating a resource with location:
curl --user apiKey:apiSecret \
-X POST "https://tenant.waylay.io/api/resources" \
-H "Content-Type: application/json" \
-d '{
"id": "mydevice_id4",
"customer": "tenant1",
"label": "helloWorld",
"location" : {
"lat" : 51,
"lon": 3.71
}
}'
Symbol | Type |
---|---|
lat |
Double |
lon |
Double |
Symbol | Type | Example |
---|---|---|
name |
String | Temperature |
valueType |
String | integer, double, boolean, string, enum |
valueChoices |
optional[list[String]] | [“OK”, “NOK”] |
metricType |
String | count / gauge / counter / timestamp (for events) default gauge |
unit |
optional[String] | SI units or non-SI units like Fahrenheit… |
maximum |
optional[Double] | 0 |
minimum |
optional[Double] | 60 |
Example of creating a resource with a metric in the request:
curl --user apiKey:apiSecret \
-X POST "https://tenant.waylay.io/api/resources" \
-H "Content-Type: application/json" \
-d '{
"id":"mydevice_id3",
"customer":"tenant1",
"label":"helloWorld",
"metrics" : [
{
"name" : "Temperature",
"unit":"C",
"valueType": "double",
"metricType": "counter"
}
]
}'
Reserved keywords for Metric type:
Symbol | Meaning |
---|---|
rate |
a number per second (implies that unit ends on ‘/s’) |
count |
a number per a given interval (such as a statsd flushInterval) |
gauge |
values at each point in time |
counter |
keeps increasing over time (but might wrap/reset at some point) i.e. a gauge with the added notion of “i usually want to derive this to see the rate” |
timestamp |
value represents a unix timestamp. so `sically a gauge or counter but we know we can also render the “age” at each point. |
More about metric types you can find here metric20org
Commands feature allows you to specify generic set of actuators for a resource, which at runtime get resolved to a specific actuator.
‘Create a resource with a SayHi command’
curl --user apiKey:apiSecret \
-X POST "https://tenant.waylay.io/api/resources" \
-H "Content-Type: application/json" \
-d '{
"id" : "my_friendly_device",
"greeter" : "Friendly device",
"commands" : [{
"SayHi" : {
"actuator" : {
"name": "debugDialog",
"version": "latest",
"properties" : {
"message": "Hello, says the {{greeter}} !"
}
}
}
}]
}'
The commands
property must be an array of objects. Each object must have one property which is the name of the command.
The value must be an actuator
definition with following properties:
Property | Value |
---|---|
name |
Name of an actuator |
version |
Exact version of the actuator or latest |
properties |
Json object with default values for the properties of the actuator |
When a command is sent to the broker for the resource and with name
SayHi, the engine will check the commands
property
of the resource’s metadata and see if there is a command SayHi
mapped to an actuator. If there is such a property and
the mapped actuator could be found, the properties
for the actuator are merged with the actual message sent to broker
and the actuator is executed for the resource
and the merged properties
.
It is possible, in the properties of the actuator, to reference the metadata properties of the resource. They will be resolved
to the actual value of the property at the moment of command execution. You can reference a metadata property by enclosing its name with {{
and }}
.
This is especially useful if you define commands at the resource type level, but need resource
specific values.
‘Send a SayHi command for resource testresource’
curl --user apiKey:apiSecret \
-X POST "https://data.waylay.io/resources/testresource/commands" \
-H "Content-Type: application/json"
-d '{
"name": "SayHi",
"message": "Hello from this friendly resource"
}'
An interesting thing to note is that commands are sent over the broker and they are queued by the broker. That means that you can easily fan out all actuations this way, in case you need to send a lot of actuations in a short period of time, without worrying whether sandbox can follow sudden high loads. Broker will make sure that they are all delivered with fastest pace, while at the same time, making sure they all have a chance to get executed by the sandbox.
You can also specify set of sensors that are applicable for a given resource. Please note that there is no explicit action taken by the Waylay platform on this meta key, unlike for commands, where the Waylay platform resolves a particular actuator for a given command call. Idea behind this abstraction is to assist integrations where an architect of the digital twin can specify which sensors from waylay library are applicable for a given resource (or resource type). For instance, you may have one sensor per metric, or multiple sensors for a given metric, or one sensor that is using multiple metrics. When calling a REST interface for meta, UI can be dynamically built based on set of capabilities for a resource both for actuations (using commands) and also associate set of sensors, next to supported metrics.
Create a resource with events sensor (which represents GoogleCalendar sensor)
curl --user apiKey:apiSecret \
-X POST "https://tenant.waylay.io/api/resources" \
-H "Content-Type: application/json"
-d '{
"id" : "my_friendly_device",
"sensors" : [
{
"name": "events",
"sensor": {
"name": "GoogleCalendarStreamSensor",
"version": "0.1.5"
}
}
]
}'
The sensors
property must be an array of objects. Each object must have a name
property that describes the sensor along with a sensor
property which is an object containing following properties:
Property | Value |
---|---|
name |
Name of a sensor |
version |
Exact version of the sensor or latest |
properties |
Json object with default values for the properties of the sensor |
Sensor properties in meta
[
{
"name": "<custom-name-for-sensor>",
"sensor": {
"name": "<sensor-name>",
"version": "<sensor-version>",
"properties": {
"<some-sensor-property>": "<property-value>",
"<another-sensor-property>": "<property-value>"
}
}
}
]
Building resource referencing a Weather Station resource
{
"id": "e0d7b1cd-5bb7-4dfd-aa63-5ab1a5d5e3fa",
"name": "Waylay Offices",
"address": "Blekersdijk 33a",
"city": "Ghent",
"weatherStation": {
"$ref": "/resources/04592b9a-e0c2-4e64-8c9a-202e50cd9275",
"name": "Gents weer"
}
}
The Waylay Engine will also recognise metadata keys which are json objects with
a $ref
keyword as references to other resource if the value for the $ref
is a URI that starts with /resources/
.
When you reference these keys, using the META.$.<key>
syntax, in the resource
field of sensor nodes in a task definition, the Waylay Engine will “resolve” these
at the start of the task and include the referenced resource as one of the task
resources.
curl --user apiKey:apiSecret \
-X PUT "https://tenant.waylay.io/api/resources/myDevice_id" \
-H "Content-Type: application/json" \
-d '{
"resourceTypeId": "resourceType_Id",
"customer":"tenant1",
"name": "helloWorld"
}'
In order to update a resource, you need to put your resourceId in the path.
curl --user apiKey:apiSecret \
-X PATCH "https://tenant.waylay.io/api/resources/myDevice_id" \
-H "Content-Type: application/json" \
-d '{
"resourceTypeId":"resourceType_Id"
}'
Partial updates allow you to add/modify individual fields on a resource.
curl --user apiKey:apiSecret \
-X PATCH "https://tenant.waylay.io/api/resources/myDevice_id" \
-H "Content-Type: application/json" \
-d '{
"customer": null
}'
If you want to remove a field from a resource, you can do so by setting
the field to null
in the payload of the PATCH
call
curl --user apiKey:apiSecret \
-X DELETE "https://tenant.waylay.io/api/resources/mydevice_id"
In order to delete a resource, you need to put your resource Id in the path
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources/[resourceId]"
This would return something like
{
"id": "testresource",
"resourceTypeId": "SampleResourceType",
"metrics":[{
"name": "Temperature",
"valueType": "double",
"metricType": "counter",
"unit": "C"
}],
"customField": "value"
}
In order to get a resource, you need to put your resourceId in the path
This will give you a denormalized view of a resource where properties that are inherited from the resourceType are merged with the properties specified at resource level.
curl -i --user apiKey:apiSecret -H "Accept: application/hal+json" \
"https://tenant.waylay.io/api/resources/[resourceId]"
This would return something like
{
"id": "Ground floor",
"name": "Ground floor",
"#desks": 0,
"_links": {
"self": {
"href": "/api/resources/Ground%20floor"
},
"children": {
"href": "/api/resources/Ground%20floor/children"
},
"parent": {
"href": "/api/resources/Office",
"id": "Office"
},
"resourceType": {
"href": "/api/resourcetypes/4539e0c2-578e-4470-8f14-2ed81d576e3a",
"id": "4539e0c2-578e-4470-8f14-2ed81d576e3a"
}
}
}
To retrieve a more “enriched” representation of the resource, specify the Accept
header as application/hal+json
The _links
property provides hyperlinks to api endpoints to retrieve more information about the resource. Following are provided:
self
: main reference to the resourcechildren
: if the resource has children, the URI to retrieve all children of the resourceparent
: if the resource has a parent, the URI to retrieve the parent of the resourceresourceType
: if the resource is link to a resource type, the reference to retrieve the resource typecurl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources/[resourceId]?denormalized=false"
This would return something like
{
"id": "testresource",
"resourceTypeId": "SampleResourceType"
}
In order to get the normalized view of a resource, i.e. get only the properties that are specified on the resource level and not the ones inherited from the resource type level, set the query parameter denormalized
to false
.
This endpoint also supports the HAL resource representation by specifying the Accept: application/hal+json
request header.
Filtered resource list request
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources?filter=car"
Paging is handled by
skip
andlimit
parameters. If you have a large volume of resources, you can iterate of them like this:
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources?limit=1&skip=0"
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources?limit=1&skip=1"
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources?limit=1&skip=2
etc
Resources can be queried by doing a GET request, if needed you can filter on these fields using the query string:
=true
to search for resources without a parent)This endpoint also supports the HAL resource representation by specifying the Accept: application/hal+json
request header. Resources will be returned in HAL format in the _embedded.values
member.
The result will next to the paging information (count
, total
, limit
and skip
) and the _embedded
member, also contain a _links
member that contains the links to
self
referencenext
reference to the next batch of results if there are more availableprev
reference to the previous batch of results if this was not the first batchFind all resources within 10km from point (51.05,3.73)
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources?lat=51.05&lon=3.73&distance=10km"
If your resources have coordinates specified in the location
property (see Create resource), you find all resources within a
specified distance from a point (specified by a lat
and lon
).
See Distance units for the specification of distance.
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources/[resourceId]/changes"
This returns the history of changes to a resource sorted by change time descending. By default only the 10 most recent changes are returned.
If you want more changes, specify using the limit
query parameter.
If you want to skip some changes, use the skip
query parameter.
If you want to history to be returned as a paged list (so with values
, total
, limit
and skip
),
set the Accept
header to application/vnd.waylay.paged+json
.
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources/[resourceId]/children"
Retrieves the child resources of the specified resource, i.e. all resources that have the specified resource as (direct) parent.
Page with skip
and limit
query parameters. Use ?denormalized=false
to retrieve the normalized representation of the children.
This endpoint also supports the HAL resource representation by specifying the Accept: application/hal+json
request header.
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resources/[resourceId]/commands"
will return something like
{
"values": [
{
"name": "Say hi",
"executionTime": "2018-09-24T13:59:10.377Z",
"actuator": "debugDialog:LATEST",
"result": {
"success": true,
"message": "Hi from resourcetype",
"rawData": {}
}
},
{
"name": "Say his",
"executionTime": "2018-09-24T13:58:56.075Z",
"errorMessage": "Command 'Say his' not found"
},
{
"name": "Say hi",
"executionTime": "2018-09-24T10:47:59.739Z",
"actuator": "debugDialog:LATEST",
"result": {
"success": true,
"message": "resource brunocommand says hi",
"rawData": {}
}
},
...
],
"skip": 0,
"limit": 10,
"total": 16
}
This returns a paged list with the command executions. Page with skip
and limit
query parameters.
In this example, we create a resource type and at the same time, we define metric types:
curl -i --user apiKey:apiSecret \
-X POST "https://tenant.waylay.io/api/resourcetypes" \
-H "Content-Type: application/json" \
-d '{
"id":"resourceType_Id",
"customField":"value",
"metrics" : [
{
"name":"Temperature",
"unit": "C",
"valueType": "double",
"metricType": "counter"
}
]
}'
Reserved keywords for resource type:
Symbol | Type | Example |
---|---|---|
id |
String | D12345 or UUID |
name |
optional[String] | device_123 |
provider |
optional[String] | Proximus |
providerId |
optional[String] | 123 |
customer |
optional[String] | customer1 |
metrics |
optional[List[ResourceMetric]] | list of metrics |
commands |
optional[Command] | Definition of commands |
templates |
optional[List[templates]] | Automatically create tasks by associating a template with a resource type |
$constraints |
optional[List[constraints]] | Applying resource constraint to resource type |
$bulkOperation |
optional[String] | Will be ignored when reading input, but will be returned to indicate a asynchronous operation is busy for the resource type |
In order to update a resource type, you need to put your resource type Id in the path
curl -i --user apiKey:apiSecret \
-X PUT "https://tenant.waylay.io/api/resourcetypes/resourceType_Id" \
-H "Content-Type: application/json" \
-d '{
"resourceTypeId": "resourceType_Id",
"customer":"tenant1",
"name": "myResourceType"
}'
curl -i --user apiKey:apiSecret \
-X PATCH "https://tenant.waylay.io/api/resourcetypes/resourceType_Id" \
-H "Content-Type: application/json" \
-d '{
"customer":"tenant2",
"customField":"value"
}'
Partial updates allow you to add/modify individual fields on a resource type.
curl --user apiKey:apiSecret \
-X PATCH "https://tenant.waylay.io/api/resourcetypes/resourceType_Id" \
-H "Content-Type: application/json" \
-d '{
"customer": null
}'
If you want to remove a field from a resource type, you can do so by setting
the field to null
in the payload of the PATCH
call
curl -i --user apiKey:apiSecret \
-X DELETE "https://tenant.waylay.io/api/resourcetypes/resourceType_Id"
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resourcetypes/[resourceType_Id]"
In order to get a resource type, you need to put your resource type Id in the path
Paging is handled by
skip
andlimit
parameters
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resourcetypes?filter=car"
Resources can be queried by doing a GET request, if needed you can filter on these fields using the query string:
curl -i --user apiKey:apiSecret \
"https://tenant.waylay.io/api/resourcetypes/[resourceType_Id]/changes"
This returns the history of changes to a resource type sorted by change time descending. By default only the last 10 most recent changes are returned.
If you want more changes, specify using the limit
query parameter.
If you want to skip some changes, use the skip
query parameter
If you want to history to be returned as a paged list (so with values
, total
, limit
and skip
),
set the Accept
header to application/vnd.waylay.paged+json
.
The waylay task engine can automatically provision tasks for each new resource. This is configured in the metadata of the resource type. All you need to add is a field templates
that contains what templates should be used and what task configuration should be applied to these managed tasks.
Resource type definition:
{
"id": "4b80d00a-89f0-41a0-b6e5-d4423caca844",
...
"templates": [
{
"templateName": "templatex",
"type": "periodic",
"frequency": 60000
},
{
"templateName": "templatey",
"type": "scheduled",
"cron": "0 0 12 * * ?"
}
]
}
If for example an existing resource’s type is set to the above type then 2 tasks will be created.
In general these managed tasks are created/removed for these actions:
curl -i --user apiKey:apiSecret -X POST \
"https://tenant.waylay.io/api/resourceconstraints" \
-H "Content-Type: application/json" \
-d '{
"name": "Mandatory customer",
"description" : "This constraints makes the customer attribute mandatory",
"attributes" : [
{
"name":"customer",
"required": true,
"type": {
"type" : "string"
"minLength" : 1
}
}
]
}'
A resource constraint has, next to a name
and a description
,
an array of attributes
description.
Each of these attributes
description has the following properties:
name
- String - unique (within the constraint) name of the attributerequired
- Boolean - flag to indicate if the attribute is mandatory or nottype
- Object - Json object describing the type of the attribute - see belowWhen a resource constraint is created, it is validated that the attributes do not
redefined the resource reserved keywords in an incompatible way
(e.g. defining provider
as a number). It is possible however to make the definition
more strict, e.g. by making an attribute required
or e.g. by defining that customer
should have a minLength
of 5.
The result of a successful POST
call will contain a uri
with the uri of the just created
resource constraint and an entity
field which contains the resource constraint including
the (generated) id
for the constraint.
Following attribute type are supported:
type
: numeric
minimum
- Number - expressing the minimum value the attribute needs to havemaximum
- Number - expressing the maximum value the attribute can havetype
: string
minLength
- Integer (>=0) - the minimum length the attribute value needs to havemaxLength
- Integer (>=0) - the maximum length the attribute value can havetype
: boolean
curl -i --user apiKey:apiSecret -X POST \
"https://tenant.waylay.io/api/resourceconstraints" \
-H "Content-Type: application/json" \
-d '{
"name": "Technology choice",
"description" : "This constraints defines a technology attribute with predefined possible values",
"attributes" : [
{
"name":"technology",
"required": false,
"type": {
"type" : "enum",
"enumType" : "string",
"items" : [ "LORA", "SIGFOX", "2G", "3G"]
}
}
]
}'
type
: enum
enumType
: numeric
or string
items
- array - valid values for the attribute. The specified values should be Numbers if enumType
is numeric
or Strings if enumType
is string
curl -i --user apiKey:apiSecret -X POST \
"https://tenant.waylay.io/api/resourceconstraints" \
-H "Content-Type: application/json" \
-d '{
"name": "Weather Station choice",
"description" : "This constraints defines weatherStation attribute"
"attributes" : [
{
"name":"weatherStation",
"required": true,
"type": {
"type" : "resourceRef",
"resourceTypes" : [ "weatherStation" ],
"exists" : true
}
}
]
}'
type
: resourceRef
attributes
- array of attributes descriptions - the reference object must have additionally to the $ref
propertyresourceTypes
- array of ResourceTypeId
s - the reference resource should be ofexists
- Boolean (default: false) - flag to indicate if the referenced resource must existcurl -i --user apiKey:apiSecret -X POST \
"https://tenant.waylay.io/api/resourceconstraints" \
-H "Content-Type: application/json" \
-d '{
"name": "Address field",
"description" : "address attribute with subfields",
"attributes" : [
{
"name":"address",
"required": true,
"type": {
"type": "object",
"attributes": [
{
"name": "street",
"required" : true,
"type" : {
"type": "string",
"minLength": 1,
"maxLength": 255
}
},
{
"name": "postal",
"required" : true,
"type" : {
"type": "string",
"minLength": 1,
"maxLength": 10
}
},
{
"name": "city",
"required" : true,
"type" : {
"type": "string",
"minLength": 1
}
}
]
}
}
]
}'
type
: object
attributes
: array of attributes descriptionscurl -i --user apiKey:apiSecret -X POST \
"https://tenant.waylay.io/api/resourceconstraints" \
-H "Content-Type: application/json" \
-d '{
"name": "tags field definition",
"description" : "tags attribute expressed as a constraint",
"attributes" : [
{
"name":"tags",
"required": false,
"type": {
"type": "array",
"elementType" : {
"type" : "string",
"minLength": 1
},
"minLength": 1,
"uniqueValues": true
}
}
]
}'
type
: array
elementType
: type of the elements, can be one of Boolean attribute, Numeric attribute, String attribute or Object attributeminLength
- Integer (>=0) - the minimum length the array value needs to havemaxLength
- Integer (>=0) - the maximum length the array value can beuniqueValues
- Boolean - flag to specify if elements of array value have to be unique or notcontains
- only supported if the elementType
is Boolean, Numeric of String, specifies values the array attribute must containAdding a possible value to technology constraint
curl -i --user apiKey:apiSecret -X PUT \
"https://tenant.waylay.io/api/resourceconstraints/b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909" \
-H "Content-Type: application/json" \
-d '{
"id" : "b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909",
"name": "Technology choice",
"description" : "This constraints defines a technology attribute with predefined possible values",
"attributes" : [
{
"name":"technology",
"required": false,
"type": {
"type" : "enum",
"enumType" : "string",
"items" : [ "LORA", "SIGFOX", "2G", "3G", "BLE" ]
}
}
]
}'
You can update an existing resource constraint by PUT
the complete, updated
resource constraint.
When updating a resource constraint, next to the compatibility check with the default reserved keywords definition, it is also checked that the resource constraint is not used by a resource type for which there are already resources.
curl -i --user apiKey:apiSecret -X DELETE\
"https://tenant.waylay.io/api/resourceconstraints/b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909"
You can delete a resource constraint that is not assigned to any resource type.
You can retrieve a resource constraint by the id.
curl -i --user apiKey:apiSecret -X GET \
"https://tenant.waylay.io/api/resourceconstraints/b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909"
returns
{
"id" : "b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909",
"name": "Technology choice",
"description" : "This constraints defines a technology attribute with predefined possible values" ,
"attributes" : [
{
"name":"technology",
"required": false,
"type": {
"type" : "enum",
"enumType" : "string",
"items" : [ "LORA", "SIGFOX", "2G", "3G", "BLE" ]
}
}
]
}
You can also retrieve the resource constraint as a json schema
by setting the Accept
header of the GET
request to application/schema+json
Requesting as Json schema
curl -i --user apiKey:apiSecret -X GET \
"https://tenant.waylay.io/api/resourceconstraints/b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909" \
-H "Accept: application/schema+json"
returns
{
"type": "object",
"properties": {
"technology": {
"type": "string",
"enum": [
"2G",
"3G",
"LORA",
"SIGFOX",
"BLE"
]
}
},
"required": []
}
curl -i --user apiKey:apiSecret -X GET \
"https://tenant.waylay.io/api/resourceconstraints?skip=0&limit=5
You can retrieve the list of defined resource constraints.
Pagination can be done with the query parameters skip
and limit
.
curl -i --user apiKey:apiSecret -X PATCH \
"https://tenant.waylay.io/api/resourcetypes/resourceType_Id" \
-H "Content-Type: application/json" \
-d '{
"$constraints": [
"b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909",
"a826cbee-6871-415e-911d-1c87d2c77aef"
]
}'
Multiple resource constraints can be applied to a resource type.
You can do that by specifying the $constraints
key as an array of resource constraint ids
in the body of an update or partial update
request on a resource type.
The system will check if the constraints that are applied are compatible with
each other, e.g. that they do not define the same attribute with conflicting types.
It is however possible that a constraint makes a definition more strict. The most
strict definition will then be applied, e.g. one constraint defines the customer
attribute to be mandatory, another constraint defines the customer
attribute to be
optional (required=false
), but specifies a minLength
of 5. When both are applied
to a resource type, any resource of that type will need to have a customer
attribute
(so mandatory) and the value for it has to be at least 5 characters.
Result of the above call
{
"id": "resourceType_Id",
"name": "Example resourceType",
"$constraints": [
{
"status": "applying",
"constraintId": "b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909"
},
{
"status": "applying",
"constraintId": "a826cbee-6871-415e-911d-1c87d2c77aef"
}
],
"$bulkOperation": "32657dc2-71e0-46b7-a4f1-11deee5111dd"
}
In the result of that call, the $constraints
will be an array of object with key
status: applying
next to the constraintId
. There will also be a $bulkOperation
key in the result indicating that an asynchronous operation is busy.
In that asynchronous operation, the resource constrains are validated on all
resources of that resource type.
When the asynchronous operation has finished, the result of a retrieve
request will not contain $bulkOperation
anymore and the status
for each of the $constraints
will either be
ineffect
meaning that the constraints are enforced and that all constraints are fulfilled by any resource of the typefailed
meaning that the constraints are enforced BUT that some constraints are not fulfilled by some of the resources of the typeSome resources do not fulfill all constraints
{
"id": "resourceType_Id",
"name": "Example resourceType",
"$constraints": [
{
"status": "ineffect",
"constraintId": "b1f7d1d2-07d7-4fdf-ae5b-1e9b5be40909"
},
{
"status": "failed",
"errors": [
{
"error": "Property address missing.",
"errorPath": "/address",
"resources": [
"714bbf92-5dfc-4c42-9623-1c6e72708126",
"c2ff6672-bee7-4849-9280-daac910eb348",
"9c8dd188-201e-458a-b1ce-4264d862bb61"
]
}
],
"constraintId": "a826cbee-6871-415e-911d-1c87d2c77aef"
}
]
}
When some resources do not fulfil the constraints, the errors
will contain per
unique error
, next to the indication of which attribute, the list of resourceIds
of the failing resources (for that error).
curl --user apiKey:apiSecret -X GET \
"https://tenant.waylay.io/api/resourcetypes/resourceType_Id/constraints"
Above would return:
{
"id": "merged",
"name": "Constraints for resourceType 'resourceType_id'",
"attributes": [
{ "name": "name", ... },
{ "name": "tags", ... },
{ "name": "firmware", ... },
{
"name": "technology",
"required": false,
"type": {
"type": "enum",
"enumType": "string",
"items": [
"LORA",
"SIGFOX",
"2G",
"3G",
"BLE"
]
}
},
{ "name": "alias", ... },
{ "name": "customer", ... },
{
"name": "address",
"required": true,
"type": {
"type": "object",
"attributes": [
...
]
}
},
{ "name": "metrics", ... },
{ "name": "resourceTypeId",... },
{ "name": "location", ... },
{ "name": "provider", ... },
{ "name": "lastMessageTimestamp", ... },
{ "name": "providerId", ... },
{ "name": "id", ... },
{ "name": "sensors", ... },
{ "name": "owner", ... },
{ "name": "parentId", ... },
{ "name": "commands", ... }
]
}
You can retrieve the merged constraints that are applicable for a certain resource type. This will give the reserved keywords for metadata expressed as resource constraint merged with all user defined resource constraints applied on the resource type.
curl --user apiKey:apiSecret -X GET \
"https://tenant.waylay.io/api/resourcetypes/resourceType_Id/constraints" \
-H "Accept: application/schema+json"
You can also retrieve the merged constraint as json schema
by setting the Accept
header as application/schema+json
curl --user apiKey:apiSecret -X POST \
"https://tenant.waylay.io/api/resourcetypes/resourceType_Id/revalidate"
You can request to revalidate all resources of a resource type
{
"statusCode": 400,
"error": "/address <- Property address missing.",
"details": [
{
"schemaPath": "#",
"errors": {},
"keyword": "required",
"msgs": [
"Property address missing."
],
"value": {
"id": "714bbf92-5dfc-4c42-9623-1c6e72708126",
"resourceTypeId": "bruno",
"name": "bruno",
"customer": "bruno_customer",
"array": [
{
"coucou": true,
"customer": "bravo"
},
{
"coucou": false
}
]
},
"instancePath": "/address"
}
]
}
Resource constraints will be validated for any operation (create/update/delete)
on a resource. If any constraint would not be fulfilled, the operation will return
a failure result (http status code 400
). details
will contain detailed information
for each constraint that was violated.
Delete resources myDevice_id, mydevice_id3 and myWrongDevice in bulk
curl --user apiKey:apiSecret \
-X POST "https://tenant.waylay.io/api/batch" \
-H "Content-Type:application/json" \
-d '{
"entity": "resource",
"action": "delete",
"query" : {
"ids" : ["myDevice_id", "mydevice_id3", "myWrongDevice"]
}
}'
Using the batch endpoint it is also possible to delete multiple resources or resource types in one api call.
To do this, you can POST
a batch operation with delete
action and
resource
or resourcetype
as entity
to the /api/batch/
endpoint.
You need to specify the ids
of the resources or resource types in the query
key of the bulk operation.