Welcome to the WoTKit

The WoTKit is a web-centric toolkit that helps organizations manage sensors and actuators to collect, aggregate, store and process sensor data and react to changes in the physical and virtual world.

To get started quickly, see the Quick Start guide. For more information see consult the V1 API Reference.

Please send any questions and feedback to info@sensetecnic.com.

Guide

WoTKit API Guides

In this section we have listed tutorials which guide users through the API. For reference documentation, refer to Sensor Data.

Organizations for Privacy and Visibility

WoTKit organizations are used to group sensors owned by an organization, and restrict the visibility of sensors and groups to other users in the system who are members of the same organization.

Organization members may have different roles: OWNER, ADMIN, and MEMBER.

  • MEMBER - a member can view private sensors and groups in the organization. They cannot add sensors or groups to the organization, modify organization membership or roles, or delete the organization.
  • ADMIN - an admin is a MEMBER who can add or remove members, and add or remove sensors and groups to an organization. They have read and write priveledges to sensors and groups.
  • OWNER - an owner is an ADMIN who owns the organization and can delete the organization.

Private Sensors and Groups

When group or sensor is marked as private, it can only be viewed by organization members.

Note: when a group contains a mix of private and public sensors from different organizations, some sensors in a group may not be visible to all users in a given organization.

Creating an Organization

When you create an organization, you are the owner of that organization. As owner, you can add members, and assign roles.

Querying Sensor Data

WoTKit provides flexibility in how you want to query your data. In the following section, we walk through the different ways of building a query to get sensor data out of wotkit. The queries are constructed using query parameters which you append to a URL endpoint.

Generally, the use cases of the data api is to query for the raw time-series data of a sensor or group of sensors. There are two different types of queries: Recent Queries and Time Range Queries.

Recent Queries are used to easily look at recent information. The API provides parameters for you to either:

  1. get n most recent sensor_data
  2. get sensor_data since t milliseconds in the past
Time Range Queries are useful for going through data in the past.
These queries allow you to page through data by specifying a start & end point in time.

The following document will walk through some examples of how to take advantage of Recent Queries and Time Range Queries

Recent Queries

In this section we’ll dive in quickly and briefly show an example of Recent Num Queries and Recent Time Queries.

Recent Num Queries

By default, the data endpoint will return the 100 most recent queries. Try it using a URL like this:

http://wotkit.sensetecnic.com/api/v2/sensors/sensetecnic.mule1/data

The response should look similar to the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
  "numFound": 100564,
  "data": [
    {
      "id": 47902511,
      "timestamp": "2013-11-29T00:46:36.056Z",
      "sensor_id": 1,
      "sensor_name": "sensetecnic.mule1",
      "value": 69,
      "lng": -123.17608,
      "lat": 49.14103
    },
    {
      "id": 47902514,
      "timestamp": "2013-11-29T00:46:39.556Z",
      "sensor_id": 1,
      "sensor_name": "sensetecnic.mule1",
      "value": 52,
      "lng": -123.17599,
      "lat": 49.13919
    },
    ... // more data
  ],
  "query": {
    "limit": 100,
    "recent_n": 100
  }
}

The data is returned in JSON. Generally, all list responses are returned in this container to aid paging and debugging.

Field Description
numFound The total number of elements matching this query
data The enclosed sensor_data. Always sorted from oldest to newest timestamp
query Contains the interpreted query from the request. For debugging.
metadata Extra information. Depends on use case.

The query field is particularly interesting because it tells you how the query was interpreted. In this case, the query has a limit of 100 and a recent_n of 100. A recent_n query fetches the n most recent items. This is useful when API users want to peek at the recent data without having to construct complex queries.

In essence, the query we ran is a convenient default for the explicit version:

http://wotkit.sensetecnic.com/api/v2/sensors/sensetecnic.mule1/data?limit=100&recent_n=100

Next we can try a recent_t query, which looks up the timestamp

Recent Time Queries

Recent Time are very similar to Recent Num Queries. The difference is that Recent Num Queries look at data count i.e. the last 10 elements, or the last 50 elements. Recent Time queries look at the timestamp instead. So, it’s useful for where we’re interested in the elements from the last hour, or the 12 hours.

Request

http://wotkit.sensetecnic.com/api/v2/sensors/sensetecnic.mule1/data?recent_t=10000

Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
  "numFound": 3,
  "data": [
      {
          "id": 47967438,
          "timestamp": "2013-11-29T18:34:09.557Z",
          "sensor_id": 1,
          "sensor_name": "sensetecnic.mule1",
          "value": 62,
          "lng": -123.14509,
          "lat": 49.186
      },
      {
          "id": 47967445,
          "timestamp": "2013-11-29T18:34:13.059Z",
          "sensor_id": 1,
          "sensor_name": "sensetecnic.mule1",
          "value": 53,
          "lng": -123.1454,
          "lat": 49.18565
      },
      {
          "id": 47967446,
          "timestamp": "2013-11-29T18:34:16.557Z",
          "sensor_id": 1,
          "sensor_name": "sensetecnic.mule1",
          "value": 67,
          "lng": -123.14844,
          "lat": 49.18323
      }
  ],
  "query": {
      "limit": 100,
      "recent_t": 10000
  }
}

Looking at the query field this time, we can see it was interpreted as a recent_t query. The query looked for items up to 10 seconds ago (10000 milliseconds). You can verify this by inspecting the timestamp of the data.

Note

When accessing WoTKit anonymously, the date string is set to UTC. If you access it an api-key, the timezone will be set based on the account’s settings.

We’ve just shown you how to run both Recent Queries. One parameter to make note of is the limit parameter. At the moment, limit is capped at 100 – which restricts how much data you get in recent_n and recent_t queries. To overcome this we will look into paging through historical data next.

Time Range Queries

At the end of the last section, we noted that there is a weakness in the recent queries which limit your ability to sift through historical data. So, to look through historical data, you can page through historical data using the following query parameters. For the remainder of this, we will be working with the sensor rymndhng.sdq-test.

Querying with Start and End

We’ll start with a simple practical example. We have a defined starting time and ending time where we want to get all the data in between. I want to know what data was there between start: "2013-11-21T11:00:51.000Z" to end: "2013-11-29T22:59:54.862Z"

Note

It’s important to note that start is exclusive and end is inclusive. i.e. for start=100 and end=200, then the query does the following:

start < sensor_data.timestamp <= end

Query Parameters

Query Parameter Value
start 1385031651000 (2013-11-21T11:00:51.000Z)
end 1385765994862 (2013-11-29T22:59:54.862Z)

Translating those two strings to milliseconds, we end up with the request below. Execute it and follow the response.

Request

http://wotkit.sensetecnic.com/api/v2/sensors/rymndhng.sdq-test/data?start=1385031651000&end=1385765994862

Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
  "numFound": 5,
  "data": [
      {
          "id": 48232725,
          "timestamp": "2013-11-29T22:59:09.472Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 81
      },
      {
          "id": 48232726,
          "timestamp": "2013-11-29T22:59:09.472Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 53
      },
      {
          "id": 48232727,
          "timestamp": "2013-11-29T22:59:19.633Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 0
      },
      {
          "id": 48232728,
          "timestamp": "2013-11-29T22:59:24.715Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 56
      },
      {
          "id": 48232729,
          "timestamp": "2013-11-29T22:59:54.862Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 97
      }
  ],
  "query": {
      "end": 1385765994862,
      "start": 1385031651000,
      "limit": 100
  }
}

Once again, let’s look at the query parameter in the response to see what was interpreted. We can see that start/end was interpreted in the query. Inspect the timestamps of of both data points, we can see it’s between the start/end points, specifically start < data[0].timestamp < ... < data[4].timestamp < end.

Paging Through Data

In the previous section, we gave a very naive example. In this case, only two elements were in the range and therefore all the relevent data was returned. Very often this isn’t the case – and you may want to sift through thousands of entries at a time. To do this, we enabled paging through data entries. We’ll also specify limit to 10 to make the Response more comprehenedable.

Let’s try to query all the data by choosing start: 0 and and a really large end: 2000000000000.

Query Parameters

Query Parameter Value
start 0 (1970-01-01T00:00:00.000Z)
end 2000000000000 (2033-05-18T03:33:20.000Z)
limit 3

Request

http://wotkit.sensetecnic.com/api/v2/sensors/rymndhng.sdq-test/data?start=0&end=2000000000000&limit=3

Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
    "numFound": 9,
    "data": [
        {
            "id": 48232722,
            "timestamp": "2013-11-21T10:58:51.000Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "value": 6.7
        },
        {
            "id": 48232723,
            "timestamp": "2013-11-21T10:59:51.000Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "value": 6.8
        },
        {
            "id": 48232724,
            "timestamp": "2013-11-21T11:00:51.000Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "value": 6.9
        }
    ],
    "query": {
        "end": 2000000000000,
        "start": 0,
        "limit": 3
    }
}

So this time, first we look at the query parameter. As mentioned previously, the limit is currently capped at 3. So how do we know if we there’s more data? Well, there is another field in the response which can help us: numFound. numFound counts all the data found within the data range from start to end. In this example, we know there’s more data because data.length < numFound.

Given this information, we can now continue paging data by setting offset. We can retrieve the next page by choosing offset = data.size, in this case, data.size is 10. Generally, we can page by specifying offset = prev_offset + data.size. We can also figure out if we’re at the end of the data range generally by testing that data.size + offset < numFound.

Now, let’s rerun the last query with an offset.

Query Parameters

Parameter Value
start 0 (same as before
end 2000000000000 (same as before)
limit 10
offset 3

Request

http://wotkit.sensetecnic.com/api/v2/sensors/rymndhng.sdq-test/data?start=0&end=2000000000000&limit=3&offset=3

Response

{
    "numFound": 9,
    "data": [
        {
            "id": 48232725,
            "timestamp": "2013-11-29T22:59:09.472Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "valua": 81
        },
        {
            "id": 48232726,
            "timestamp": "2013-11-29T22:59:09.472Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "valua": 53
        },
        {
            "id": 48232727,
            "timestamp": "2013-11-29T22:59:19.633Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "valua": 0
        }
    ],
    "query": {
        "offset": 3,
        "end": 2000000000000,
        "start": 0,
        "limit": 3
    }

}

Once again, looking at the query, we can now see that offset is specfied as 3. We can also verify that an offset was used by looking at id and timestamp of the two responses. The last element of the first response has id: 48232724 and timestamp: "2013-11-21T11:00:51.000Z". The first element in the second response has id: 48232725 and timestamp: "2013-11-29T22:59:09.472Z". You can easily verify that they are in sequence.

Advanced Time Range Queries

In general, using start, end, offset provides enough flexibility. However, sensors are allowed to have multiple data on the same timestamp. This can easily happen when historical data is PUT into the system. In other words, you cannot expect timestamp to be unique for sensor data (generally they are good enough). So, we introduce the idea of start_id and end_id to allow precise selection of start and end elements.

We’ll start off with our first query .. code-block:: javascript

Response

{
  "numFound": 9,
  "data": [
      {
          "id": 48232722,
          "timestamp": "2013-11-21T10:58:51.000Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 6.7
      },
      {
          "id": 48232723,
          "timestamp": "2013-11-21T10:59:51.000Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 6.8
      },
      {
          "id": 48232724,
          "timestamp": "2013-11-21T11:00:51.000Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 6.9
      },
      {
          "id": 48232725,
          "timestamp": "2013-11-29T22:59:09.472Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 81
      }
  ],
  "query": {
      "start": 0,
      "limit": 4
  }
}

Now sometime in the future, we want to rerun the query using the information we had previously. So, we’ll use the last item’s timestamp (2013-11-29T22:59:09.472Z) as the start value.

Request

http://wotkit.sensetecnic.com/api/v2/sensors/rymndhng.sdq-test/data?start=1385765949472&limit=4

Response

{
  "numFound": 4,
  "data": [
      {
          "id": 48232727,
          "timestamp": "2013-11-29T22:59:19.633Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 0
      },
      {
          "id": 48232728,
          "timestamp": "2013-11-29T22:59:24.715Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 56
      },
      {
          "id": 48232729,
          "timestamp": "2013-11-29T22:59:54.862Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 97
      },
      {
          "id": 48232730,
          "timestamp": "2013-11-29T23:00:24.862Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 6.7
      }
  ],
  "query": {
      "start": 1385765949472,
      "limit": 4
  }
}

Everything looks fine and dandy doesn’t it? The timestamps are incremental, and therefore all is well is it? Well, no it actually isn’t. There’s a problem which we are unaware of. We’ve actually skipped an element because of duplicate timestamps.

Run this request which querys the entire range and look at the data.

Request

http://wotkit.sensetecnic.com/api/v2/sensors/rymndhng.sdq-test/data

Response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{
  "numFound": 9,
  "data": [
      {
          "id": 48232722,
          "timestamp": "2013-11-21T10:58:51.000Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 6.7
      },
      {
          "id": 48232723,
          "timestamp": "2013-11-21T10:59:51.000Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 6.8
      },
      {
          "id": 48232724,
          "timestamp": "2013-11-21T11:00:51.000Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 6.9
      },
      {
          "id": 48232725,
          "timestamp": "2013-11-29T22:59:09.472Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 81
      },
      {
          "id": 48232726,
          "timestamp": "2013-11-29T22:59:09.472Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 53
      },
      {
          "id": 48232727,
          "timestamp": "2013-11-29T22:59:19.633Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 0
      },
      {
          "id": 48232728,
          "timestamp": "2013-11-29T22:59:24.715Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "valua": 56
      },
      {
          "id": 48232729,
          "timestamp": "2013-11-29T22:59:54.862Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 97
      },
      {
          "id": 48232730,
          "timestamp": "2013-11-29T23:00:24.862Z",
          "sensor_id": 531,
          "sensor_name": "rymndhng.sdq-test",
          "value": 6.7
      }
  ],
  "query": {
      "limit": 100,
      "recent_n": 10
  }
}

The highlighted lines for id: 48232726 did not exist in either of our queries. In Querying with Start and End, we specified the second query did exactly what you asked for: Query sensor data after timestamp 1385765949472 limit 3. So, to solve this, we introduce a new parameter start_id. This parameter can be used in conjuction with start to specify specify which data element’s id to start with. Essentially, sensor_data are uniquely identified using this tuple (timestamp, id). So, let’s rerun the second query with start_id: 48232725 from the first query.

Request

http://wotkit.sensetecnic.com/api/v2/sensors/rymndhng.sdq-test/data?start=1385765949472&limit=4&start_id=48232725

Response

{
    "numFound": 5,
    "data": [
        {
            "id": 48232726,
            "timestamp": "2013-11-29T22:59:09.472Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "valua": 53
        },
        {
            "id": 48232727,
            "timestamp": "2013-11-29T22:59:19.633Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "valua": 0
        },
        {
            "id": 48232728,
            "timestamp": "2013-11-29T22:59:24.715Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "valua": 56
        },
        {
            "id": 48232729,
            "timestamp": "2013-11-29T22:59:54.862Z",
            "sensor_id": 531,
            "sensor_name": "rymndhng.sdq-test",
            "value": 97
        }
    ],
    "query": {
        "start": 1385765949472,
        "limit": 4,
        "start_id": 48232725
    }
}

There, we got the response with id: 48232726. The start_id allowed us to filter ids greater than 3. end_id works the same way as start_id if you really need fine-grained control over the range of a data query.

Summary of Time Range Data Query

With all the information given, we can really condense the query parameters into the following query. data_ts is the sensor data’s timestamp, and data_id is the data’s id element.

Without start_id or end_id, the query range is done like this.

start < data_ts <= end

With start_id and/or end_id, the query range adds extra checks near the bounds

(start < data_ts <= end)
OR (data_ts = start AND data_id > start_id)
OR (data_ts = end   AND data_id <= end_id)

Below is a quicky summary of what query parameter means:

Parameter Type Description
start timestamp The absolute starting point (in milliseconds since Jan 1, 1970).
start_id id The starting id of sensor_data at timestamp start. Used for paging.
end timestamp The absolute ending timestamp (in milliseconds since Jan 1, 1970)
end_id timestamp The end id of sensor_data with timestamp end. Used for paging.

Sensor Data Query Recipes

In this section, we will highlight some novel ways of combining the information above to query the data.

Use start_id instead of start for start of query

In the documentation, we used start_id alongisde start, but actually, this is optional. If you use start_id without start, we will actually lookup the timestamp of the element with id start_id, and then use that as the starting timestamp.

Making Start Inclusive

From Summary of Time Range Data Query, it shows the start range is exclusive. But, there is a way to make this inclusive. If you set start_id: 0, it will make the data range inclusive.

V1 API Reference

This section contains API References for V1 of WoTKit’s API. In addition to the documentation posted here, our API can be explored using Swagger with the following URL http://wotkit.sensetecnic.com/api/api-docs?path=v1.

Authentication

The WoTKit API supports three forms of authentication to control access to a user’s sensors and other information on the WoTKit.

  1. Basic authentication using the user’s name and password
  2. Basic authentication with Keys (key id and key password)
  3. OAuth2 authorization of server-based Applications

Using the WoTKit portal, developers can create keys for use by one or more sensor gateways or scripts. Users can also register new server side applications and then authorize these applications to allow them to access a user’s sensors on their behalf.

Note

Most examples in this document use basic authentication with keys or WoTKit username and passwords. However, OAuth2 authorization is also possible by removing the id and password and by appending an access_token parameter. See apps-oauth-label for details.

Methods privacy

Some API methods are private and will return an HTTP status code of 403 Forbidden if accessed without authenticating the request, while others are completely private or are restricted to certain users. (Currently only system administrators have access to ALL methods),

Every method has a description of its private level in one of the following forms:

  • Public accessible to all

  • Private accessible only to authenticated users

  • Public or Private accessible to all, but might return different results to authenticated users.

    • Example of different results is the “get sensors” method, which might return a user’s private sensors when the method is called as an authenticated user.
  • Admin accessible only to authenticated admin users

Keys and Basic Authentication

Keys are created on the WoTKit UI (http://wotkit.sensetecnic.com/wotkit/keys) and are unique to each user.

To grant a client access to your sensors, you can create a key. The client can then be supplied the auto-generated ‘key id’ and ‘key password’. These will act as username and password credentials, using basic authentication to access sensors on the user’s behalf.

For instance, the following curl command uses a ‘key id’ and ‘key password’ to get information about the sensor sensetecnic.mule1.

(Please replace the {key_id} and {key_password} in the code with appropriate values copied from the WoTKit UI.)

example

curl --user {key_id}:{key_password} "http://wotkit.sensetecnic.com/api/sensors/sensetecnic.mule1"

This returns:

{
        "name":"mule1",
        "fields":[
        {"name":"lat","value":49.20532,"type":"NUMBER","index":0,
         "required":true,"longName":"latitude","lastUpdate":"2012-12-07T01:47:18.639Z"},
        {"name":"lng","value":-123.1404,"type":"NUMBER","index":1,
         "required":true,"longName":"longitude","lastUpdate":"2012-12-07T01:47:18.639Z"},
        {"name":"value","value":58.0,"type":"NUMBER","index":2,
         "required":true,"longName":"Data","lastUpdate":"2012-12-07T01:47:18.639Z"},
        {"name":"message","type":"STRING","index":3,
         "required":false,"longName":"Message"}
                ],
        "id":1,
        "visibility":PUBLIC,
        "owner":"sensetecnic",
        "description":"A big yellow taxi that travels from
                       Vincent's house to UBC and then back.",
        "longName":"Big Yellow Taxi",
        "latitude":51.060386316691,
        "longitude":-114.087524414062,
        "lastUpdate":"2012-12-07T01:47:18.639Z"}
}

Registered Applications and OAuth2

The WoTKit supports the OAuth2 authorization framework as described in RFC 6749.

Applications are registered on the WoTKit UI (http://wotkit.sensetecnic.com/wotkit/apps) by an application developer. Applications can be installed by many users, but the application credentials called the client_id and client_secret are unique to that application.

Once registered, the client application then uses its ‘Client ID’ and generated ‘Application Secret’ as credentials in the OAuth2 authorization process to request permission to access WoTKit resources on a user’s behalf by generating an access token. Using an access token, the application can them make API calls to the WoTKit on behalf of the user – no further id/passwords are needed.

For example, the following curl command uses an access token to get information about the sensor sensetecnic.mule1.

The first step of OAuth 2 is to get authorization from the user. The WoTKit supports two grant types:

  • Authorization Code for apps running on a web server
  • Password for logging in with a username and password

Authorization Code Grant

In order to obtain an access token for a web server application using the Authorization Code grant, the following needs to be done:

  1. Request an authorization code by providing the ‘Client ID’ as follows:

    http://wotkit.sensetecnic.com/api/oauth/authorize?client_id={application client id} &response_type=code&redirect_uri={redirect uri}

  2. If the user has not previously logged into the WoTKit authorization server, a login page will be presented. A WoTKit user must first log in.

  3. Once logged in, a prompt will ask the user to authorize the ‘application client id’ to act on their behalf. Once authorized, an ‘authorization code’ is provided.

  4. Using the application credentials, this authorization code is exchanged for an access token used to access the WoTKit API.

Example: PHP file pointed to by {redirect_uri}

<?php
$code = $_GET['code'];
$access_token = "none";
$ch = curl_init();

if(isset($code)) {
        // try to get an access token
        $params = array("code" => $code,
                        "client_id"=> {application client id},
                        "client_secret" => {application secret},
                        "redirect_uri" => {redirect uri},
                        "grant_type" => "authorization_code");
        $data = ArraytoNameValuePairs ($params);

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, "http://wotkit.sensetecnic.com/api/oauth/token");
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

        $access_token = json_decode($response)->access_token;
        }
        ?>

Password Grant

The password grant type can be used to exchange the user name and password for an access token directly. This is generally used by applications that are part of the WoTKit service, since they need to collect the user’s name and password.

To use the password grant type, you simply POST the name and password along with the client id and secret directly, in response you will receive an access token.

example

curl -d "grant_type=password&username={username}&password={password}&client_id={clientid}&client_secret={clientsecret}&scope=all" https://wotkit.sensetecnic.com/api/oauth/token

returns:

{
        "access_token":"{access_token}",
        "token_type":"bearer",
        "refresh_token":"{refresh_token}",
        "expires_in":43199,
        "scope":"all"
}

Access Token Facts

When obtaining an access token, the ‘response’ field holds the following useful information:

  • response->access_token

  • response->expires_in

    • default value is approx. 43200 seconds (or 12 hrs)

Error Reporting

Errors are reported with an HTTP status code accompanied by an error JSON object. The object contains the status, an internal error code, user-displayable message, and an internal developer message.

For example, when a sensor cannot be found, the following error is returned:

HTTP/1.1 404 Not Found

{
    "error": {
        "status": 404,
        "code": 0,
        "message": "No thing with that id or name",
        "developerMessage": ["my_sensor"]
    }
}

Sensors

A sensor represents a physical or virtual sensor or actuator. It contains a data stream made up of fields.

A sensor has the following attributes:

Name Value Description
id the numeric id of the sensor. This may be used in the API in place of the sensor name.
name **
the name of the sensor.
Note that the global name is {username}.{sensorname}.
When logged in as a the owner, you can refer to the sensor using only {sensorname}.
To access a public sensor created by another user, you can refer to it by its numeric id or the global name, {username}.{sensorname}.
description ** a description of the sensor for text searches.
longName ** longer display name of the sensor.
url deprecated
latitude
the latitude location of the sensor in degrees.
This is a static location used for locating sensors on a map and for location-based queries. (Dynamic location (e.g. for mobile sensors) is in the lat and lng fields of sensor data.)
longitude
the longitude location of the sensor in degrees.
This is a static location used for locating sensors on a map and for location-based queries. (Dynamic location (e.g. for mobile sensors) is in the lat and lng fields of sensor data.)
lastUpdate
last update time in milliseconds.
This is the last time sensor data was recorded, or an actuator script polled for control messages.
visibility
PUBLIC: The sensor is publicly visible
ORGANIZATION: The sensor is visible to everyone in the same organization as the sensor
PRIVATE: The sensor is only visible to the owner. In any case posting data to the sensor is restricted to the sensor’s owner.
owner the owner of the sensor
fields the expected data fields, their type (number or string), units and if available, last update time and value.
tags the list of tags for the sensor
data sensor data (not shown yet)

** Required when creating a new sensor.


Querying Sensors

A list of matching sensors may also be queried by the system.

The current query parameters are as follows:

Name Value Description
scope
all - all sensors the current user has access to
subscribed - the sensors the user has subscribed to | contributed - the sensors the user has contributed to the system.
tags list of comma separated tags
orgs list of comma separated organization names
private
**true** - private sensors only; **false** - public only
deprecated, use visibility instead
visibility filter by the visibility of the sensors, either of public, organization, or private
text text to search for in the name, long name and description
active when true, only returns sensors that have been updated in the last 15 minutes.
offset offset into list of sensors for paging
limit limit to show for paging. The maximum number of sensors to display is 1000.
location
geo coordinates for a bounding box to search within.
Format is yy.yyy,xx.xxx:yy.yyy,xx.xxx, and the order of the coordinates are North,West:South,East.
Example: location=56.89,-114.55:17.43,-106.219

To query for sensors, add query parameters after the sensors URL as follows:

URL http://wotkit.sensetecnic.com/api/sensors?{query}
Privacy Public or Private
Format json
Method GET
Returns On error, an appropriate HTTP status code; On success, OK 204 and a list of sensor descriptions matching the query.

example

curl --user {id}:{password}
"http://wotkit.sensetecnic.com/api/sensors?tags=canada"

Output:

[
  {
        "tags":["data","vancouver","canada"],
                "latitude":0.0,
                "longitude":0.0,
                "longName":"api-data-test-1",
                "lastUpdate":"2013-01-26T01:55:36.514Z",
                "name":"api-data-test-1",
                "fields":
                        [{"required":true, "longName":"latitude",
                          "lastUpdate":"2013-01-26T01:55:36.514Z",
                          "name":"lat", "value":39.0, "type":"NUMBER","index":0},
                        {"required":true,"longName":"longitude",
                         "lastUpdate":"2013-01-26T01:55:36.514Z",
                         "name":"lng","value":85.0,"type":"NUMBER","index":1},
                        {"required":true,"longName":"Data",
                         "lastUpdate":"2013-01-26T01:55:36.514Z
                         "name":"value","value":20.0,"type":"NUMBER","index":2},
                        {"required":false,"longName":"Message",
                         "lastUpdate":"2013-01-26T01:55:36.514Z",
                         "name":"message","value":"test message to be active 164",
                         "type":"STRING","index":3}],
        "id":69,
        "visibility":"PUBLIC",
        "owner":"roseyr",
        "description":"api-data-test-1"
  },

  {
        "tags":["data","canada","edmonton"],
        "latitude":0.0,
        "longitude":0.0,
        "longName":"api-data-test-2",
        "lastUpdate":"2013-01-26T01:55:42.400Z",
        "name":"api-data-test-2",
        "fields":
                [{"required":true,"longName":"latitude",
                  "lastUpdate":"2013-01-26T01:55:37.537Z",
                  "name":"lat","value":65.0,"type":"NUMBER","index":0},
                {"required":true,"longName":"longitude",
                 "lastUpdate":"2013-01-26T01:55:37.537Z",
                 "name":"lng","value":74.0,"type":"NUMBER","index":1},
                {"required":true,"longName":"Data",
                 "lastUpdate":"2013-01-26T01:55:37.537Z",
                 "name":"value","value":82.0,"type":"NUMBER","index":2},
                {"required":false,"longName":"Message",
                 "lastUpdate":"2013-01-26T01:55:37.537Z",
                 "name":"message","value":"test message to be active 110",
                 "type":"STRING","index":3}],
        "id":70,
        "visibility":"PUBLIC",
        "owner":"roseyr",
        "description":"api-data-test-1"
  },

  {
        "tags":["data","canada","winnipeg"],
        "latitude":0.0,
        "longitude":0.0,
        "longName":"api-data-test-3",
        "lastUpdate":"2013-01-26T01:55:34.488Z",
        "name":"api-data-test-3",
        "fields":
                [{"required":true,"longName":"latitude","name":"lat","value":0.0,
                  "type":"NUMBER","index":0},
                {"required":true,"longName":"longitude","name":"lng","value":0.0,
                 "type":"NUMBER","index":1},
                {"required":true,"longName":"Data","name":"value","value":0.0,
                 "type":"NUMBER","index":2},
                {"required":false,"longName":"Message","name":"message",
                 "type":"STRING","index":3}],
        "id":71,
        "visibility":"PUBLIC",
        "owner":"roseyr",
        "description":"api-data-test-3"
  }
]

Viewing a Single Sensor

To view a single sensor, query the sensor by sensor name or id as follows:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}
Privacy Public or Private
Format json
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

example

curl --user {id}:{password}
"http://wotkit.sensetecnic.com/api/sensors/sensetecnic.mule1"

Output:

{
        "name":"mule1",
        "fields":[
                {"name":"lat","value":49.20532,"type":"NUMBER","index":0,
                 "required":true,"longName":"latitude",
                 "lastUpdate":"2012-12-07T01:47:18.639Z"},
                {"name":"lng","value":-123.1404,"type":"NUMBER","index":1,
                 "required":true,"longName":"longitude",
                 "lastUpdate":"2012-12-07T01:47:18.639Z"},
                {"name":"value","value":58.0,"type":"NUMBER","index":2,
                 "required":true,"longName":"Data",
                 "lastUpdate":"2012-12-07T01:47:18.639Z"},
                {"name":"message","type":"STRING","index":3,
                 "required":false,"longName":"Message"}
        ],
        "id":1,
        "visibility":"PUBLIC",
        "owner":"sensetecnic",
        "description":"A big yellow taxi that travels
                       from Vincent's house to UBC and then back.",
        "longName":"Big Yellow Taxi",
        "latitude":51.060386316691,
        "longitude":-114.087524414062,
        "lastUpdate":"2012-12-07T01:47:18.639Z"}
}

Creating/Registering a Sensor

To register a sensor, you POST a sensor resource to the url /sensors.

  • The sensor resources is a JSON object.
  • The “name”, “longName”, and “description” fields are required when creating a sensor.
  • The “latitude” and “longitude” fields are optional and will default to 0 if not provided.
  • The “visibility” field is optional and will default to “PUBLIC” if not provided.
  • The “tags”, “fields” and “organization” information are optional.
  • If “visibility” is set to ORGANIZATION, a valid “organization” must be supplied.
  • The sensor name must be at least 4 characters long, contain only lowercase letters, numbers, dashes and underscores, and can start with a lowercase letter or an underscore only.

To create a sensor:

URL http://wotkit.sensetecnic.com/api/sensors
Privacy Private
Format json
Method POST
Returns HTTP status code; Created 201 if successful; Bad Request 400 if sensor is invalid; Conflict 409 if sensor with the same name already exists

example

curl --user {id}:{password} --request POST --header "Content-Type: application/json"
--data-binary @test-sensor.txt 'http://wotkit.sensetecnic.com/api/sensors'

For this example, the file test-sensor.txt contains the following. This is the minimal information needed to register a sensor resource.

{
        "visibility":"PUBLIC",
        "name":"taxi-cab",
        "description":"A big yellow taxi.",
        "longName":"Big Yellow Taxi",
        "latitude":51.060386316691,
        "longitude":-114.087524414062
}

Creating/Registering multiple Sensors

To register multiple sensors, you PUT a list of sensor resources to the url /sensors.

  • The sensor resources is a JSON list of objects as described in Creating/Registering a Sensor.
  • Limited to 100 new sensors per call. (subject to change)
URL http://wotkit.sensetecnic.com/api/sensors
Privacy Private
Format json
Method PUT
Returns HTTP status code; Created 201 if successful; Bad Request 400 if sensor is invalid; Conflict 409 if sensor with the same name already exists ; On Created 201 or some errors (not all) you will receive a JSON dictionary where the keys are the sensor names and the values are true/false depending on whether creating the sensor succeeded. For Created 201 all values will be true.

Updating a Sensor

Updating a sensor is the same as registering a new sensor other than PUT is used and the sensor name or id is included in the URL.

Note that all top level fields supplied will be updated.

  • You may update any fields except “id”, “name” and “owner”.
  • Only fields that are present in the JSON object will be updated.
  • If “visibility” is set to ORGANIZATION, a valid “organization” must be supplied.
  • If “tags” list or “fields” list are included, they will replace the existing lists.
  • If “visibility” is hardened (that is, the access to the sensor becomes more restrictive) then all currently subscribed users are automatically unsubscribed, regardless of whether they can access the sensor after the change.

To update a sensor owned by the current user:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}
Privacy Private
Format json
Method PUT
Returns HTTP status code; No Content 204 if successful

For instance, to update a sensor description and add tags:

example

curl --user {id}:{password} --request PUT --header "Content-Type: application/json"
--data-binary @update-sensor.txt 'http://wotkit.sensetecnic.com/api/sensors/taxi-cab'

The file update-sensor.txt would contain the following:

{
        "visibility":"PUBLIC",
        "name":"taxi-cab",
        "description":"A big yellow taxi. Updated description",
        "longName":"Big Yellow Taxi",
        "latitude":51.060386316691,
        "longitude":-114.087524414062,
        "tags": ["big", "yellow", "taxi"]
}

Deleting a Sensor

Deleting a sensor is done by deleting the sensor resource.

To delete a sensor owned by the current user:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}
Privacy Private
Format not applicable
Method DELETE
Returns HTTP status code; No Response 204 if successful

example

curl --user {id}:{password} --request DELETE
'http://wotkit.sensetecnic.com/api/sensors/test-sensor'

Sensor Subscriptions

Sensor subscriptions are handled using the /subscribe URL.

Get Sensor Subscriptions

To view sensors that the current user is subscribed to:

URL http://wotkit.sensetecnic.com/api/subscribe
Privacy Private
Format json
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

Subscribe

To subscribe to a non-private sensor or private sensor owned by the current user:

URL http://wotkit.sensetecnic.com/api/subscribe/{sensorname}
Privacy Private
Format json
Method PUT
Returns HTTP status code; No Content 204 if successful

Unsubscribe

To unsubscribe from a sensor:

URL http://wotkit.sensetecnic.com/api/subscribe/{sensorname}
Privacy Private
Format json
Method DELETE
Returns HTTP status code; No Content 204 if successful

Sensor Fields

Sensor fields are the fields of data saved in a sensor stream. Together they make up the sensor schema.

Each sensor has the following default fields:

Field Name Information
value The numerical data for the sensor. Required.
lat The latitude of the sensor. Required.
lng The longitude of the sensor. Required.
message The string message for the sensor. Not Required.

Each sensor field consists of the following:

Field Name Information
name The unique name for the sensor field. It is required when creating/updating/deleting a field and cannot be changed.
longName The display name for the field.
type Can be “NUMBER” or “STRING”. It is required when creating/updating a field.
required Is a boolean field. If true, data sent to a sensor must include this field or an error will result. Optional.
units Is a string. Optional.
index The numerical index of the field used to maintain ordering. This field is automatically generated by the system and is read only.
value The last value of this sensor field received by the sensor when sending data. This is a read only field set when the sensor receives data for this field.
lastUpdate The time stamp of the last value sent to the field. This is a read only field set when the sensor receives data for this field.

Querying Sensor Fields

To retrieve the sensor fields for a specific sensor:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}/fields
Privacy Public or Private
Format json
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

To query a single sensor field for a specific sensor:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}/fields/{fieldName}
Privacy Public or Private
Format json
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

Updating a Sensor Field

You can update or add a sensor field by performing a PUT operation to the specified field. The field information is supplied in a JSON format.

If the sensor already has a field with the given name, it will be updated with new information. Otherwise, a new field with that name will be created.

Notes:

  • When inputting field data, the sub-fields “name” and “type” are required-both for adding a new field or updating an existing one.
  • Read only sub-fields such as index, value and lastUpdate should not be supplied.
  • The “name” sub-field of an existing field cannot be updated.
  • For user defined fields, the “longName”, “type”, “required”, and “units” sub-fields may be updated.
  • You cannot change the index of a field. If a field is deleted, the index of the following fields will be adjusted to maintain the field order.

To update/add a sensor field:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}/fields/{fieldname}
Privacy Private
Format json
Method PUT
Returns HTTP status code; No Content 204 if successful

For instance, to create a new field called “test-field”:

example

curl --user {id}:{password} --request POST
--header "Content-Type: application/json" --data-binary @field-data.txt
'http://wotkit.sensetecnic.com/api/sensors/test-sensor/fields/test-field'

The file field-data.txt could contain the following. (This is the minimal information needed to create a new field.)

{
        "name":"test-field",
        "type":"STRING"
}

To then update “test-field” sub-fields, the curl command would be used to send a PUT request.

example

curl --user {id}:{password} --request PUT
--header "Content-Type: application/json" --data-binary @field-data.txt
'http://wotkit.sensetecnic.com/api/sensors/test-sensor/fields/test-field'

And ‘’field-data.txt’’ could now contain the following.

{
        "name":"test-field",
        "type":"NUMBER",
        "longName":"Test Field",
        "required":true,
        "units":"mm"
}

Deleting a Sensor Field

You can delete an existing sensor field by performing a DELETE and including the field name in the URL.

To delete a sensor field:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}/fields/{fieldname}
Privacy Private
Format n/a
Method DELETE
Returns HTTP status code; No Content 204 if successful

Sensor Data

In the WoTKit, sensor data consists of a timestamp followed by one or more named fields. There are a number of reserved fields supported by the WoTKit:

Reserved field name Description
timestamp the time that the sensor data was collected. This is a long integer representing the number of milliseconds from Jan 1, 1970 UTC. Optional; if not supplied, a server-supplied timestamp will be used.
id a unique identifier for the data reading. This is to distinguish one reading from another when they share the same timestamp. Read only; This field is read only and should not be sent by the client when sending new data.
sensor_id the globally unique sensor id that produced the data. Read only; This is a read only field generated by the wotkit that should not be sent by a client when sending new data.
sensor_name the globally unique sensor name, in the form {username}.{sensorname}. Read only; This is a read only field and should not be sent by the client when sending new data.

When a new sensor is created, a number of default fields are created by the wotkit for a sensor as follows. Note that these can be changed by editing the sensor fields.

In addition to these reserved fields, additional required or optional fields can be added by updating the sensor fields in the WoTKit UI or sensor_fields in the API.

Note

* Python’s time.time() function generates the system time in seconds, not milliseconds.

To convert this to an integer in milliseconds use int(time.time()*1000). Using Java: System.currentTime().

Sending New Data

To send new data to a sensor, POST name value pairs corresponding to the data fields to the /sensors/{sensorname}/data URL.

There is no need to provide a timestamp since it will be assigned by the server. Data posted to the system will be processed in real time.

To send new data:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}/data
Privacy Private
Format not applicable
Method POST
Returns HTTP status code; No Response 201 (Created) if successful

example

curl --user {id}:{password} --request POST
-d value=5 -d lng=6 -d lat=7 'http://wotkit.sensetecnic.com/api/sensors/test-sensor/data'

Sending Bulk Data

To send a range of data, you PUT data (rather than POST) data into the system. Note that data PUT into the WoTKit will not be processed in real time, since it occurred in the past

  • The data sent must contain a list of JSON objects containing a timestamp and a value.
  • If providing a single piece of data, existing data with the provided timestamp will be deleted and replaced. Otherwise, the new data will be added.
  • If providing a range of data, any existing data within this timestamp range will be deleted and replaced by the new data.

To update data:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}/data
Privacy Private
Format JSON
Method PUT
Returns HTTP status code; No Response 204 if successful

Example of valid data:

[{"timestamp":"2012-12-12T03:34:28.626Z","value":67.0,"lng":-123.1404,"lat":49.20532},
{"timestamp":"2012-12-12T03:34:28.665Z","value":63.0,"lng":-123.14054,"lat":49.20554},
{"timestamp":"2012-12-12T03:34:31.621Z","value":52.0,"lng":-123.14063,"lat":49.20559},
{"timestamp":"2012-12-12T03:34:35.121Z","value":68.0,"lng":-123.14057,"lat":49.20716},
{"timestamp":"2012-12-12T03:34:38.625Z","value":51.0,"lng":-123.14049,"lat":49.20757},
{"timestamp":"2012-12-12T03:34:42.126Z","value":55.0,"lng":-123.14044,"lat":49.20854},
{"timestamp":"2012-12-12T03:34:45.621Z","value":56.0,"lng":-123.14215,"lat":49.20855},
{"timestamp":"2012-12-12T03:34:49.122Z","value":55.0,"lng":-123.14727,"lat":49.20862},
{"timestamp":"2012-12-12T03:34:52.619Z","value":59.0,"lng":-123.14765,"lat":49.20868}]

example

curl --user {id}:{password} --request PUT --data-binary @data.txt
'http://wotkit.sensetecnic.com/api/sensors/test-sensor/data'

where data.txt contains JSON data similar to the above JSON array.

Deleting Data

Currently you can only delete data by timestamp, where timestamp is in numeric or ISO form. Note that if more than one sensor data point has the same timestamp, they all will be deleted.

To delete data:

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}/data/{timestamp}
Privacy Private
Format not applicable
Method DELETE
Returns HTTP status code; No Response 204 if successful

Raw Data Retrieval

To retrieve raw data use the following:

URL http://wotkit.sensetecnic.com/api/sensors/{sensor-name}/data?{query-params}
Privacy Public or Private
Format json
Method GET
Returns On success, OK 200 with a list of timestamped data records.

The query parameters supported are the following:

Name Value Description
start the absolute start time of the range of data selected in milliseconds. (Defaults to current time.) May only be used in combination with another parameter.
end the absolute end time of the range of data in milliseconds
after the relative time after the start time, e.g. after=300000 would be 5 minutes after the start time (Start time MUST also be provided.)
afterE the number of elements after the start element or time. (Start time MUST also be provided.)
before the relative time before the start time. E.g. data from the last hour would be before=3600000 (If not provided, start time default to current time.)
beforeE the number of elements before the start time. E.g. to get the last 1000, use beforeE=1000 (If not provided, start time default to current time.)
reverse true: order the data from newest to oldest; false (default):order from oldest to newest

Note

These queries looks for timestamps > “start” and timestamps <= “end”

Formatted Data Retrieval

To retrieve data in a format suitable for Google Visualizations, we support an additional resource for retrieving data called the dataTable.

URL http://wotkit.sensetecnic.com/api/sensors/{sensor-name}/dataTable?{query-params}
Privacy Public or Private
Format json
Method GET
Returns On success, OK 200 with a list of timestamped data records.

In addition to the above query parameters, the following parameters are also supported:

   
tqx A set of colon-delimited key/value pairs for standard parameters, defined here.
tq A SQL clause to select and process data fields to return, explained here.

Note

When using tq sql queries, they must be url encoded. When using tqx name/value pairs, the reqId parameter is necessary.


For instance, the following would take the “test-sensor”, select all data where value was greater than 20, and display the output as an html table.


Aggregated Data Retrieval

Aggregated data retrieval allows one to receive data from multiple sensors, queried using the same parameters as when searching for sensors or sensor data. The query must be specified using one of the following 5 patterns.

Pattern 1 - With Start/End

start The most recent starting time of the query. This value is optional and defaults to the current time.
end A timestamp before the start time.
limit Specifies the limit to return. This value is optional, with a default value of 1000.
offset Specifies the offset to return. This value is optional, with a default value of 0.

Pattern 2 - With Start/After

start A starting timestamp.
after A relative timestamp after start.
limit Specifies the limit to return. This value is optional, with a default value of 1000
offset Specifies the offset to return. This value is optional, with a default value of 0

Pattern 3 - With Start/Before

start A starting timestamp.
before A relative timestamp before start.
limit Specifies the limit to return. This value is optional, with a default value of 1000
offset Specifies the offset to return. This value is optional, with a default value of 0

Pattern 4 - With Start/BeforeE

start A starting timestamp.
beforeE The number of elements to return before start
offset Specifies the offset to return. This value is optional, with a default value of 0

Pattern 5 - With Start/AfterE

start A starting timestamp.
afterE The number of elements to return after start
offset Specifies the offset to return. This value is optional, with a default value of 0

The following parameters may be added to any of the above patterns: * scope * tags * private (deprecated, use visibility instead) * visibility * text * active * orderBy * sensor: which groups data by sensor_id * time (default): which orders data by timestamp, regardless of the sensor it comes from.

To receive data from more that one sensor, use the following:

URL http://wotkit.sensetecnic.com/api/data?{query-param}={query-value}&{param}={value}...
Privacy Public or Private
Format json
Method GET
Returns On success, OK 200 with a list of timestamped data records.

Sensor Control Channel: Actuators

An actuator is a sensor that uses a control channel to actuate things. Rather than POSTing data to the WoTKit, an actuator script or gateway polls the control URL for messages to affect the actuator, to do things like move a servo motor, turn a light on or off, or display a message on a screen.

To demonstrate actuators, the control visualization that comes with the WoTKit sends three type of events to the sensor control channel:

   
button ‘on’ or ‘off’ to control a light, or switch.
message text message for use by the actuator, for example to be shown on a message board or display.
slider a numeric value to affect the position of something, such as a server motor.

Any name/value pair can be sent to an actuator in a message, these are just the names sent by the visualization.

Sending Actuator Messages

To send a control message to a sensor (actuator), POST name value pairs corresponding to the data fields to the /sensors/{sensorname}/message URL.

URL http://wotkit.sensetecnic.com/api/sensors/{sensorname}/message
Privacy Public or Private
Format json
Method POST
Returns On success, OK 200 (no content).

Receiving Actuator Messages

In order to receive messages from an actuator, you must own that actuator.

Subscribing to an Actuator Controller

First, subscribe to the controller by POSTing to /api/control/sub/{sensor-name}. In return, we receive a json object containing a subscription id.

URL http://wotkit.sensetecnic.com/api/control/sub/{sensor-name}
Privacy Private
Format json
Method POST
Returns On success, OK 200 with JSON containing subscription id.

Example subscription id returned:

{
        "subscription":1234
}
Query an Actuator

Using the subscription id, then poll the following resource: /api/control/sub/{subscription-id}?wait=10. The wait specifies the time to wait in seconds for a control message. If unspecified, a default wait time of 10 seconds is used. The maximum wait time is 20 seconds. The server will respond on timeout, or when a control messages is received.

URL http://wotkit.sensetecnic.com/api/control/sub/{subscription-id}?wait={wait-time}
Privacy Private
Format json
Method GET
Returns On success, OK 200 with JSON containing control messages.

To illustrate, the following code snippet uses HTTP client libraries to subscribe and get actuator messages from the server, and then print the data. Normally, the script would change the state of an actuator like a servo or a switch based on the message received.

# sample actuator code
import urllib
import urllib2
import base64
import httplib

try:
        import json
except ImportError:
        import simplejson as json

#note trailing slash to ensure .testactuator is not dropped as a file extension
actuator="mike.testactuator/"

# authentication setup
conn = httplib.HTTPConnection("wotkit.sensetecnic.com")
base64string = base64.encodestring('%s:%s' % ('{id}', '{password}'))[:-1]
authheader =  "Basic %s" % base64string
headers = {'Authorization': authheader}

#subscribe to the controller and get the subscriber ID
conn.request("POST", "/api/control/sub/" + actuator, headers=headers)
response = conn.getresponse()
data = response.read()

json_object = json.loads(data)
subId = json_object['subscription']

#loop to long poll for actuator messages
while 1:
        print "request started for subId: " + str(subId)
        conn.request("GET", "/api/control/sub/" + str(subId) + "?wait=10", headers=headers)
        response = conn.getresponse()
        data = response.read()

        json_object = json.loads(data)

                # change state of actuator based on json message received
        print json_object

Tags

You can get a list of tags, either the most used by public sensors or by a sensor query.

Querying Sensor Tags

A list of matching tags. The query parameters are as follows:

Name Value Description
scope
all-all tags used by sensors that the current user has access to; | subscribed-tags for sensors the user has subscribed to; | contributed-tags for sensors the user has contributed to the system.
private
true - private sensors only; false - public only
(Deprecated, use visibility instead)
visibility filter by the visibility of the sensors, either of public, organization or private
text text to search in the sensors’s name, long name and description
active when true, only returns tags for sensors that have been updated in the last 15 minutes.
offset offset into list of tags for paging
limit limit to show for paging. The maximum number of tags to display is 1000.
location
geo coordinates for a bounding box to search within.
Format is yy.yyy,xx.xxx:yy.yyy,xx.xxx, the order of the coordinates are North,West:South,East. Example: location=56.89,-114.55:17.43,-106.219

To query for tags, add query parameters after the sensors URL as follows:

URL http://wotkit.sensetecnic.com/api/tags?{query}
Privacy Public or Private
Format json
Method GET
Returns On error, an appropriate HTTP status code; On success, OK 200 and a list of tag count objects matching the query.

example

curl --user {id}:{password}
"http://wotkit.sensetecnic.com/api/sensors/tags?text=bicycles"

Output:

[
        {
                'name': 'bicycle',
                'count': 3,
                'lastUsed': 1370887340845
        },{
                'name': 'bike',
                'count': 3,
                'lastUsed': 1350687440754
        },{
                'name': 'montreal',
                'count': 1,
                'lastUsed': 1365857340341
        }
]

The lastUsed field represents the creation date of the newest sensor that uses this tag.

Users

Admins can list, create and delete users from the system.

List/Query Users

A list of matching user may be queried by the system. The optional query parameters are as follows:

Name Value Description
text text to search for in the username, first name and/or last name
reverse true to get the oldest users first; false (default) to get newest first
offset offset into list of users for paging
limit limit to show for paging. The maximum number of users to display is 1000.

To query for users, add query parameters after the sensors URL as follows:

URL http://wotkit.sensetecnic.com/api/users?{query}
Privacy Admin
Format json
Method GET
Returns On error, an appropriate HTTP status code; On success, OK 200 and a list of users matching the query.

Viewing a Single User

To view a single user, query by username or id as follows:

URL http://wotkit.sensetecnic.com/api/users/{username}
Privacy Admin
Format json
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

example

curl --user {id}:{password}
"http://wotkit.sensetecnic.com/api/users/1"

Output:

{
        'id': 1,
        'username': 'sensetecnic',
        'email': 'info@sensetecnic.com',
        'firstname': 'Sense',
        'lastname': 'Tecnic',
        'enabled': True,
        'accountNonExpired': True,
        'accountNonLocked': True,
        'credentialsNonExpired': True
}

Creating/Registering a User

To register a user, you POST a user resource to the url /users.

  • The user resources is a JSON object.
  • The “username”, “firstname”, “lastname”, “email”, and “password” fields are required when creating a user.
  • The “timeZone” field is optional and defaults to UTC.
  • The username must be at least 4 characters long.

To create a user:

URL http://wotkit.sensetecnic.com/api/users
Privacy Admin
Format json
Method POST
Returns HTTP status code; Created 201 if successful; Bad Request 400 if user is invalid; Conflict 409 if user with the same username already exists

Updating a User

  • You may only update the following fields: “firstname”, “lastname”, “email”, “timeZone” and “password”.
  • Only fields that will be present in the JSON object will be updated. The rest will remain unchanged.

To update a user:

URL http://wotkit.sensetecnic.com/api/users/{username}
Privacy Admin
Format json
Method PUT
Returns HTTP status code; No Content 204 if successful

Deleting a User

Deleting a user is done by deleting the user resource.

To delete a user:

URL http://wotkit.sensetecnic.com/api/users/{username}
Privacy Admin
Format not applicable
Method DELETE
Returns HTTP status code; No Response 204 if successful

Organizations

All users can see all organizations, and admins can manipulate them.

List/Query Organizations

A list of matching organizations may be queried by the system. The optional query parameters are as follows:

Name Value Description
text text to search for in the name, long name and/or description
offset offset into list of organizations for paging
limit limit to show for paging. The maximum number of organizations to display is 1000.

To query for organizations, add query parameters after the sensors URL as follows:

URL http://wotkit.sensetecnic.com/api/orgs?{query}
Privacy Public
Format json
Method GET
Returns On error, an appropriate HTTP status code; On success, OK 200 and a list of organizations matching the query from newest to oldest.

Viewing a Single Organization

To view a single organization, query by name:

URL http://wotkit.sensetecnic.com/api/orgs/{org-name}
Privacy Public
Format json
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

Output:

{
        "id": 4764,
        "name": "electric-inc",
        "longName": "Electric, Inc.",
        "description": "Electric, Inc. was established in 1970.",
        "imageUrl": "http://www.example.com/electric-inc-logo.png"
}

Creating/Registering an Organization

To register a new organization, you POST an organization resource to the url /org.

  • The organization resources is a JSON object.
  • The “name” and “longName” fields are required and must both be at least 4 characters long.
  • The “imageUrl” and “description” fields are optional.

To create an organization:

URL http://wotkit.sensetecnic.com/api/orgs
Privacy Admin
Format json
Method POST
Returns HTTP status code; Created 201 if successful; Bad Request 400 if organization is invalid; Conflict 409 if an organization with the same name already exists

Updating an Organization

  • You may update any fields except “id” and “name”.
  • Only fields that are present in the JSON object will be updated.

To update an organization:

URL http://wotkit.sensetecnic.com/api/orgs/{org-name}
Privacy Admin
Format json
Method PUT
Returns HTTP status code; No Content 204 if successful

Deleting an Organization

Deleting an organization is done by deleting the organization resource.

To delete a user:

URL http://wotkit.sensetecnic.com/api/orgs/{org-name}
Privacy Admin
Format not applicable
Method DELETE
Returns HTTP status code; No Content 204 if successful

Organization Membership

List all members of an Organization

To query for organization members:

URL http://wotkit.sensetecnic.com/api/orgs/{org-name}/members
Privacy Admin
Format not applicable
Method GET
Returns On error, an appropriate HTTP status code; On success, OK 200 and a list of organization members.

Add new members to an Organization

To add new members to an organization, post a JSON array of usernames:

URL http://wotkit.sensetecnic.com/api/orgs/{org-name}/members
Privacy Admin
Format json
Method POST
Returns On error, an appropriate HTTP status code; On success, OK 204.

Usernames that are already members, or usernames that do not exist, will be ignored.

For instance, to add the users “abe”, “beth”, “cecilia” and “dylan” to the organization “electric-inc”:

example

curl --user {id}:{password} --request POST
--header "Content-Type: application/json" --data-binary @users-list.txt
'http://wotkit.sensetecnic.com/api/orgs/electric-inc/members'

The file users-list.txt would contain the following.

["abe", "beth", "cecilia", "dylan"]
Remove members from an Organization

To remove members from an organization, DELETE a JSON array of usernames:

URL http://wotkit.sensetecnic.com/api/orgs/{org-name}/members
Privacy Admin
Format json
Method DELETE
Returns On error, an appropriate HTTP status code; On success, OK 204.

Usernames that are not members, or usernames that do not exist, will be ignored.

Sensor Groups

Sensor Groups are used to logically organize related sensors. A Sensors can be a member of many groups.

Currently, all Sensor Groups have public visibility, but only the owner (creator) can add/remove sensors from the group.

Sensor Groups can be manipulated using a REST API in the following section

Sensor Group Format

All request body and response bodies use JSON. The following fields are present:

Field Name Type Required Notes
id Integer true The id contains a unique number which is used to identify the group
name String[4,50] true The name is a system-unique string identifier for the group. Names must be lowercase containing alphanumeric, underscores or hyphens [a-z0-9_-]. The first character must be an alphabetic character
longName String[,255] optional A readable name used for visual interfaces.
owner String[4,50] true The name of the group’s owner. This field is set by the system and cannot be modified.
description String[,255] optional A simple description of the group
imageUrl String[,255] optional A string url to an image which can be used to represent this group
sensors Array[Sensor] optional Contains a JSON list of sensors. This field is only useful for viewing sensors. To append/remove sensors from Sensor Groups, refer to Adding a Sensor to Sensor Group.

An example of a Sensor Group JSON would be follows:

{
  id: 49,
  name: "water-sensor",
  longName: "A water sensor",
  owner: "robertl",
  description: "This is a short description",
  imageUrl: "http://someurl.com/water-sensor.jpg"
  sensors: []
}

List Groups

Provides a list of groups on the system as an array using the JSON format specified in Sensor Group Format

URL http://wotkit.sensetecnic.com/api/groups/
Method GET
Returns OK 200, along with list

example

curl --user {id}:{password} --request GET 'http://wotkit.sensetecnic.com/api/groups'

Viewing a Single Sensor Group

Similar to listing a group, but retrieving only a single sensor. Replace {group-name} with group.id or group.name. The API accepts both formats

URL http://wotkit.sensetecnic.com/api/groups/{group-name}
Method GET
Returns OK 200

example

curl --user {id}:{password} --request GET 'http://wotkit.sensetecnic.com/api/groups'

Creating a Sensor Group

To create a sensor group, append the Sensor Group contents following Sensor Group Format.

On creation, the id and owner fields are ignored because they are system generated.

URL http://wotkit.sensetecnic.com/api/groups
Method POST
Returns If a sensor with the same name exists, ERROR 409. Otherwise, OK 204.

Modifying Sensor Group Fields

Modifying is similar to creation, the content is placed in the response body

Again, the id and owner fields in the JSON object are ignored if they are modified. The Sensor Group is specified by substituting {group-name} in the URL with either group.id or group.name. The API accepts both formats.

URL http://wotkit.sensetecnic.com/api/groups/{group-name}
Method PUT
Returns If user has no permissions to edit group, returns UNAUTHORIZED 401, otherwise OK 204

Deleting a Sensor Group

Deleting a Sensor Group is fairly trivial, assuming you are the owner of the group. A request body is unnecessary.

URL http://wotkit.sensetecnic.com/api/groups/{group-name}
Method DELETE
Returns If user has no permissions to edit group, returns UNAUTHORIZED 401, otherwise OK 204

Adding a Sensor to Sensor Group

This is done by invoking the URL by replacing the specified parameters where {group-name} can be group.id or group.name. {sensor-id} should be sensor.id.

URL http://wotkit.sensetecnic.com/api/groups/{group-name}/sensors/{sensor-id}
Method POST

The response will contain one of the following response codes.

Return Code Description
OK 204 No Content is given.
400 Sensor is already a member of sensor group
401 User is unauthorized to edit group.

Removing a Sensor from Sensor Group

The format is the same as Adding a Sensor to Sensor Group except replacing method with DELETE

URL http://wotkit.sensetecnic.com/api/groups/{group-name}/sensors/{sensor-id}
Method DELETE

The response will contain one of the following codes.

Return Code Description
OK 204 No Content is given. If a sensor does not exist in a group, this is also returned.
401 User is unauthorized to edit group

News

To get “news” (a list of interesting recent things that happened in the system):

URL http://wotkit.sensetecnic.com/api/news
Privacy Public
Format not applicable
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

Output:

[{
        'timestamp': 1370910428123,
        'title': u'The sensor "Light Sensor" has updated data.',
        'url': u'/sensors/5/monitor'
},{
        'timestamp': 1370910428855,
        'title': u'The sensor "api-data-test-1" has updated data.',
        'url': u'/sensors/40/monitor'
}]

Statistics

To get some statistics (eg. number of public sensors, active sensors, new sensors, etc...):

URL http://wotkit.sensetecnic.com/api/stats
Privacy Public
Format not applicable
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

Output:

{
        'total': 65437,
        'active': 43474,
        'new': {
                'day': 53,
                'week': 457,
                'month': 9123,
                'year': 40532
        }
}

Smart Streets Authentication

The WoTKit API for Smart Streets supports basic authentication using user name and password, WoTKit keys, as well as a developer key. Note that Smart Streets does not support OAuth2.

Authenticating using Smart Streets Developer Keys

More on this to come

V2 API Reference

This documentation is a work in process. It’s not production ready yet – but feel free to look around.

Sensor Data

In the WoTKit, sensor data consists of a timestamp followed by one or more named fields. There are a number of reserved fields supported by the WoTKit:

Reserved field name Description
timestamp the time that the sensor data was collected. This is a long integer representing the number of milliseconds from Jan 1, 1970 UTC. Optional; if not supplied, a server-supplied timestamp will be used.
id a unique identifier for the data reading. This is to distinguish one reading from another when they share the same timestamp. Read only; This field is read only and should not be sent by the client when sending new data.
sensor_id the globally unique sensor id that produced the data. Read only; This is a read only field generated by the wotkit that should not be sent by a client when sending new data.
sensor_name the globally unique sensor name, in the form {username}.{sensorname}. Read only; This is a read only field and should not be sent by the client when sending new data.

When a new sensor is created, a number of default fields are created by the wotkit for a sensor as follows. Note that these can be changed by editing the sensor fields.

Default field name Description
lat the current latitude location of the sensor in degrees (number). Needed for map visualizations.
lng the current longitude location of the sensor in degrees (number). Needed for map visualizations.
value the primary value of the sensor data collected (number). Needed for most visualizations.
message a text message, for example a twitter message (text). Needed for text/newsfeed visualizations.

In addition to these default fields, additional fields can be added by updating the sensor fields in the WoTKit UI or Sensor Fields in the API.

Note

Python’s time.time() function generates the system time in seconds, not milliseconds. To convert this to an integer in milliseconds use int(time.time()*1000).

In Javascript: var d = new Date(); d.getTime();

In Java: System.currentTime().

Sending New Data

To send new data to a sensor, POST name value pairs corresponding to the data fields to /sensors/{sensorname}/data. There is no need to supply the sensor id, or sensor name fields since the sensor is specified in the URL.

If a timestamp is not provided in the request body, it will be set to the current time by the the server.

To send new data:

URL http://wotkit.sensetecnic.com/api/v2/sensors/{sensorname}/data
Privacy Private
Format not applicable
Method POST
Returns HTTP status code; No Response 201 (Created) if successful

Example

curl --user {id}:{password} --request POST -d value=5 -d lng=6 -d lat=7
'http://wotkit.sensetecnic.com/api/sensors/test-sensor/data'

Updating a Range of Historical Data

To insert or update a range of historical data, you PUT data (rather than POST) data into the system. Note that data PUT into the WoTKit will not be processed in real time, since it occurred in the past.

  • The request body must be a list of JSON objects containing a timestamp value.
  • Any existing data within this timestamp range will be deleted and replaced by the data supplied.

To update data:

URL http://wotkit.sensetecnic.com/api/v2/sensors/{sensorname}/data
Privacy Private
Format JSON
Method PUT
Returns HTTP status code; No Response 204 if successful

Example of valid data:

[{"timestamp":"2012-12-12T03:34:28.626Z","value":67.0,"lng":-123.1404,"lat":49.20532},
{"timestamp":"2012-12-12T03:34:28.665Z","value":63.0,"lng":-123.14054,"lat":49.20554},
{"timestamp":"2012-12-12T03:34:31.621Z","value":52.0,"lng":-123.14063,"lat":49.20559},
{"timestamp":"2012-12-12T03:34:35.121Z","value":68.0,"lng":-123.14057,"lat":49.20716},
{"timestamp":"2012-12-12T03:34:38.625Z","value":51.0,"lng":-123.14049,"lat":49.20757},
{"timestamp":"2012-12-12T03:34:42.126Z","value":55.0,"lng":-123.14044,"lat":49.20854},
{"timestamp":"2012-12-12T03:34:45.621Z","value":56.0,"lng":-123.14215,"lat":49.20855},
{"timestamp":"2012-12-12T03:34:49.122Z","value":55.0,"lng":-123.14727,"lat":49.20862},
{"timestamp":"2012-12-12T03:34:52.619Z","value":59.0,"lng":-123.14765,"lat":49.20868}]

example

curl --user {id}:{password} --request PUT --data-binary @data.txt
'http://wotkit.sensetecnic.com/api/sensors/test-sensor/data'

where data.txt contains JSON data similar to the above JSON array.

Retrieving a Single Data Item

If you know the data element’s id, you can query for a single data element using the following query.

URL http://wotkit.sensetecnic.com/api/v2/sensors/{sensor-name}/data/{data_id}
Privacy Public or Private, depending on sensor privacy
Format json
Method GET
Returns On success, OK 200 with a list of timestamped data records.

Retrieving Data Using Query

To retrive sensor data over a time range you can use the following endpoint. An interactive guide on how to use this endpoint is available at: Querying Sensor Data.

URL http://wotkit.sensetecnic.com/api/v2/sensors/{sensor-name}/data
Privacy Public or Private, depending on sensor privacy
Format json
Method GET
Returns On success, OK 200 with a list of timestamped data records.

The query parameters supported are the following. They can only be used together if they appear in the same Group below.

Parameter Group Type Description
recent_t 1 integer Gets the elements up to recent_t milliseconds ago
recent_n 2 integer Gets the n recent elements
start 3 timestamp The absolute starting point (in milliseconds since Jan 1, 1970).
start_id 3 id The starting id of sensor_data at timestamp start. Used for paging and to distinguish data elements that share the same timestamp.
end 3 timestamp The absolute ending timestamp (in milliseconds since Jan 1, 1970)
end_id 3 timestamp The end id of sensor_data with timestamp end. Used for paging.
limit [2,3] integer specifies how many datapoints to see on each response

Delete Data by Id

Same as Retrieving a Single Data Item instead using HTTP Delete.

URL http://wotkit.sensetecnic.com/api/v2/sensors/{sensorname}/data/{data_id}
Privacy Private
Format not applicable
Method DELETE
Returns HTTP status code; No Response 204 if successful

Delete Data using Data Query

Can delete using query parameters in Retrieving Data Using Query with the restriction on only using group 3 parameters.

URL http://wotkit.sensetecnic.com/api/v2/sensors/{sensorname}/data
Privacy Private
Format not applicable
Method DELETE
Returns HTTP status code; No Response 204 if successful

Alerts

An alert is set up by an user for notification purpose. Multiple conditions can be attached to an alert. Each condition is associated with a sensor field. An alert fires and sends a message to the owner’s inbox and email (if email functionality is enabled) when all of its attached conditions are satisfied. Currently, each user is limited to have a maximum of 20 alerts.

An alert has the following attributes:

Name Value Description
id the numeric id of the alert. It is automatically assigned when alert is created.
name ** the name of the alert.
longName longer display name of the alert.
description ** a description of the alert.
owner the user that creates the alert. The value of this field is automatically assigned as a user creates an alert.
disabled
the on/off state of the alert.
- If ‘disabled’ is ‘true’, the alert is switched off; it switches on if otherwise.
inProgress
whether conditions are still true after an alert has fired.
- inProgress is ‘true’ if all alert conditions remain true after an alert has fired. It becomes ‘false’ when any condition turns false. An alert gets fired when its inProgress state changes from false to true.
template ** The message template that is sent to the inbox when alert is fired.
sendEmail ** A boolean to enable/disable send email functionaity.
conditions the list of alert conditions

** Required when creating a new alert.

An alert condition is composed of a sensor field, an operator for evaluation, and a value. It has the following attributes:

Name Value Description
sensorId the ID of the sensor associated with the condition
field the field name to be compared of the chosen sensor
operator
the conditon operator, its value can be one of following:
‘LT’: Less Than
‘LE’: Less Than Or Equal To
‘GT’: Greater Than
‘GE’: Greater Than Or Equal To
‘EQ’: Equal
‘NEQ’: Not Equal
‘NULL’: Is Null
‘NOTNULL’: Is Not Null
value value that the operator compares with

Listing Alerts of an User

To view a list of “alerts” created by an user:

URL http://wotkit.sensetecnic.com/api/v2/alerts
Privacy Private
Format JSON
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

example

curl --user {id}:{password} "http://wotkit.sensetecnic.com/api/v2/alerts"

Sample Output:

    [{
    "id": 6,
    "owner": "crysng",
    "name": "temperature-alert",
    "longName": "Temperature Alert",
    "description": "This alert notifies user when Hydrogen Sulfide content and Wind speed is too high at Burnaby Burmount. ",
    "disabled": false,
    "inProgress": false,
    "template": "Hydrogen Sulfide and wind speed is high!",
    "sendEmail": true,
    "email": "rottencherries@hotmail.com",
    "conditions": [
        {
            "sensorId": 241,
            "field": "h2s",
            "operator": "GT",
            "value": 10
        },
        {
            "sensorId": 241,
            "field": "wspd",
            "operator": "GE",
            "value": 50
        }
    ]
},
{
    "id": 5,
    "owner": "crysng",
    "name": "test",
    "longName": "Moisture Sensor Alert",
    "description": "This alert fires when moisture level is too low. ",
    "disabled": false,
    "inProgress": false,
    "template": "Moisture level is too low, water the plant now!",
    "sendEmail": true,
    "email": "someone@email.com",
    "conditions": [
        {
            "sensorId": 504,
            "field": "value",
            "operator": "LT",
            "value": 3
        }
    ]
}]

Viewing an Alert

To view an alert, query the alert by its id as followed:

URL http://wotkit.sensetecnic.com/api/v2/alerts/{alert id}
Privacy Private
Format json
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

example

curl --user {id}:{password}
"http://wotkit.sensetecnic.com/api/v2/alerts/5"

Output:

    {
    "id": 5,
    "owner": "crysng",
    "name": "test",
    "longName": "Moisture Sensor Alert",
    "description": "This alert fires when moisture level is too low. ",
    "disabled": false,
    "inProgress": false,
    "template": "Moisture level is too low, water the plant now!",
    "sendEmail": true,
    "email": "someone@email.com",
    "conditions": [
        {
            "sensorId": 504,
            "field": "value",
            "operator": "LT",
            "value": 3
        }
    ]
}

Creating Alerts

To create an alert, you POST an alert resource to the url /v2/alerts.

  • The alert resource is a JSON object.
  • The “name”, “description”, “template”, and “sendEmail” fields are required when creating an alert.
  • The alert name must be at least 4 characters long, contain only lowercase letters, numbers, dashes and underscores, and can start with a lowercase letter or an underscore only.

To create an alert:

URL http://wotkit.sensetecnic.com/api/v2/alerts
Privacy Private
Format json
Method POST
Returns HTTP status code; Created 201 if successful; Bad Request 400 if sensor is invalid; Conflict 409 if alert with the same name already exists

example1

curl --user {id}:{password} --request POST --header "Content-Type: application/json"
--data-binary @test-alert.txt 'http://wotkit.sensetecnic.com/api/v2/alerts'

For this example, the file test-alert.txt contains the following. This is the minimal information needed to create an alert.

{
        "name":"test alert",
        "description":"A test alert.",
        "template":"Template for test alert",
        "sendEmail":false
}

example2

Now, let’s create an alert with additional information and conditions. The file test-alert.txt contains the following.

{
        "name": "test alert 2",
        "longName": "Test Alert 2",
        "description": "This is test 2. ",
        "disabled": false,
        "template": "The alert test 2 has fired!! ",
        "sendEmail": true,
        "email": "someone@email.com",
        "conditions": [
        {
                "sensorId": 504,
                "field": "value",
                "operator": "LT",
                "value": 3
        },
        {
                "sensorId": 24,
                "field": "data",
                "operator": "NOTNULL"
        }
        ]
}

Updating Alerts

Updating an alert is the same as creating a new alert other than PUT is used and the alert id is included in the URL.

Note that all top level fields supplied will be updated.

  • You may update any fields except “id”, and “owner”.
  • Only fields that are present in the JSON object will be updated.

To update an alert owned by the current user:

URL http://wotkit.sensetecnic.com/api/v2/alerts/{alert id}
Privacy Private
Format json
Method PUT
Returns HTTP status code; No Content 204 if successful

For instance, to update an alert:

example

curl --user {id}:{password} --request PUT --header "Content-Type: application/json"
--data-binary @update-alert.txt 'http://wotkit.sensetecnic.com/api/v2/alerts/{alert id}'

The file update-alert.txt would contain the following:

{
        "longName": "New Alert Name",
        "description":"Updated Description"
}

Deleting Alerts

Deleting an alert is done by deleting the alert resource.

To delete an alert owned by the current user:

URL http://wotkit.sensetecnic.com/api/v2/alertss/{alert id}
Privacy Private
Format not applicable
Method DELETE
Returns HTTP status code; No Response 204 if successful

example

curl --user {id}:{password} --request DELETE
'http://wotkit.sensetecnic.com/api/v2/alerts/{alert id}'

Inbox

The Inbox is the storage place for inbox messages that are sent by an alert firing event.

An inbox message has the following attributes:

Name Value Description
id the numeric id of the message. It is automatically generated.
timestamp the time that the message is sent to inbox.
title title of the inbox message
message the message content
sendEmail the boolean variable of whether email functionality is enabled
read the flag of whether the message is read
sent the flag of whether an email is sent

Listing Inbox Messages of an User

To view a list of “inbox messages” of an user:

URL http://wotkit.sensetecnic.com/api/v2/inbox
Privacy Private
Format JSON
Method GET
Returns Appropriate HTTP status code; OK 200 - if successful

example

curl --user {id}:{password} "http://wotkit.sensetecnic.com/api/v2/inbox"

Sample Inbox Messages Output:

[
        {
        "id": 5,
        "timestamp": "2014-04-17T00:51:41.701Z",
        "title": "Moisture Sensor Alert",
        "message": "Moisture level is too low, water the plant now!",
        "sendEmail": true,
        "email": "someone@email.com",
        "read": false,
        "sent": false
        }
]

Indices and tables