Skip to Content
Technical Articles

Invoke several APIs within SAP Leonardo IoT Rules and Actions

 

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 Sensor. 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:

  • Name: any name (i.e.: “IoTS_rail_commands”)
  • Type: HTTP
  • URL: using as reference the IoTS API Docs the call is a POST to the endpoint with the following format: https://{hostname}/{instanceid}/iot/core/api/v1/tenant/{tenantId}/devices/{deviceId}/commands (the address used in this example to have a connection with my device is https://160bee76-3185-40da-9e14-696e48a9ac51.eu10.cp.iot.sap/160bee76-3185-40da-9e14-696e48a9ac51/iot/core/api/v1/tenant/1773169968/devices/04bd1748-e7d2-43b1-a504-3341b8c9e9c2/commands)
  • Proxy Type: Internet
  • Authentication: BasicAuthentication
  • User: <use your IoT Service username>
  • Password: <use your IoT Service password>

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:

  • Body:
{
	"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:

  • Body:
{
	"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/Events)
  • 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/Events)

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 3rd party endpoints.

 

Be the first to leave a comment
You must be Logged on to comment or reply to a post.