In
my last blog post I’ve explained how to create a ticket for a service request in SAP Cloud for Customer within an SAP Leonardo IoT action.
Today I would like to show how to invoke APIs from different endpoints while using the SAP Leonardo IoT actions focusing on the fact that it's possible to invoke more than one action per event.
Let’s assume that your
Thing is already configured and
SAP Leonardo IoT is currently ingesting data correctly for your asset.
The
SAP Cloud Platform Internet of Things device has already been onboarded and is currently communicating with the platform. It will be given just a short overview on the device modelling.
Use case 1
The scenario I'd like to explain in this first use case is a Rule that trigger an Action to send a command to a physical end-device.
The command is sent to the end-device by using the
SAP Cloud Platform Internet of Thing APIs.
The story
Our device is a vital part of an equipment in the railway environment that is called in short
git; it is in redundancy with at least one replica, and is able to monitor his own status. In case of failure certain actions must be invoked for security reasons.
In particular our device is currently sending as measurement to SAP Cloud Platform IoT Service and SAP Leonardo IoT a counter with the number of errors and problems detected from the startup of the physical device. If this number is higher than a fixed threshold, we would like to invoke one of the available device commands (for example the reboot command or the stop).
Device modelling
The device provisioned into the SAP Cloud Platform Internet of Things instance have only one S
ensor. His sensor is described by the
Sensor Type named
gitSensorType that is composed of the following
Capabilities:
- git: this is the number of the rotations of the current git sensor, that is the physical measurement
- errors: it contains the device error counters of and the type of the errors. This value will be evaluated within the Rule of SAP Leonardo IoT
The Sensor Type gitSensorType contains also a Capability with type
command:
- commands: this is the command we are going to invoke within the SAP Leonardo IoT Action.
In particular the command has 3
Properties:
- Reboot
- Stop
- SystemFailure
All the properties are of type
Boolean and are evaluated with a prioritization schema. If more than one is set to
true only the one with the higher priority is computed and his related command invoked.
In the next part, SAP Leonardo IoT uses the
SAP Cloud Platform Cockpit Destinations to invoke the HTTP calls. It means that a new destination to connect the
Action with
SAP Cloud Platform Internet of Things Device Management module needs to be created, to issue correctly the command.
Destination
To complete this step, you need to open into the Cloud Platform cockpit, your Cloud Foundry subaccount, then press “
Destination” in the menu on the left, under “
Connections” and create a new Connection with the following details:
Note: Ensure that in the
URL the
deviceId is used and not the deviceAlternateId, otherwise the command will not be invoked correctly.
Rule
In this step I’ll show you how to configure the
Rule Context and the
Rule.
First of all, open the
Rule Contexts tile of your
SAP Leonardo IoT Fiori launchpad and create a new Rule Context linked to the Thing Type and Properties which you have already onboarded before (not explained in this blog post, please refer to the
official tutorial).
The Rule Context used is built over the
git Thing Type and is using the
nError property
Now we can proceed with Rule modelling: open the
Rules tile in the Fiori launchpad and create a
New Rule of type “
Streaming”.
After the specification of a rule name and, optionally a description, navigate the tab
editor and as
Rule Context select the one created in the step before, to enable the usage of the property
nErrors in the condition of your rule.
The purpose of the rule is to notify when a certain number of errors have been detected (10 is the threshold).
In fact the condition
“nErrors of the measures is greater than 10” will raise an event called
“rebootRequired” that will be used to fire action in the next step.
After the creation press the
Activate button to start the scheduling of the rule.
Action
Open the
Actions tile of SAP Leonardo IoT Fiori Launchpad and press “
New” to create a record.
This action is using the
HTTP cloud destination created before to invoke the
POST API to send a command to the device.
The parameters of the Action are:
- a name for the action, e.g. Reboot_caused_by_errors
- triggered by “Event from Rule”
- Use the rule at the previous step as “Rule”
- Action Type: HTTP
- In the drop down of the destination, use the destination you have created for your deviceId in the Cloud Cockpit
- Invocation Type: Auto
- Method: POST
- Trigger subsequent event: checked; leave it checked to permit others to consume the event
- Response Payload Type: XML
- For the request body put a JSON object such as:
{
"capabilityId": "5c4f6359-d97e-4e1f-9159-3c5dfda65409",
"command": {
"Reboot": true,
"Stop": false,
"SystemFailure": false
},
"sensorId": "b6e98738-bb04-41a6-846c-1106569fc4f0"
}
The capabilityId is the id (and not the
alternateId) of the capability
commands; you can discover it directly with the Internet of Things Cockpit.
Similarly, you have to detect the
sensorId of the sensor
git.
Verification
Our device is going to consume the command specified into the payload and the native reboot will be invoked.
Let’s assume that the status of the device is logged with a serial port, that means we will have a feedback of the device status and the executed operations.
Unfortunately in the example we are not using a real device, but a simulator, so we can simulate a certain numbers of errors , that will cause an increment of the nErrors value and all the consumed commands are logged directly into a file, like for the real device but without using any serial port.
After we have simulated 11 anomalies the nErrors counter is over the threshold. It means that the action has been triggered and the reboot command invoked.
This is the content of the log file:
//.....................//
INFO [git] --- git1-1 --- Received command for git: git1-1. Arguments: "Reboot": true, "Stop": false, "SystemFailure": false
INFO [git] --- git1-1 --- Processing Command: "SystemFailure": false -- Nothing to do
INFO [git] --- git1-1 --- Processing Command: "Stop": false -- Nothing to do
INFO [git] --- git1-1 --- Processing Command: "Reboot": true -- Invoking command...
INFO [git] --- git1-1 --- Reboot command sent
WARN [git] --- git1-1 --- SIGTERM
INFO [git] --- git1-1 --- Bootup of git1-1...
//.....................//
Use case 2
One common question: is it possible to call more than one action with just one rule? Or am I forced to duplicate the rule in case the scenario requires to be executed more than one action for certain conditions?
SAP Leonardo IoT Rules and Actions are in a
1:n ratio. It means that it’s possible to invoke more than one action with just one rule.
In this second part, as extension of the first use case of this blog post, the same rule created in the first part will also call a second action which invokes an API of SAP Leonardo IoT to create a
Custom Event.
Scenario
The device is in a critical status, too many errors have been generated: we would like to reboot it and save a custom SAP Leonardo IoT event that collect several non-standard properties.
The first part has already been implemented in the use case 1, let’s now focus on the creation of the custom event.
Event Type
First of all there is the creation of a custom event type. Since it’s an operation that is executed just one time, in this post we are using
Postman to create it. Any other rest client could be used instead (for example curl).
To proceed with the next steps you need to discover what is you oData event endpoint and your oAuth2 authentication details.
oAuth2 Details
To discover them go to
SAP Cloud Platform Cockpit and open the
Cloud Foundry subaccount; go to
Spaces and navigate the space where the instance of
SAP Leonardo IoT has been created during the onboarding phase.
Click
Service Instances and open the instance with Service name “
iotae” and then
Service Keys.
In the JSON of your keys copy the address of “
events-sap” that will be used later to invoke the event type creation (e.g.: "events-sap":
https://events-sap.cfapps.eu10.hana.ondemand.com)
Now copy the oAuth2 details that are in the
uua subpart; in particular we need to use the following fields:
Create Property Set
Open
Postman and create a new call with type
POST.
In the authorization tab select
oAuth2 compile the form to
Get New Access Token.
The access token url is the url taken from your
SAP Cloud Platform Cockpit by adding at the end of the address
/oauth/token (e.g:
https://iotpmdemosenv.authentication.eu10.hana.ondemand.com/oauth/token)
In the header section of the request add a new header with:
- Key: “Content-Type”
- Value: “application/json”
Now let’s compile the body of the
POST and the address:
{
"Name": "iot.iotpmdemosenv.rail:gitCriticalStatusSet",
"PackageName": "iot.iotpmdemosenv.rail",
"Descriptions": [{
"LanguageCode": "en",
"Description": "gitCriticalStatusSet"
}, {
"LanguageCode": "it",
"Description": "gitCriticalStatusSet"
}],
"DataCategory": "EventData",
"Properties": [{
"Name": "gitCriticalStatus",
"Type": "String",
"PropertyLength": "127",
"Descriptions": [{
"LanguageCode": "en",
"Description": "git critical status"
}, {
"LanguageCode": "it",
"Description": "Stato critic per il git"
}]
}]
}
Press Send to create it. An HTTP status 201 of the response identify a success.
The events name are always categorized the fully qualified package name format (
<qualified_tenant_name>.<package> : iot.iotpmdemosenv.rail)
Create EventType
Use the same oAuth token and headers of the step before, and compile the
POST method with the following details:
{
"Name": "iot.iotpmdemosenv.rail:gitCritical",
"EventTypeState": "Mutable",
"Descriptions": [{
"LanguageCode": "en",
"Description": "Event type for gitCritical"
}, {
"LanguageCode": "it",
"Description": "Event type gitCritical"
}],
"PackageName": "iot.iotpmdemosenv.rail",
"PropertySetId": "gitCriticalStatusSet",
"PropertySetType": "iot.iotpmdemosenv.rail:gitCriticalStatusSet",
"PropertySetDescriptions": [{
"LanguageCode": "en",
"Description": "git property set type"
}],
"Statuses": [{
"EventStatus": "New",
"Descriptions": [{
"LanguageCode": "en",
"Description": "New event: git status critical"
}]
}, {
"EventStatus": "Reboot",
"Descriptions": [{
"LanguageCode": "en",
"Description": "Invoked reboot for the git"
}]
}, {
"EventStatus": "Stop",
"Descriptions": [{
"LanguageCode": "en",
"Description": "Invoked the STOP for the git"
}]
}, {
"EventStatus": "GeneralFailure",
"Descriptions": [{
"LanguageCode": "en",
"Description": "git general failure"
}]
}, {
"EventStatus": "Done",
"Descriptions": [{
"LanguageCode": "en",
"Description": "Completed git status critical"
}]
}, {
"EventStatus": "RebootDone",
"Descriptions": [{
"LanguageCode": "en",
"Description": "git reboot completed"
}]
}, {
"EventStatus": "StopDone",
"Descriptions": [{
"LanguageCode": "en",
"Description": "git STOP completed"
}]
}],
"Severities": [{
"EventSeverity": 1,
"Descriptions": [{
"LanguageCode": "en",
"Description": "High"
}]
}, {
"EventSeverity": 2,
"Descriptions": [{
"LanguageCode": "en",
"Description": "Medium"
}]
}, {
"EventSeverity": 3,
"Descriptions": [{
"LanguageCode": "en",
"Description": "Low"
}]
}],
"Codes": [{
"EventCode": "EQ12",
"Descriptions": [{
"LanguageCode": "en",
"Description": "Event Code 12"
}]
}]
}
The
EventTypeState is set to
Mutable. This means that you will be able to modify or remove the events. If this field is not specified in the JSON or specified as
Immutable there is no way to modify or remove the created events.
Press Send to create it. An HTTP status 201 of the response identify a success.
Destination
In order to invoke an API of SAP Leonardo IoT you need to create a new connection in
SAP Cloud Cockpit Destinations with the following details:
- Name: any name (i.e.: “IoTS_rail_commands”)
- Type: HTTP
- URL: it must be the final url of the Events endpoint that is with the following format: <“event-sap” endpoint>/ES/EventType/<event type name>/v1/Events (in the example it is https://events-sap.cfapps.eu10.hana.ondemand.com/ES/EventType/iot.iotpmdemosenv.rail:gitCritical/v1/...)
- Proxy Type: Internet
- Authentication: OAuth2UserTokenExchange
- Client ID: <use the client id copied before>
- Client Secret: <use the client secret copied before>
- Token Service URL: <use the same value used in Postman for the oAuth2 authentication>
A new Action
Open the
Actions tile of SAP Leonardo IoT Fiori Launchpad and press “
New” to create another action.
The parameters of the Action are:
- a name for the action, e.g. CustomEvent_caused_by_errors
- triggered by “Event from Rule”
- Use the rule at the previous step as “Rule”
- Action Type HTTP
- In the drop down of the destination, use the destination you have created for the Events in the SAP Cloud Cockpit
- Invocation Type: Auto
- Method: POST
- Trigger subsequent event: checked; leave it checked to permit others to consume the event
- Response Payload Type: XML
- For the request body put a JSON object such as:
{
"BusinessTimestamp": "${event.time}",
"Type": "Alert",
"EventInfo": "Alert on git",
"EventStatus": "New",
"EventSeverity": 1,
"EventCode": null,
"EventSource": null,
"ThingId": "${thing.id}",
"ThingProperty": "Too many errors for the git",
"ExternalId": "gitError"
}
Verification
To verify the behavior we have to force again the triggering of the Rule.
First of all we can verify that the action of the use case 1 is still executed; as expected the log identify again that a reboot have been invoked.
Open again
Postman and create a
GET Method.
Use the same
oAuth token and headers used for the
EventType creation and use the following address: <“event-sap” endpoint>/ES/EventType/<event type name>/v1/Events (the address for our example is:
https://events-sap.cfapps.eu10.hana.ondemand.com/ES/EventType/iot.iotpmdemosenv.rail:gitCritical/v1/...)
In case of success, the result of the HTTP request is 200, and in the body of the response you can verify the presence of one Event, created by the action.
Conclusion
In this blog post I’ve shown how to invoke more than one action and both the actions where invoking an SAP services. In a similar way it’s possible to invoke also 3
rd party endpoints.