How notifications work
The platform is able to send notifications, based in a subscription mechanism implemented by Context Broker. Let's describe it step by step.
For all this document, we will assume that a service called smartown
and a subservice called /roads
have been
created. All the requests to the platform will include the appropriate ´Fiware-service´ and Fiware-servicepath
headers, as explained here.
Device provisioning at IoT Agent
Let's consider a fleet of several cars that are moving around a given city (Madrid, for example). Each car has an onboard sensor, all them managed by the platform IoT Agents, assuming network connectivity between the sensor and the platform. First of all, the sensor provider has to provision a Configuration Group for its devices. This can be achieved with the following query:
POST /iot/services
Content-Type: application/json
Fiware-service: smartown
Fiware-servicepath: /roads
{
"services": [
{
"protocol": [
"IoTA-UL"
],
"apikey": "801230BJKL23Y9090DSFL123HJK09H324HV8732",
"entity_type": "Car",
"attributes": [
{
"object_id": "s",
"name": "speed",
"type": "Number"
}
]
}
]
}
Once the subservice is configured to use Car entities, cars can start sending their information to the IoTAgents. In this case, the selected IoT Agent is the Ultralight 2.0 Agent. The following request shows how to send the speed to the Context Broker:
POST /iot/d?k=801230BJKL23Y9090DSFL123HJK09H324HV8732&i=BCZ6754
Content-Type: text/plain
s|55
This request will send a speed value of 55 to the IoTAgent, that, in turn will update the entity BCZ6754
of type
Car
in the Context Broker, updating the speed
attribute.
For more details on how the IoTAgents and Ultralight 2.0 work, refer to the Device API.
Subscriptions and notifications at Context Broker
Now that the car speed information is periodically sent to Context Broker, let's see how to configure notifications.
The simplest notification trigger is based on entity attribute changes. For example, in order to get
notifications each time the speed
attribute changes in any entity with type Car
the following
subscription would be used. Notifications will be send to the (sample) endpoint http://example.com/receiver
.
POST /v2/subscriptions
Content-Type: application/json
Fiware-service: smartown
Fiware-servicepath: /roads
{
"subject": {
"entities": [
{
"idPattern": ".*",
"type": "Car"
}
],
"condition": {
"attrs": [ "speed" ]
}
},
"notification": {
"http": {
"url": "http://example.com/receiver"
}
}
}
Subscriptions are first class objects managed by Context Broker, as entities are. Thus, they can be modified after creation, managed (e.g. paused/resumed, etc.) and eventually deleted.
By default the notification includes all the attributes in the entity, i.e. not only speed
but any other
attribute that a Car may have. If you want to receive only a subset of attributes, you can configure it
as part of the notification
field:
...
"notification": {
"http": {
"url": "http://example.com/receiver"
},
"attrs": [ "speed" ]
}
...
Moreover, you can include filters associated to the subscription. For example, in order to get notification not
only each time that speed
changes but also requiring that the speed is greater than 50 km/h and the Car
is located in the center of Madrid city (in particular, 15 km closer to the city center):
...
"conditions": {
"attrs": [ "speed" ],
"expression": {
"q": "speed>50",
"georel": "near;maxDistance:15000",
"geometry": "point",
"coords": "40.418889,-3.691944"
}
}
...
By default, notifications received by http://example.com/receiver
used a "fixed" format, in the following way:
POST http://example.com/receiver
Content-Type: application/json
Fiware-service: smartown
Fiware-servicepath: /roads
{
"subscriptionId": "...",
"data": [
{
"id": "BCZ6754",
"type": "Car",
"speed": {
"value": 57,
"type": "Number",
"metadata": {}
}
}
]
}
You can use the attrsFormat
field in order to select more compact formats (e.g. including just the values of the
attributes, without type or metadata) or, even better, customize completely all the notification parameters.
Customization is done using the httpCustom
field (instead of http
) and supports macro substitution.
For example, you could send text alarms in the following way:
...
"notification": {
"httpCustom": {
"url": "http://example.com/receiver",
"headers": {
"Content-Type": "text/plain"
},
"qs": {
"format": "text"
},
"payload": "Car ${id} speed is ${speed} km/h. Be careful you could be fined!"
},
"attrs": [ "speed" ]
}
...
resulting in notifications like this one:
POST http://example.com/receiver?format=text
Content-Type: text/plain
Car BCZ6754 speed is 57 km/h. Be careful you could be fined!
This is just a brief introduction to the overall subscriptions/notifications functionality. You can find the full details and more examples at the Context Broker documentation and the "Subscriptions" section at the NGSIv2 specification.
The TimeInstant
metadata
As in IoT Platform version v4.1, the default behavior for Context Broker is to send notifications only
when the attribute has actually changed. Thus, if the Car speed
is 67 and Context Broker receives
an update with the value 67 then it doesn't send a notification.
For those use cases that needs notifying each update (no matter if it results on actual value change or not), the
IoTAgent implements a clever mechanism based on adding a TimeInstant
metadata with the timestamp of the update.
This way, it is ensured that from a logical point of view the attribute always changes, as a change in any metadata
is considered a change in the attribute. Look for the TimeInstant
element documentation in the IoT Agent documentation.
In the case of client-provided entities (i.e. entities not managed by IoTAgent but by your application as the DGM2765
entity
shown below) you may need a similar mechanism. In this case, ensure that the TimeInstant
metadata resolution is high enough,
e.g. if your system is able to notify several times per second, then the timestamp resolution should be higher than one second.
PUT /v2/entities/DGM2765/attrs/speed
Content-Type: application/json
Fiware-service: smartown
Fiware-servicepath: /roads
{
"value": 57,
"type": "Number",
"metadata": {
"TimeInstant": {
"value": "2017-06-17T07:21:24.238Z",
"type": "DateTime"
}
}
}