Description: This tutorial introduces the concise NGSI-LD format and demonstrates its use and explains the differences between concise and normalized NGSI-LD payloads.
The tutorial uses cUrl commands throughout, but is also available as Postman documentation
Concise NGSI-LD Payloads
"To speak much is one thing; to speak to the point another!"
— Sophocles, Oedipus at Colonus
The NGSI-LD API is a flexible mechanism for producing context data in multiple formats. This was demonstrated in the
initial Getting Started tutorial where both "normalized" and "key-values" pairs format were
produced. The default, verbose data format is so-called "normalized" NGSI-LD where every Property is defined by
"type": "Property"
and every Relationship is defined by "type": "Relationship"
. These keywords ( type
,
Property
and Relationship
) are in turn strictly defined JSON-LD terms which can be found in the core @context served
with every request.
NGSI-LD Payloads
Normalized NGSI-LD
The full "normalized" form is an excellent choice for data exchange, since through the @context
and the definition of
JSON-LD keywords, machines are given all the tools to fully comprehend the payload format. Responses return the complete
current state of each entity, with payloads all including sub-attributes such as Properties-of-Properties,
Properties-of-Relationships and other standard metadata terms like observedAt
and unitCode
. Furthermore normalized
payloads are exceedingly regular and parseable, and can easily be reduced down to the relevant value
elements if such
an operation necessary. However with the normalized format, is necessary to repeatedly supply common defining attributes
such as "type": "Property"
throughout the payload to ensure that machines can fully understand the data represented.
Normalized NGSI-LD using options=normalized
{
"@context": [
"https://fiware.github.io/tutorials.Step-by-Step/example.jsonld",
"https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld"
],
"id": "urn:nsgi-ld:Beatle:John_Lennon",
"type": "Beatle",
"age": { "type": "Property", "value": 40, "unitCode": "ANN" },
"name": { "type": "Property", "value": "John Lennon" },
"born": { "type": "Property", "value": "1940-10-09" },
"spouse": {
"type": "Relationship",
"object": "urn:nsgi-ld:Person:Cynthia_Lennon"
},
"location": {
"type": "GeoProperty",
"value": {
"type": "Point",
"coordinates": [-73.975, 40.775556]
}
}
}
Open in JSON-LD Playground
Simplified NGSI-LD
The use of the normalized format can be contrast with the "key-values" pairs format, which is a simplified version
concentrating purely on the values of the first level of attributes only. The payloads remain regular, but are much
shorter and to the point, and not all information is returned by the request - second level attributes such as
unitCode
and observedAt
will not be returned in the payload for example.
Simplified NGSI-LD using options=keyValues
{
"@context": [
"https://fiware.github.io/tutorials.Step-by-Step/example.jsonld",
"https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld"
],
"id": "urn:nsgi-ld:Beatle:John_Lennon",
"name": "John Lennon",
"born": "1940-10-09",
"spouse": "urn:nsgi-ld:Person:Cynthia_Lennon",
"age": 40,
"location": {
"type": "Point",
"coordinates": [-73.975, 40.775556]
}
}
Open in JSON-LD Playground
This key-values payload matches the simple JSON-LD payload which can be seen on the front-page of the official JSON-LD site.
Both normalized and key-values NGSI-LD formats are valid JSON-LD, but since the key-values format is lossy, until recently, all updates to an NGSI-LD context broker must be made using the normalized format.
Concise NGSI-LD
To make the API easier to use and reduce the burden on developers, NGSI-LD now accepts an intermediate "concise" format
which still offers all of the context data in the payload, but removes the redundancy of repeatedly adding
"type": "Property"
throughout each payload. The concise representation is a terser, lossless form of the normalized
representation, where redundant "type" members are omitted and the following rules are applied:
- Every Property without further sub-attributes is represented by the Property value only.
- Every Property that includes further sub-attributes is represented by a value key-value pair.
- Every GeoProperty without further sub-attributes is represented by the GeoProperty’s GeoJSON representation only
- Every GeoProperty that includes further sub-attributes is represented by a value key-value pair.
- Every LanguageProperty is defined by a
languageMap
key-value pair. - Every Relationship is defined by an
object
key-value pair.
Concise NGSI-LD using options=concise
{
"@context": [
"https://fiware.github.io/tutorials.Step-by-Step/example.jsonld",
"https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld"
],
"id": "urn:nsgi-ld:Beatle:John_Lennon",
"name": "John Lennon",
"born": "1940-10-09",
"spouse": {
"object": "urn:nsgi-ld:Person:Cynthia_Lennon"
},
"age": { "value": 40, "unitCode": "ANN" },
"location": {
"type": "Point",
"coordinates": [-73.975, 40.775556]
}
}
Open in JSON-LD Playground
It can be seen from the payload above that the concise format (like normalized) is also lossless as it still includes
Properties-of-Properties like unitCode
(the units of the age
attribute is obviously years following the UN/CEFACT
code ANN
for example) and also clearly distinguishes between Properties and Relationships (since
Relationships always have an object
).
In summary, all NGSI-LD formats provide a structured, well-defined payloads, but the "normalized" format is verbose and lossless, "key-values" is short and lossy, and third format - "concise" is a secondary, intermediate lossless format designed to bridge the gap between the two.
Device Monitor
For the purpose of this tutorial, a series of dummy agricultural IoT devices have been created, which will be attached
to the context broker. Details of the architecture and protocol used can be found in the
IoT Sensors tutorial The state of each device can be
seen on the UltraLight device monitor web page found at: http://localhost:3000/device/monitor
.
Architecture
This application builds on the components and dummy IoT devices created in previous tutorials. It will use two FIWARE components: the Orion Context Broker and the IoT Agent for Ultralight 2.0.
Therefore the overall architecture will consist of the following elements:
-
The FIWARE Generic Enablers:
- The Orion Context Broker which will receive requests using NGSI-LD
- The FIWARE IoT Agent for UltraLight 2.0 which will receive southbound requests using NGSI-LD and convert them to UltraLight 2.0 commands for the devices
-
A MongoDB database:
- Used by the Orion Context Broker to hold context data information such as data entities, subscriptions and registrations
- Used by the IoT Agent to hold device information such as device URLs and Keys
-
An HTTP Web-Server which offers static
@context
files defining the context entities within the system. - The Tutorial Application does the following:
- Acts as set of dummy agricultural IoT devices using the UltraLight 2.0 protocol running over HTTP.
Since all interactions between the elements are initiated by HTTP requests, the entities can be containerized and run from exposed ports.
The overall architecture can be seen below:
The necessary configuration information can be seen in the services section of the associated docker-compose.yml
file.
It has been described in a previous tutorial.
Video: Concise Payloads
Click on the image above to watch a demo of this tutorial describing how to use the NGSI-LD Concise format
Start Up
Before you start, you should ensure that you have obtained or built the necessary Docker images locally. Please clone the repository and create the necessary images by running the commands as shown:
git clone https://github.com/FIWARE/tutorials.Concise-Format.git
cd tutorials.Concise-Format
git checkout NGSI-LD
./services create
Thereafter, all services can be initialized from the command-line by running the services Bash script provided within the repository. To start the system with your preferred context broker, run the following command:
./services [orion|scorpio|stellio]
Note: If you want to clean up and start over again you can do so with the following command:
./services stop
Concise NGSI-LD Operations
Any context-broker operation which uses a normalized NGSI-LD payload can also be triggered using a concise payload.
Create Operations
Create Operations map to HTTP POST.
- The
/ngsi-ld/v1/entities
endpoint is used for creating new entities - The
/ngsi-ld/v1/entities/<entity-id>/attrs
endpoint is used for adding new attributes
Any newly created entity must have id
and type
attributes and a valid @context
definition. All other attributes
are optional and will depend on the system being modelled. If additional attributes are present though, a concise
Property must be encapsulated within a value
. If a Relationship is added it must be encapsulated within an
object
.
The response will be 201 - Created if the operation is successful or 409 - Conflict if the operation fails.
Create a New Data Entity
This example adds a new TemperatureSensor entity to the context.
1 Request:
curl -iX POST 'http://localhost:1026/ngsi-ld/v1/entities/' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--data-raw '{
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"category": "sensor",
"temperature": {
"value": 25,
"unitCode": "CEL"
}
}'
New entities can be added by making a POST request to the /ngsi-ld/v1/entities
endpoint. Notice that because
category
has no sub-attributes, it does not require a value
element.
As usual, the request will fail if the entity already exists in the context.
2 Request:
You can check to see if the new TemperatureSensor can be found in the context by making a GET request. This returns the full normalized form:
curl -L -X GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"'
Create New Attributes
This example adds a new batteryLevel
Property and a controlledAsset
Relationship to the existing
TemperatureSensor entity with id=urn:ngsi-ld:TemperatureSensor:001
.
3 Request:
curl -iX POST 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001/attrs' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--data-raw '{
"batteryLevel": {
"value": 0.8,
"unitCode": "C62"
},
"controlledAsset": {
"object": "urn:ngsi-ld:Building:barn002"
}
}'
New attributes can be added by making a POST request to the /ngsi-ld/v1/entities/<entity>/attrs
endpoint.
The payload should consist of a JSON object holding the attribute names and values as shown.
All Property attributes with additional sub-attributes must have a value
associated with them. All
Relationship attributes must have an object
associated with them which holds the URN of another entity.
Well-defined common metadata elements such as unitCode
can be provided as strings, all other metadata should be passed
as a JSON object with its own type
and value
attributes.
Subsequent requests using the same id
will update the value of the attribute in the context.
4 Request:
You can check to see if the new TemperatureSensor can be found in the context by making a GET request.
curl -L -X GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"'
As you can see there are now two additional attributes (batteryLevel
and controlledAsset
) added to the entity. These
attributes have been defined in the @context
as part of the Device model and therefore can be read using their
short names.
Batch Create New Data Entities or Attributes
This example uses the convenience batch processing endpoint to add three new TemperatureSensor entities to the
context. Batch create uses the /ngsi-ld/v1/entityOperations/create
endpoint.
5 Request:
curl -iX POST 'http://localhost:1026/ngsi-ld/v1/entityOperations/create' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/ld+json' \
--data-raw '[
{
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"category": ["sensor"],
"temperature": {
"value": 20,
"unitCode": "CEL"
}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"category": ["sensor" , "actuator"],
"temperature": {
"value": 2,
"unitCode": "CEL"
}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:004",
"type": "TemperatureSensor",
"category": {
"type": "Property",
"value": "sensor"
},
"temperature": {
"type": "Property",
"value": 100,
"unitCode": "CEL"
}
}
]'
It can be seen that "type": "Property"
can be optionally added to concise payloads and the format is still recognized.
This means that any normalized payload automatically a valid concise payload. Care should be taken when adding arrays
using NGSI-LD due to the existing constraints of JSON-LD. Effectively there is no difference between an array of one
entry "category": ["sensor"]
and a simple string value "category": "sensor"
. Furthermore, order within the array is
not maintained.
Note: In NGSI-LD, an ordered array value could be encoded as a JSON Literal
"category" : {"@type": "@json", "@value":[1,2,3]}
.
The request will fail if any of the attributes already exist in the context. The response highlights which actions have been successful and the reason for failure (if any has occurred).
{
"@context": "http://context/ngsi-context.jsonld",
"success": [
"urn:ngsi-ld:TemperatureSensor:002",
"urn:ngsi-ld:TemperatureSensor:003",
"urn:ngsi-ld:TemperatureSensor:004"
],
"errors": []
}
Batch Create/Overwrite New Data Entities
This example uses the convenience batch processing endpoint to add or amend two TemperatureSensor entities in the context.
- if an entity already exists, the request will update that entity's attributes.
- if an entity does not exist, a new entity will be created.
6 Request:
curl -iX POST 'http://localhost:1026/ngsi-ld/v1/entityOperations/upsert' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/ld+json' \
--data-raw '[
{
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"category": "sensor",
"temperature": {
"value": 21,
"unitCode": "CEL"
}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"category": "sensor",
"temperature": {
"type": "Property",
"value": 27,
"unitCode": "CEL"
}
}
]'
Batch processing for create/overwrite uses the /ngsi-ld/v1/entityOperations/upsert
endpoint.
A subsequent request containing the same data (i.e. same entities and actionType=append
) will also succeed won't
change the context state. The modifiedAt
metadata will be amended however.
Read Operations
- The
/ngsi-ld/v1/entities
endpoint is used for listing entities - The
/ngsi-ld/v1/entities/<entity>
endpoint is used for retrieving the details of a single entity.
For read operations the @context
must be supplied in a Link
header.
Filtering
- The
options
parameter (combined with theattrs
parameter) can be used to filter the returned fields - The
q
parameter can be used to filter the returned entities
Read a Data Entity (concise)
This example reads the state of an existing TemperatureSensor entity with a known id
and returns in concise
format.
7 Request:
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-d 'options=concise,sysAttrs'
Response:
Tip: Use jq to format the JSON responses in this tutorial. Pipe the result by appending
| jq '.'
TemperatureSensor urn:ngsi-ld:TemperatureSensor:001
is returned as concise NGSI-LD. Additional metadata is returned
because options=sysAttrs
. By default the @context
is returned in the payload body (although this could be moved due
to content negotiation if the Accept:application/json
had been set). The full response is shown below:
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"createdAt": "2020-08-27T14:33:06Z",
"modifiedAt": "2020-08-27T14:33:10Z",
"category": {
"createdAt": "2020-08-27T14:33:06Z",
"modifiedAt": "2020-08-27T14:33:06Z",
"value": "sensor"
},
"temperature": {
"createdAt": "2020-08-27T14:33:06Z",
"modifiedAt": "2020-08-27T14:33:06Z",
"value": 25,
"unitCode": "CEL"
},
"batteryLevel": {
"value": 0.8,
"createdAt": "2020-08-27T14:33:10Z",
"modifiedAt": "2020-08-27T14:33:10Z",
"unitCode": "C62"
},
"controlledAsset": {
"object": "urn:ngsi-ld:Building:barn002",
"createdAt": "2020-08-27T14:33:10Z",
"modifiedAt": "2020-08-27T14:33:10Z"
}
}
Individual context data entities can be retrieved by making a GET request to the /ngsi-ld/v1/entities/<entity>
endpoint.
Read an Attribute from a Data Entity
This example reads the value of a single attribute (temperature
) from an existing TemperatureSensor entity with a
known id
.
8 Request:
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-d 'attrs=temperature'
Response:
The sensor urn:ngsi-ld:TemperatureSensor:001
is reading at 25°C. The response is shown below:
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"temperature": {
"value": 25,
"unitCode": "CEL"
}
}
Because options=concise
was used this is response includes the metadata such as unitCode
but not
"type": "Property"
Context data can be retrieved by making a GET request to the /ngsi-ld/v1/entities/<entity-id>
endpoint and selecting the attrs
using a comma separated list.
Read a Data Entity (concise)
This example reads the concise NGSI-LD format from the context of an existing TemperatureSensor entities with a
known id
.
9 Request:
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001' \
-H 'Link: <http://context/json-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/json' \
-d 'options=concise'
Response:
The sensor urn:ngsi-ld:TemperatureSensor:001
is reading at 25°C. The response is shown below:
{
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"category": "sensor",
"temperature": {
"value": 25,
"unitCode": "CEL"
},
"batteryLevel": {
"value": 0.8,
"unitCode": "C62"
},
"controlledAsset": {
"object": "urn:ngsi-ld:Building:barn002"
}
}
The response contains an unfiltered list of context data from an entity containing all of the attributes of the
urn:ngsi-ld:TemperatureSensor:001
. The payload body does not contain an @context
attribute since the
Accept: application/json
was set.
Combine the options=concise
parameter with the attrs
parameter to retrieve a limited set of key-value pairs.
Read Multiple attributes values from a Data Entity
This example reads the value of two attributes (category
and temperature
) from the context of an existing
TemperatureSensor entity with a known id
.
10 Request:
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001' \
-H 'Link: <http://context/json-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/json' \
-d 'options=concise' \
-d 'attrs=category,temperature'
Response:
The sensor urn:ngsi-ld:TemperatureSensor:001
is reading at 25°C. The response is shown below:
{
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"category": "sensor",
"temperature": {
"value": 25,
"unitCode": "CEL"
}
}
Combine the options=concise
parameter and the attrs
parameter to return a list of values.
List all Data Entities (concise)
This example lists the full context of all TemperatureSensor entities.
11 Request:
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-d 'type=TemperatureSensor' \
-d 'options=concise'
Response:
On start-up the context was empty, four TemperatureSensor entities have been added by create operations so the full context will now contain four sensors.
[
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:004",
"type": "TemperatureSensor",
"category": "sensor",
"temperature": {
"value": 100,
"unitCode": "CEL"
}
},
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"category": "sensor",
"temperature": {
"value": 21,
"unitCode": "CEL"
}
},
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"category": "sensor",
"temperature": {
"type": "Property",
"value": 27,
"unitCode": "CEL"
}
},
{
"@context": "http://context/ngsi-context.jsonld",
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"batteryLevel": {
"value": 0.8,
"unitCode": "C62"
},
"category": "sensor",
"controlledAsset": {
"object": "urn:ngsi-ld:Building:barn002"
},
"temperature": {
"value": 25,
"unitCode": "CEL"
}
}
]
List all Data Entities (filtered)
This example lists the temperature
attribute of all TemperatureSensor entities in concise format.
12 Request:
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/' \
-H 'Link: <http://context/json-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/json' \
-d 'type=TemperatureSensor' \
-d 'options=concise' \
-d 'attrs=temperature'
Response:
The full context contains four sensors, they are returned in a random order:
[
{
"id": "urn:ngsi-ld:TemperatureSensor:004",
"type": "TemperatureSensor",
"temperature": {
"value": 100,
"unitCode": "CEL"
}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"temperature": {
"value": 21,
"unitCode": "CEL"
}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"temperature": {
"value": 27,
"unitCode": "CEL"
}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"temperature": {
"value": 25,
"unitCode": "CEL"
}
}
]
Context data for a specified entity type can be retrieved by making a GET request to the /ngsi-ld/v1/entities/
endpoint and supplying the type
parameter, combine this with the options=keyValues
parameter and the attrs
parameter to retrieve key-values.
Filter Data Entities by ID
This example lists selected data from two TemperatureSensor entities chosen by id
. Note that every id
must be
unique, so type
is not required for this request. To filter by id
add the entries in a comma delimited list.
13 Request:
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/'' \
-H 'Link: <http://context/json-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: 'application/json' \
-d 'id=urn:ngsi-ld:TemperatureSensor:001,urn:ngsi-ld:TemperatureSensor:002' \
-d 'attrs=temperature' \
-d 'options=concise'
Response:
The response details the selected attributes from the selected entities.
[
{
"id": "urn:ngsi-ld:TemperatureSensor:002",
"type": "TemperatureSensor",
"temperature": {
"value": 21,
"unitCode": "CEL"
}
},
{
"id": "urn:ngsi-ld:TemperatureSensor:001",
"type": "TemperatureSensor",
"temperature": {
"value": 25,
"unitCode": "CEL"
}
}
]
Returning data as GeoJSON
The concise format is also available for the GeoJSON format which can be requested by setting the Accept
header to
application/geo+json
and setting the options=concise
parameter.
14 Request:
curl -G -iX GET 'http://localhost:1026//ngsi-ld/v1/entities/' \
-H 'Link: <http://context/json-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
-H 'Accept: application/geo+json' \
-H 'NGSILD-Tenant: openiot' \
-d 'id=urn:ngsi-ld:Animal:pig010,urn:ngsi-ld:Animal:pig006' \
-d 'options=concise'
Response:
The response details the selected attributes from the selected entities is returned as a GeoJSON feature collection. The
properties
section holds data in concise format.
{
"type": "FeatureCollection",
"features": [
{
"id": "urn:ngsi-ld:Animal:pig010",
"type": "Feature",
"properties": {
"type": "Animal",
"heartRate": {
"value": 71,
"providedBy": {
"object": "urn:ngsi-ld:Device:pig010"
},
"observedAt": "2022-03-01T15:49:57.039Z",
"unitCode": "5K"
},
"phenologicalCondition": "femaleAdult",
"reproductiveCondition": "active",
"name": "Carnation",
"legalID": "M-sow010-Carnation",
"sex": "female",
"species": "pig",
"location": {
"value": {
"type": "Point",
"coordinates": [13.346, 52.52]
},
"providedBy": {
"object": "urn:ngsi-ld:Device:pig010"
},
"observedAt": "2022-03-01T15:49:57.039Z"
}
},
"@context": "http://context/json-context.jsonld",
"geometry": {
"type": "Point",
"coordinates": [13.346, 52.52]
}
},
{
"id": "urn:ngsi-ld:Animal:pig006",
"type": "Feature",
"properties": {
"type": "Animal",
"heartRate": {
"value": 62,
"providedBy": {
"object": "urn:ngsi-ld:Device:pig006"
},
"observedAt": "2022-03-01T15:49:57.287Z",
"unitCode": "5K"
},
"phenologicalCondition": "femaleAdult",
"reproductiveCondition": "inCalf",
"name": "Peach",
"legalID": "M-sow006-Peach",
"sex": "female",
"species": "pig",
"location": {
"value": {
"type": "Point",
"coordinates": [13.347, 52.522]
},
"providedBy": {
"object": "urn:ngsi-ld:Device:pig006"
},
"observedAt": "2022-03-01T15:49:57.287Z"
}
},
"@context": "http://context/json-context.jsonld",
"geometry": {
"type": "Point",
"coordinates": [13.347, 52.522]
}
}
]
}
Update Operations
Overwrite operations are mapped to HTTP PATCH:
- The
/ngsi-ld/v1/entities/<entity-id>/attrs/<attribute>
endpoint is used to update an attribute - The
/ngsi-ld/v1/entities/<entity-id>/attrs
endpoint is used to update multiple attributes
Overwrite the value of an Attribute value
This example updates the value of the category
attribute of the Entity with id=urn:ngsi-ld:TemperatureSensor:001
.
15 Request:
curl -iX PATCH 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001/attrs/category' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--data-raw '{
"value": ["sensor", "actuator"]
}'
Existing attribute values can be altered by making a PATCH request to the
/ngsi-ld/v1/entities/<entity-id>/attrs/<attribute>
endpoint. The appropriate @context
should be supplied as a Link
header. The only difference between a normalized and concise payload is the missing type
attribute.
Overwrite Multiple Attributes of a Data Entity
This example simultaneously updates the values of both the category
and controlledAsset
attributes of the Entity
with id=urn:ngsi-ld:TemperatureSensor:001
.
16 Request:
curl -iX PATCH 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:TemperatureSensor:001/attrs' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--data-raw '{
"category": {
"value": [
"sensor",
"actuator"
]
},
"controlledAsset": {
"object": "urn:ngsi-ld:Building:barn001"
}
}'
Batch Update Attributes of Multiple Data Entities
This example uses the convenience batch processing endpoint to update existing sensors.
17 Request:
curl -iX POST 'http://localhost:1026/ngsi-ld/v1/entityOperations/upsert?options=update' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--data-raw '[
{
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"category": [
"actuator",
"sensor"
]
},
{
"id": "urn:ngsi-ld:TemperatureSensor:004",
"type": "TemperatureSensor",
"category": [
"actuator",
"sensor"
]
}
]'
Batch processing uses the /ngsi-ld/v1/entityOperations/upsert
endpoint. The payload body holds an array of the
entities and attributes we wish to update. The options=update
parameter indicates we will not remove existing
attributes if they already exist and have not been included in the payload.
An alternative would be to use the /ngsi-ld/v1/entityOperations/update
endpoint. Unlike upsert
, the update
operation will not silently create any new entities - it fails if the entities do not already exist.
Batch Replace Entity Data
This example uses the convenience batch processing endpoint to replace entity data of existing sensors.
18 Request:
curl -iX POST 'http://localhost:1026/ngsi-ld/v1/entityOperations/update?options=replace' \
-H 'Content-Type: application/json' \
-H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \
--data-raw '[
{
"id": "urn:ngsi-ld:TemperatureSensor:003",
"type": "TemperatureSensor",
"category":[
"actuator",
"sensor"
]
},
{
"id": "urn:ngsi-ld:TemperatureSensor:004",
"type": "TemperatureSensor",
"temperature": {
"value": 16,
"unitCode": "CEL"
"observedAt": "2022-03-01T15:00:00.000Z"
}
}
]'
Batch processing uses the /ngsi-ld/v1/entityOperations/update
endpoint with a payload with the options=replace
parameter, this means we will overwrite existing entities. /ngsi-ld/v1/entityOperations/upsert
could also be used if
new entities are also to be created.
Setting up concise Subscriptions
Concise Notification
The concise format can also be used when generating a notification from a subscription. Simply set the
"format": "concise"
within the notification
element as shown:
19 Request:
curl -iX POST
'http://{{orion}}/ngsi-ld/v1/subscriptions/' \
-H 'Content-Type: application/ld+json' \
-H 'NGSILD-Tenant: openiot' \
--data-raw '{
"description": "Notify me of low feedstock on Farm:001",
"type": "Subscription",
"entities": [{"id": "urn:ngsi-ld:Animal:pig003", "type": "Animal"}],
"notification": {
"format": "concise",
"endpoint": {
"uri": "http://tutorial:3000/subscription/low-stock-farm001-ngsild",
"accept": "application/geo+json"
}
},
"@context": "http://context/ngsi-context.jsonld"
}'
Then go to the Device Monitor http://localhost:3000/app/farm/urn:ngsi-ld:Building:farm001
and remove some hay from the
barn. Eventually a request is sent to subscription/low-stock-farm001
as shown:
http://localhost:3000/app/monitor
Subscription Payload:
{
"id": "urn:ngsi-ld:Notification:6220b4e464f3729a8527f8a0",
"type": "Notification",
"subscriptionId": "urn:ngsi-ld:Subscription:6220b4a964f3729a8527f88c",
"@context": "http://context/ngsi-context.jsonld",
"notifiedAt": "2022-03-03T12:30:28.237Z",
"data": [
{
"id": "urn:ngsi-ld:Animal:pig003",
"type": "Animal",
"heartRate": {
"value": 67,
"unitCode": "5K",
"observedAt": "2022-03-03T12:30:27.000Z",
"providedBy": {
"object": "urn:ngsi-ld:Device:pig003"
}
},
"phenologicalCondition": "maleAdult",
"reproductiveCondition": "active",
"name": "Flamingo",
"legalID": "M-boar003-Flamingo",
"sex": "male",
"species": "pig",
"location": {
"value": {
"type": "Point",
"coordinates": [13.357, 52.513]
},
"observedAt": "2022-03-03T12:30:27.000Z",
"providedBy": {
"object": "urn:ngsi-ld:Device:pig003"
}
}
}
]
}
Concise GeoJSON Notification
20 Request:
It is also possible to send GeoJSON notifications if the "accept": "application/geo+json"
attribute is set. Combining
this with "format": "concise"
results in a FeatureCollection
with properties in concise format.
curl -iX POST
'http://{{orion}}/ngsi-ld/v1/subscriptions/' \
-H 'Content-Type: application/ld+json' \
-H 'NGSILD-Tenant: openiot' \
--data-raw '{
"description": "Notify me of low feedstock on Farm:001",
"type": "Subscription",
"entities": [{"id": "urn:ngsi-ld:Animal:pig003", "type": "Animal"}],
"notification": {
"format": "concise",
"endpoint": {
"uri": "http://tutorial:3000/subscription/low-stock-farm001-ngsild",
"accept": "application/geo+json"
}
},
"@context": "http://context/ngsi-context.jsonld"
}'
Subscription Payload:
The result of a concise GeoJSON notification can be seen below.
{
"id": "urn:ngsi-ld:Notification:6220b50264f3729a8527f8ab",
"type": "Notification",
"subscriptionId": "urn:ngsi-ld:Subscription:6220b47764f3729a8527f886",
"notifiedAt": "2022-03-03T12:30:58.294Z",
"data": {
"type": "FeatureCollection",
"features": [
{
"id": "urn:ngsi-ld:Animal:pig003",
"type": "Feature",
"properties": {
"type": "Animal",
"heartRate": {
"value": 63,
"unitCode": "5K",
"observedAt": "2022-03-03T12:30:58.000Z",
"providedBy": {
"object": "urn:ngsi-ld:Device:pig003"
}
},
"phenologicalCondition": "maleAdult",
"reproductiveCondition": "active",
"name": "Flamingo",
"legalID": "M-boar003-Flamingo",
"sex": "male",
"species": "pig",
"location": {
"value": {
"type": "Point",
"coordinates": [13.357, 52.513]
},
"observedAt": "2022-03-03T12:30:58.000Z",
"providedBy": {
"object": "urn:ngsi-ld:Device:pig003"
}
}
},
"@context": "https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context-v1.6.jsonld",
"geometry": {
"value": {
"type": "Point",
"coordinates": [13.357, 52.513]
},
"observedAt": "2022-03-03T12:30:58.000Z",
"providedBy": {
"object": "urn:ngsi-ld:Device:pig003"
}
}
}
]
}
}