FIWARE NGSI APIv2 Walkthrough

Introduction

This walkthrough adopts a practical approach that we hope will help our readers to get familiar with the Orion Context Broker and have some fun in the process :).

The walkthrough is based on the NGSIv2 Specification, that can be found in Apiary format here. You should also have a look at the NGSIv2 implementation notes.

The main section is context management. It describes the basic context broker functionality for context management (information about entities, such as the temperature of a car). Context availability management (information not about the entities themselves, but about the providers of that information) is also described as part of this document.

Before starting (or if you get lost in the middle and need to start from scratch :) ), restart Orion Context Broker as described in starting the broker for the tutorials.

It is recommended to get familiar with the theoretical concepts on which the NGSI model is based before starting. E.g. entities, attributes, etc. Have a look at the FIWARE documentation about this, e.g. this public presentation.

Top

Before starting...

Before starting, let's introduce the example case that is used in the tutorials and how to run and interact with Orion Context Broker.

Top

Example case

Let's assume we have a building with several rooms and that we want to use Orion Context Broker to manage its context information. The rooms are Room1, Room2, Room3 and Room4 and each room has two sensors: temperature and (atmospheric) pressure, except Room4 that only has a pressure sensor. In addition, let's consider that we have two cars (Car1 and Car2) with sensors able to measure speed and location (in GPS sense).

The Orion Context Broker interacts with context producer applications (which provide sensor information) and a context consumer application (which processes that information, e.g. to show it in a graphical user interface). We will play the role of both kinds of applications in the tutorials.

Top

Starting the broker for the tutorials

Before starting, you need to install the broker as described in the Installation and Administration Guide.

The tutorials assume that you don't have any previous content in the Orion Context Broker database. In order make sure it is so, please follow the delete database procedure.

To start the broker (either as root or using the sudo command):

/etc/init.d/contextBroker start

To restart the broker (either as root or with sudo):

/etc/init.d/contextBroker restart

Top

Starting accumulator server

Some parts of the tutorial (the ones related with subscriptions and notifications) require a process to play the role of the consumer application, able to receive notifications. To that end, please download the accumulator script, available in GitHub. It is a very simple "dummy" application that simply listens to a given URL (the example below uses localhost:1028/accumulate, but a different host and/or port can be specified) and echoes whatever it receives in the terminal window where it is executed. Run it using the following command:

# cd /dir/where/accumulator-server/is/downloaded
# chmod a+x accumulator-server.py
# ./accumulator-server.py --port 1028 --url /accumulate --host ::1 --pretty-print -v

Note this script requires Flask version 1.0.2 and pyOpenSSL version 19.0.0, which can be installed using pip install Flask==1.0.2 and pip install pyOpenSSL==19.0.0. In case of conflict with your base operating system Python installation, we recommend to use virtualenv.

Top

Issuing commands to the broker

To issue requests to the broker, you can use the curl command line tool. curl is chosen because it is almost ubiquitous in any GNU/Linux system and simplifies including examples in this document that can easily be copied and pasted. Of course, it is not mandatory to use it, you can use any REST client tool instead (e.g. RESTClient). Indeed, in a real case, you will probably interact with the Orion Context Broker using a programming language library implementing the REST client part of your application.

The basic patterns for all the curl examples in this document are the following:

  • For POST:
curl localhost:1026/<operation_url> -s -S [headers]' -d @- <<EOF
[payload]
EOF
  • For PUT:
curl localhost:1026/<operation_url> -s -S [headers] -X PUT -d @- <<EOF
[payload]
EOF
  • For PATCH:
curl localhost:1026/<operation_url> -s -S [headers] -X PATCH -d @- <<EOF
[payload]
EOF
  • For GET:
curl localhost:1026/<operation_url> -s -S [headers]
  • For DELETE:
curl localhost:1026/<operation_url> -s -S [headers] -X DELETE

Regarding [headers] you have to include the following ones:

  • Accept header to specify the payload format in which you want to receive the response. You should explicitly specify JSON.
curl ... -H 'Accept: application/json' ...
  • If using payload in the request (i.e. POST, PUT or PATCH), you have to supply the Context-Type HTTP header to specify the format (JSON).
curl ... -H 'Content-Type: application/json' ...

Some additional remarks:

  • Most of the time we are using multi-line shell commands to provide the input to curl, using EOF to mark the beginning and the end of the multi-line block (here-documents). In some cases (GET and DELETE) we omit -d @- as no payload is used.

  • In the examples, it is assumes that the broker is listening on port 1026. Adjust this in the curl command line if you are using a different port.

  • In order to pretty-print JSON in responses, you can use Python with msjon.tool (examples along with tutorial are using this style):

(curl ... | python -mjson.tool) <<EOF
...
EOF
  • Check that curl is installed in your system using:
which curl

Top

Context management

Don't forget to restart the broker before starting this tutorial as previously described in this document

At the end of this section, you will have the basic knowledge to create applications (both context producers and consumers) using Orion Context Broker with context management operations.

Entity creation

Orion Context Broker starts in an empty state (no entities in the database), so first of all we need to make Orion aware of the existence of certain entities. In particular, we are going to "create" Room1 and Room2 entities, each one with two attributes (temperature and pressure). We do this using the POST /v2/entities operation.

First, we are going to create Room1. Let's assume that at entity creation time, temperature and pressure of Room1 are 23 ºC and 720 mmHg respectively.

curl localhost:1026/v2/entities -s -S -H 'Content-Type: application/json' -d @- <<EOF
{
  "id": "Room1",
  "type": "Room",
  "temperature": {
    "value": 23,
    "type": "Float"
  },
  "pressure": {
    "value": 720,
    "type": "Integer"
  }
}
EOF

Apart from the id and type fields (that define the ID and type of the entity), the payload contains a set of attributes. Each attribute contains a value and a type.

Orion Context Broker doesn't perform any check on types (e.g. it doesn't check that when a context producer application updates the value of the temperature, this value is formatted as a float like 25.5 or -40.23 and not something like hot).

Upon receipt of this request, Orion creates the entity in its internal database, sets the values for its attributes and responds with a 201 Created HTTP code.

Next, let's create Room2 in a similar way (in this case, setting temperature and pressure to 21 ºC and 711 mmHg respectively).

curl localhost:1026/v2/entities -s -S -H 'Content-Type: application/json' -d @- <<EOF
{
  "id": "Room2",
  "type": "Room",
  "temperature": {
    "value": 21,
    "type": "Float"
  },
  "pressure": {
    "value": 711,
    "type": "Integer"
  }
}
EOF

Apart from simple values corresponding to JSON datatypes (i.e. numbers, strings, booleans, etc.) for attribute values, complex structures or custom metadata can be used. This is an advanced topic, described in this section and this other, respectively.

Top

Query entity

Now let's play the role of a consumer application, wanting to access the context information stored by Orion Context Broker to do something interesting with it (e.g. show a graph with the room temperature in a graphical user interface). The GET /v2/entities/{id} request is used in this case, e.g. to get context information for Room1:

curl localhost:1026/v2/entities/Room1?type=Room -s -S -H 'Accept: application/json' | python -mjson.tool

Actually, you don't need to specify the type, as in this case there is no ambiguity using just the ID, so you can also do:

curl localhost:1026/v2/entities/Room1 -s -S -H 'Accept: application/json' | python -mjson.tool

In both cases,the response includes all the attributes belonging to Room1 and we can check that temperature and pressure have the values that we set at entity creation with updateContext (23ºC and 720 mmHg).

{
    "id": "Room1",
    "pressure": {
        "metadata": {},
        "type": "Integer",
        "value": 720
    },
    "temperature": {
        "metadata": {},
        "type": "Float",
        "value": 23
    },
    "type": "Room"
}

The keyValues option can be used in order to get a more compact and brief representation, including just attribute values:

curl localhost:1026/v2/entities/Room1?options=keyValues -s -S -H 'Accept: application/json' | python -mjson.tool

Response:

{
    "id": "Room1",
    "pressure": 720,
    "temperature": 23,
    "type": "Room"
}

You can also use the values option in order to get an even more compact representation corresponding to a list of attribute values. In this case, the attrs URL parameter needs to be used to specify the order. Eg, to get temperature first, then pressure:

curl 'localhost:1026/v2/entities/Room1?options=values&attrs=temperature,pressure' -s -S  \
    -H 'Accept: application/json' | python -mjson.tool

Response:

[
    23,
    720
]

Compare with the same operation, but reversing the attrs list (pressure first, then pressure):

Request:

curl 'localhost:1026/v2/entities/Room1?options=values&attrs=pressure,temperature' -s -S  \
    -H 'Accept: application/json' | python -mjson.tool

Response:

[
    720,
    23
]

You can also request a single attribute, using the GET /v2/entities/{id}/attrs/{attrsName} operation. For example, to get only the temperature:

curl localhost:1026/v2/entities/Room1/attrs/temperature -s -S -H 'Accept: application/json' | python -mjson.tool

whose response is as follows:

{
    "metadata": {},
    "type": "Float",
    "value": 23
}

You can also get only the value using the operation GET /v2/entities/{id}/attrs/{attrsName}/value. Note that in this case you need to use Accept: text/plain as the value of the attribute is of that kind.

curl localhost:1026/v2/entities/Room1/attrs/temperature/value -s -S -H 'Accept: text/plain' | python -mjson.tool

whose response is simply:

23.0

Finally, note that you will get an error in case you try to query a non-existing entity or attribute, as shown in the following cases below.

Request:

curl localhost:1026/v2/entities/Room5 -s -S -H 'Accept: application/json' | python -mjson.tool

Response:

{
    "description": "The requested entity has not been found. Check type and id",
    "error": "NotFound"
}

Request:

curl localhost:1026/v2/entities/Room1/attrs/humidity -s -S -H 'Accept: application/json' | python -mjson.tool

Response:

{
    "description": "The entity does not have such an attribute",
    "error": "NotFound"
}

In both cases, the HTTP response code (not visible in the example) is 404 Not Found.

Top

Getting all entities and filtering

You can get all the entities using the GET /v2/entities operation

curl localhost:1026/v2/entities -s -S -H 'Accept: application/json' | python -mjson.tool

In our case, both Room1 and Room2 will be returned:

[
    {
        "id": "Room1",
        "pressure": {
            "metadata": {},
            "type": "Integer",
            "value": 720
        },
        "temperature": {
            "metadata": {},
            "type": "Float",
            "value": 23
        },
        "type": "Room"
    },
    {
        "id": "Room2",
        "pressure": {
            "metadata": {},
            "type": "Integer",
            "value": 711
        },
        "temperature": {
            "metadata": {},
            "type": "Float",
            "value": 21
        },
        "type": "Room"
    }
]

As with GET /v2/entities/{id} the keyValues and values options can be used also.

Apart from providing the whole set of entities, this operation implements filtering capabilities in order to adjust the list of retrieved entities to what you need. In particular:

  • You can filter by type, using the type URL parameter. For example, to get all entities with type Room (in this case retrieving both Room1 and Room2) you can use:
curl localhost:1026/v2/entities?type=Room -s -S  -H 'Accept: application/json' | python -mjson.tool
  • You can filter using entity id patterns, using the idPattern URL parameter (whose value is a regular expression). For example, to get all entities whose id starts with Room and is followed by a number in the 2 to 5 range (in this case retrieving Room2) you can use (note the -g in curl command line to avoid problems with brackets):
curl localhost:1026/v2/entities?idPattern=^Room[2-5] -g -s -S -H 'Accept: application/json' | python -mjson.tool
  • You can filter using attribute filters, using the URL parameter q. For a complete description, please have a look at the "Simple Query Language" section in the NGSv2 specification. For example, to get all entities whose temperature is above 22 (in this case retriving Room1). you can use:
curl 'localhost:1026/v2/entities?q=temperature>22' -s -S  -H 'Accept: application/json' | python -mjson.tool
  • You can filter by geographical location. This is an advanced topic, described in this section.

As a final comment, note that although our example is very simple (only 2 entities), Orion can manage millions of entities in a real deployment. However, by default, only 20 entities are returned (which is fine for this tutorial, but probably not for a real utilization scenario). In order to learn about how to retrieve large sets of entities page by page, please refer to the section on pagination in this manual.

Top

Update entity

You can update the value of entity attributes using the PATCH /v2/entities/{id}/attrs operation. This assumes that the attribute already exists in the entity.

Now we will play the role of a context producer application, i.e. a source of context information. Let's assume that this application in a given moment wants to set the temperature and pressure of Room1 to 26.5 ºC and 763 mmHg respectively, so it issues the following request:

curl localhost:1026/v2/entities/Room1/attrs -s -S -H 'Content-Type: application/json' -X PATCH -d @- <<EOF
{
  "temperature": {
    "value": 26.5,
    "type": "Float"
  },
  "pressure": {
    "value": 763,
    "type": "Float"
  }
}
EOF

As you can see, the structure of the request is very similar to the one used by the entity creation operation, except that entity id and type are not included in the payload.

Upon receipt of this request, the broker updates the values for the entity attributes in its internal database and responds with 204 No Content.

Now you can use the query entity operation to check that Room1 has been actually been updated.

You can also use the PUT /v2/entities/{id}/attrs/{attrName}/value operation to update the value of an attribute in a really compact way and leaving the attribute type untouched. For example, to update Room1 temperature to 28.4 (note that the Content-Type here is text/plain which corresponds to the value 28.4 - no JSON involved here ...):

curl localhost:1026/v2/entities/Room1/attrs/temperature/value -s -S -H 'Content-Type: text/plain' -X PUT -d 28.5

Finally, the PUT /v2/entities/{id}/attrs operation can be used to replace all the attributes of a given entity, i.e. removing previously existing ones.

As in the case of entity creation, apart from simple values corresponding to JSON datatypes (i.e. numbers, strings, booleans, etc.) for attribute values, you can also use complex structures or custom metadata. These are advanced topics, described in this section and this other, respectively.

More details on adding/removing attributes can be found in this section of the manual.

Top

Subscriptions

The operations you have been familiarized with until now, to create, query and update entities are the basic building blocks for synchronous context producer and context consumer applications. However, Orion Context Broker has another powerful feature that you can take advantage of: the ability to subscribe to context information so when "something" happens (we will explain the different cases for that "something"), your application will get an asynchronous notification. This way, you don't need to continuously repeat query requests (i.e. polling). The Orion Context Broker will let you know the information when it arrives.

Before starting to play with this feature, please start the accumulator server to capture notifications.

In order to create a subscription, the following POST /v2/subscriptions operation is used. Let's consider the following example (note we are using -v to get the Location header in the response, as explained later on):

curl -v localhost:1026/v2/subscriptions -s -S -H 'Content-Type: application/json' -d @- <<EOF
{
  "description": "A subscription to get info about Room1",
  "subject": {
    "entities": [
      {
        "id": "Room1",
        "type": "Room"
      }
    ],
    "condition": {
      "attrs": [
        "pressure"
      ]
    }
  },
  "notification": {
    "http": {
      "url": "http://localhost:1028/accumulate"
    },
    "attrs": [
      "temperature"
    ]
  },
  "expires": "2040-01-01T14:00:00.00Z",
  "throttling": 5
}
EOF

Let's examine in detail the different elements included in the payload:

  • The entities and attrs subfields within notifications define the contents of the notification messages. In this example, we are specifying that the notification has to include the temperature attribute for entity Room1.
  • The URL where to send notifications is defined with the url sub-field. Here we are using the URL of the accumulator-server.py program, previously started. Only one URL can be included per subscription. However, you can have several subscriptions on the same context elements (i.e. same entity and attribute).
  • Subscriptions may have an expiration date (expires field), specified using the ISO 8601 standard format. Once subscription overpass that date, the subscription is simply ignored (however, it is still stored in the broker database and needs to be purged using the procedure described in the administration manual). You can extend the duration of a subscription by updating it. We are using a date far enough away in time (year 2040) hoping the subscription will not expire while you run this tutorial :).
  • You can also have permanent subscriptions. Just omit the expires field.
  • The conditions element defines the "trigger" for the subscription. The attrs field contains a list of attribute names. These names define the "triggering attributes", i.e. attributes that upon creation/change due to entity creation or update trigger the notification.
  • The rule is that if at least one of the attributes in the conditions.attrs list changes (e.g. some kind of "OR" condition), then a notification is sent. For example, in this case, when Room1 pressure changes, the Room1 temperature value is notified, but not pressure itself. If you want pressure to be notified as well, the request would need to include "pressure" within the notifications.attrs list (or to use an empty attribute vector, which means "all the attributes in the entity"). Now, this example here, to be notified of the value of temperature each time the value of pressure changes may not be too useful. The example is chosen this way only to show the enormous flexibility of subscriptions.
  • You can leave conditions.attrs empty to make a notification trigger on any entity attribute change (regardless of the name of the attribute).
  • Notifications include the attribute values after processing the update operation triggering the notification. However, you can make Orion include also the previous value. This is achieved using metadata. Have a look at the following piece of documentation.
  • You can also set "notify all attributes except some" subscriptions (a kind of "blacklist" functionality). In this case, use exceptAttrs instead of attrs within notifications.
  • You can include filtering expressions in conditions. For example, to get notified not only if pressure changes, but if it changes within the range 700-800. This is an advanced topic, see the "Subscriptions" section in the NGSIv2 specification.
  • The throttling element is used to specify a minimum inter-notification arrival time. So, setting throttling to 5 seconds as in the example above, makes a notification not to be sent if a previous notification was sent less than 5 seconds earlier, no matter how many actual changes take place in that period. This is to give the notification receptor a means to protect itself against context producers that update attribute values too frequently. In multi-CB configurations, take into account that the last-notification measure is local to each CB node. Although each node periodically synchronizes with the database in order to get potentially newer values (more on this here) it may happen that a particular node has an old value, so throttling is not 100% accurate.

The response corresponding to that request uses 201 Created as HTTP response code. In addition, it contains a Location header which holds the subscription ID: a 24 digit hexadecimal number used for updating and cancelling the subscription. Write it down because you will need it later in this tutorial.

< HTTP/1.1 201 Created
< Connection: Keep-Alive
< Content-Length: 0
< Location: /v2/subscriptions/57458eb60962ef754e7c0998
< Fiware-Correlator: 9ac7bbba-2268-11e6-aaf0-d48564c29d20
< Date: Wed, 25 May 2016 11:05:35 GMT

Let's have a look now at accumulator-server.py. We will see one notification (and just one for the moment, no matter how long you wait), similar to this one:

POST http://localhost:1028/accumulate
Content-Length: 141
User-Agent: orion/1.1.0-next libcurl/7.38.0
Ngsiv2-Attrsformat: normalized
Host: localhost:1028
Accept: application/json
Content-Type: application/json; charset=utf-8
Fiware-Correlator: 3451e5c2-226d-11e6-aaf0-d48564c29d20

{
    "data": [
        {
            "id": "Room1",
            "temperature": {
                "metadata": {},
                "type": "Float",
                "value": 28.5
            },
            "type": "Room"
        }
    ],
    "subscriptionId": "57458eb60962ef754e7c0998"
}

Orion Context Broker notifies context subscriptions using the POST HTTP method (on the URL for the subscription). The payload includes a reference to the subscription ID and a data vector, with the actual data for the entities. Note that the entity representation format is the same as the one used by the responses to the GET /v2/entities operation.

You may wonder why accumulator-server.py is getting this message if you don't actually do any update. This is due to the initial notification, which details are described here.

Now, do the following exercise, based on what you know from update entity: perform the following four updates in sequence, letting pass more than 5 seconds between updates (to avoid losing notifications due to throttling):

  • update Room1 temperature to 27: nothing happens, as temperature is not the triggering attribute
  • update Room1 pressure to 765: you will get a notification with the current value of Room1 temperature (27)
  • update Room1 pressure to 765: nothing happens, as the broker is clever enough to know that the value previous to the updateContext request was also 765 so no actual update has occurred and consequently no notification is sent.
  • update Room1 pressure to 765 adding ?options=forcedUpdate to the request URL: In this case, the broker will send the notification, because of the forcedUpdate URI option. Details about forcedUpdate URI option are described here.
  • update Room2 pressure to 740: nothing happens, as the subscription is for Room1, not Room2.

Next, try to check how throttling is enforced. Update Room1 pressure fast, without letting pass 5 seconds and you will see that no second notification arrives to accumulator-server.py.

Subscriptions can be retrieved using GET /v2/subscriptions (which provides the whole list and pagination may be needed if the list is too large) or GET /v2/subscriptions/{subId} (to get a single subscription). In addition, subscriptions can be updated using the PATCH /v2/subscription/{subId} operation. Finally, subscriptions can be deleted using the DELETE /v2/subscriptions/{subId} operation.

Some additional considerations:

  • Subscriptions can be paused. In order to do so, set the status attribute to "inactive" (and if you want to resume the subscription, set it back to "active"):
curl localhost:1026/v2/subscriptions/57458eb60962ef754e7c0998 -s -S \
    -X PATCH -H 'Content-Type: application/json' -d @- <<EOF
{
  "status": "inactive"
}
EOF
  • Notifications can be customized in several ways. First, you can tune the entity representation format in notifications, using the attrsFormat field within notification. Secondly, you can use a custom notification HTTP verb (e.g. PUT), custom HTTP headers, custom URL query parameters and custom payloads (not necessarily in JSON). Have a look at "Notification Messages" and "Custom Notifications" in the NGSIv2 specification.

Top

Browsing all types and detailed information on a type

The following operation can be used to get a list of all entity types that exist in the Orion Context Broker in a given moment. For example, let's assume we have three entities of type Room and two entities of type Car:

curl localhost:1026/v2/types -s -S -H 'Accept: application/json' | python -mjson.tool

Response:

[
    {
        "attrs": {
            "fuel": {
                "types": [
                    "Percentage"
                ]
            },
            "speed": {
                "types": [
                    "Float"
                ]
            }
        },
        "count": 2,
        "type": "Car"
    },
    {
        "attrs": {
            "pressure": {
                "types": [
                    "Integer"
                ]
            },
            "temperature": {
                "types": [
                    "Float"
                ]
            }
        },
        "count": 3,
        "type": "Room"
    }
]

As you can see, attribute information for each type is provided. Some important remarks:

  • Given that NGSI doesn't force all the entities of a given type to have the same set of attributes (i.e. entities of the same type may have a different attributes set) the attributes set per type returned by this operation is the union set of the attribute sets of each entity belonging to that type.
  • Moreover, attributes with the same name in different entities may have different types. Thus, the types field associated to each attribute is a list.

If you only need a list of the entity types (without any extra attribute details), you can use:

curl localhost:1026/v2/types?options=values -s -S -H 'Accept: application/json' | python -mjson.tool

and get:

[
    "Car",
    "Room"
]

Note that the pagination mechanism also works in the GET /v2/types operation described above.

In addition, you can use the following operation to get detailed information of a single type:

curl localhost:1026/v2/types/Room -s -S -H 'Accept: application/json' | python -mjson.tool

The response will be:

{
    "attrs": {
        "pressure": {
            "types": [
                "Integer"
            ]
        },
        "temperature": {
            "types": [
                "Float"
            ]
        }
    },
    "count": 3
}

Top

Batch operations

Apart from the RESTful operations to manage entities described so far, NGSIv2 also includes "batch" operations that may be useful in some cases. In particular, there is a batch update operation (POST /v2/op/update) and a batch query operation (POST /v2/op/query).

Batch update allows you to create or update several entities with a single request. For example, to create Room3 (temperature 21.2 and pressure 722) and Room4 (temperature 31.8 and pressure 712) you can use:

curl -v localhost:1026/v2/op/update -s -S -H 'Content-Type: application/json' -d @- <<EOF
{
  "actionType": "append",
  "entities": [
    {
      "type": "Room",
      "id": "Room3",
      "temperature": {
        "value": 21.2,
        "type": "Float"
      },
      "pressure": {
        "value": 722,
        "type": "Integer"
      }
    },
    {
      "type": "Room",
      "id": "Room4",
      "temperature": {
        "value": 31.8,
        "type": "Float"
      },
      "pressure": {
        "value": 712,
        "type": "Integer"
      }
    }
  ]
}
EOF

On success, the response uses HTTP response code 204 No Content. In this case we are using append actionType, which is for adding entities and attribute. We could also use update to change an attribute in one entity (temperature in Room3) and another attribute in other (pressure in Room4), leaving the other attributes untouched.

curl -v localhost:1026/v2/op/update -s -S -H 'Content-Type: application/json' -d @- <<EOF
{
  "actionType": "update",
  "entities": [
    {
      "type": "Room",
      "id": "Room3",
      "temperature": {
        "value": 29.9,
        "type": "Float"
      }
    },
    {
      "type": "Room",
      "id": "Room4",
      "pressure": {
        "value": 709,
        "type": "Integer"
      }
    }
  ]
}
EOF

Apart from append and update, there are other action types: delete, appendStrict, etc. See this section for details.

Finally, the POST /v2/op/query allows to retrieve entities matching a query condition specified in the payload. It is very similar to GET /v2/entities (in fact, the response payload is the same and it also supports pagination in the same way). However POST /v2/op/query can express queries that GET /v2/entities cannot (e.g. a list of entities of different type).

For example, to get the attributes temperature and pressure of all the entities of type Room or Car whose temperature is greater than 40 and that are located within 20 km from the coordinates 40.31, -3.75, the following operation could be used:

curl -v localhost:1026/v2/op/query -s -S -H 'Content-Type: application/json' -d @- <<EOF
{
  "entities": [
    {
      "idPattern": ".*",
      "type": "Room"
    },
    {
      "id": ".*",
      "type": "Car"
    }
  ],
  "attrs": [
    "temperature",
    "pressure"
  ],
  "expression": {
    "q": "temperature>40",
    "georel": "near;maxDistance:20000",
    "geometry": "point",
    "coords": "40,31,-3.75"
  }
}
EOF

Top

Context availability management

While context management is about entities and attributes (creating, updating, retrieving, etc.), context availability management is about the source of the entities and attributes. The basic concept in context availability management is the registration resource. A registration contains information about a source of information (named a "context provider") and what entities and attributes are provided by that source.

Let's illustrate with an example, creating a simple registration. We are stating that the attributes temperature and pressure of Room5 are provided by a context provider in the URL http://mysensors.com/Rooms:

curl -v localhost:1026/v2/registrations -s -S -H 'Content-Type: application/json' -d @-  <<EOF
{
  "description": "Registration for Room5",
  "dataProvided": {
    "entities": [
      {
        "id": "Room5",
        "type": "Room"
      }
    ],
    "attrs": [
      "temperature",
      "pressure"
    ]
  },
  "provider": {
    "http": {
      "url": "http://mysensors.com/Rooms"
    }
  }
}
EOF

The response corresponding to that request uses 201 Created as HTTP response code. In addition, it contains a Location header which holds the registration ID: a 24 digit hexadecimal number used for updating and deleting the registration. Write it down because you will need it later in this tutorial.

< HTTP/1.1 201 Created
< Connection: Keep-Alive
< Content-Length: 0
< Location: /v2/registrations/5a82be3d093af1b94ac0f730
< Fiware-Correlator: e4f0f334-10a8-11e8-ab6e-000c29173617
< Date: Tue, 13 Feb 2018 10:30:21 GMT

You may retrieve the list of existing registrations using the following request:

curl localhost:1026/v2/registrations -s -S -H 'Accept: application/json' | python -mjson.tool

In this particular case you will retrieve only one registration (as you have created only one) but note that the response uses [...] so a full list could be present.

In addition, you may retrieve a single registration using the following request (replace 5a82be3d093af1b94ac0f730 by the actual registration ID in your case):

curl localhost:1026/v2/registrations/5a82be3d093af1b94ac0f730 -s -S -H 'Accept: application/json' | python -mjson.tool

Orion not only stores information about sources of entities/attributes in the form of registrations, but also uses these registrations to implement query/update forwarding. In other words, while a registration is in place, Orion uses that information to solve queries/updates in entities that aren't managed locally. However, this is an advanced topic out of the scope of this tutorial. Please have a look at the context providers and request forwarding documentation for details.

Finally, you can delete an existing registration with the following request (replace 5a82be3d093af1b94ac0f730 by the actual registration ID in your case):

curl -X DELETE localhost:1026/v2/registrations/5a82be3d093af1b94ac0f730 -s -S -H 'Accept: application/json' | python -mjson.tool

Top