Introduction
In part two of the blog post series, we have published the Equipment Model and created one Equipment from the Model. Afterwards, we checked and retrieved the mapping of the Objects to the external Systems.
In this part of the blog post, we are going to upload sensor data to Leonardo IoT and verify that it arrives in the SAP Predictive Maintenance and Service (PdMS).
Previous Posts
Pre-Requisites
To upload sensor data to Leonardo IoT (the new name of IoT Application Enablement), we need the authorization to do so. This means, we either need a service key or we need to be able to login into the Leonardo IoT Launchpad. In this blog post, we are using the service key method.
Recap
In the last blog post we created one Equipment (Asset Central Id: 44F6588537524198BF895C376D0B81FF and Thing Id: CF1446EF0F3B481684E3F1E1A391E182) which we created from Model Weather Station (Asset Central Id: D9B4D6A2FDBA4E888A7527220D351150, ThingType: dca.demo.sap.weatherstation:M_Weather_Station).
We have the following mappings for Indicator and Indicator Groups:
Indicator Group |
Property Set Type |
Property Set |
Measurements |
dca.demo.sap.weatherstation:IG_Measurements |
IG_Measurements0 |
Scores |
dca.demo.sap.weatherstation:IG_Scores |
IG_Scores0 |
and the following mapping for the Indicators:
Indicator |
Property |
Temperature |
I_Temperature |
Pressure |
I_Pressure |
Humidity |
I_Humidity |
Score |
I_Score |
Normalized_Score |
I_Normalized_Score |
Make sure to replace the IDs in this blog post with the IDs of your system!
Get a JWT token for Authentication and Authorization
The easiest way to authenticate and authorize against Leonardo IoT is to use the service key. There is good description how to get the service key in
this help article.
Once you have obtained the clientId and clientSecret for your Leonardo IoT tenant we can do a curl request do retrieve a so-called JWT token from the SAP UAA. As in the other blog posts, we will store the JWT token in the headers.txt file to use it later in our requests to the Leonardo IoT APIs. In the following call replace the placeholders (<tenant-subdomain>, <clientId>, <clientSecret>) with the actual values taken from your service keys:
curl -X POST \
https://<tenant-subdomain>.authentication.eu10.hana.ondemand.com/oauth/token \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&response_type=token&client_id=<clientId>&client_secret=<clientSecret>' | jq -r '.access_token' | sed 's/^/Authorization: Bearer /' > headers.txt
After sending this request, your headers.txt should somehow similar like this:
➜ ~ cat headers.txt
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vZGNhLWRlbW8tbGl2ZS5hdXRoZW50aWNhdGlvbi5ldTEwLmhhbmEub25kZW1hbmQuY29tL3Rva2VuX2tleXMiLCJraWQiOiJrZXktaWQtMSIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1YjM5MmVmMjMyYWE0YjRmYmZlYjg3YTk0ODgwMTA0NCIsImV4dF9hdHRyIjp7ImVuaGFuY2VyIjoiWFNVQUEiLCJ6ZG4iOiJkY2EtZGVtby1saXZlIiwic2VydmljZWluc3RhbmNlaWQiOiIzNWU4MGQyMS0xOGQxLTRjYmEtYjZiYS05NDRmMzhlMzE5MDcifSwic3ViIjoic2ItMzVlODBkMjEtMThkMS00Y2JhLWI2YmEtOTQ0ZjM4ZTMxOTA3IWIxNDY3MXxpb3RhZV9zZXJ2aWNlIWI1IiwiYXV0aG9yaXRpZXMiOlsiYXV0aCF0NS5jb25mLmMiLCJhdXRoIXQ1LmNvbmYuZCIsInRnIXQ1LnUiLCJ0ZW5hbnQhdDUucGVycy5jIiwidGhpbmchdDUuRXZlbnQuciIsInRlbmFudCF0NS5wZXJzLmQiLCJ0aGluZyF0NS5FdmVudC51IiwidGchdDUuciIsImF1dGghdDUuY29uZi5yIiwidGchdDUuYyIsInRnIXQ1LmQiLCJjb25mIXQ1LnIiLCJ0ZW5hbnQhdDUucGVycy5yIiwidGVuYW50IXQ1LnBlcnMudSIsInVhYS5yZXNvdXJjZSIsImNvbGRzdG9yZSF0NS5yIiwiaW90YXMhdDUuQXNzaWdubWVudC5yIiwiYmRtIXQ1LnIiLCJpb3RhcyF0NS5Bc3NpZ25tZW50LmMiLCJpb3RhcyF0NS5Bc3NpZ25tZW50LmQiLCJvaHMhdDUudSIsImJwIXQ1LmMiLCJvaHMhdDUuciIsImJwIXQ1LmQiLCJpb3RhcyF0NS5nZW9sb2NhdGlvbi5yIiwiaW90YXMhdDUuVm9jYWJ1bGFyeS5yIiwidGhpbmdjb25mIXQ1LmQiLCJpb3RhcyF0NS5BTS5jIiwiaW90YWVfc2VydmljZSFiNS5DYWxsYmFjayIsInRoaW5nY29uZiF0NS5jIiwiaW90YXMhdDUuQU0uZCIsImJwIXQ1LnZoLnIiLCJhdXRoIXQ1LmMiLCJpb3RhcyF0NS5Wb2NhYnVsYXJ5LnUiLCJ0aGluZyF0NS5kIiwiaW90YXMhdDUuZ2VvbG9jYXRpb24uZCIsInRoaW5nIXQ1LmMiLCJicCF0NS5yIiwiaW90YXMhdDUuQXNzaWdubWVudC51IiwiY29tcGNkIXQ1LnIiLCJicC...
After a while, the JWT will expire and you have to run the above command again.
Get Sensor Data for Indicator Group 'Measurements'
Generally to view or upload data we have to use the appiot-mds service of Leonardo IoT.
To retrieve the data for Thing 'CF1446EF0F3B481684E3F1E1A391E182' of ThingType 'dca.demo.sap.weatherstation:M_Weather_Station' and PropertySet 'IG_Measurements0' in the time range from 2019-06-01T00:00:00Z to 2019-06-02T00:00:00Z we can send the following request:
curl -H @headers.txt -s \
"https://appiot-mds.cfapps.eu10.hana.ondemand.com/Things('CF1446EF0F3B481684E3F1E1A391E182')/dca.demo.sap.weatherstation:M_Weather_Station/IG_Measurements0?timerange=2019-06-01T00:00:00Z-2019-06-02T00:00:00Z" | jq .
Response:
{
"value": []
}
The response indicates that there is no data ([]) available for that time range. Let's upload our first entry
🙂
Upload Sensor Data
The payload for two example sensor readings is in the snippet below. Feel free to modify the date in the '_time' property of the readings. Especially when you get a respond from the API that "_time cannot be beyond retention period". This means that the timestamp of the sensor data are not in the retention period of the time series store. In that case, use more recent dates (easy) or adjust the retention period in Leonardo IoT.
{
"value":[
{
"_time":"2019-06-01T01:00:00Z",
"I_Temperature":1,
"I_Pressure":2,
"I_Humidity":3
},
{
"_time":"2019-06-01T02:00:00Z",
"I_Temperature":4,
"I_Pressure":5,
"I_Humidity":6
}
]
}
The following curl command uploads it:
curl -X PUT \
-H @headers.txt \
-H 'Content-Type: application/json' \
"https://appiot-mds.cfapps.eu10.hana.ondemand.com/Things('CF1446EF0F3B481684E3F1E1A391E182')/dca.demo.sap.weatherstation:M_Weather_Station/IG_Measurements0" \
-d '{
"value": [
{
"_time": "2019-06-01T01:00:00Z",
"I_Temperature": 1,
"I_Pressure": 2,
"I_Humidity": 3
},
{
"_time": "2019-06-01T02:00:00Z",
"I_Temperature": 4,
"I_Pressure": 5,
"I_Humidity": 6
}
]
}'
We can check if data is uploaded by executing the command from above again:
➜ ~ curl -H @headers.txt -s \
"https://appiot-mds.cfapps.eu10.hana.ondemand.com/Things('CF1446EF0F3B481684E3F1E1A391E182')/dca.demo.sap.weatherstation:M_Weather_Station/IG_Measurements0?timerange=2019-06-01T00:00:00Z-2019-06-02T00:00:00Z" | jq .
Response:
{
"value": [
{
"_time": "2019-06-01T02:00:00.000Z",
"I_Temperature": 4,
"I_Humidity": 6,
"I_Pressure": 5
},
{
"_time": "2019-06-01T01:00:00.000Z",
"I_Temperature": 1,
"I_Humidity": 3,
"I_Pressure": 2
}
]
}
Which now returns the data we uploaded!
Verify Data in PdMS
When we now go to the PdMS Equipment page of this Equipment and open the Indicator Chart, we see that our two readings have been uploaded. It can take a few moments for them to appear, because Leonardo IoT computes M4 aggregates to be able to visualise large quantity of data.
Delete Sensor Data
The Delete request is similar to the Get request, just that a different Http-Verb is used:
curl -H @headers.txt -X DELETE -s \
"https://appiot-mds.cfapps.eu10.hana.ondemand.com/Things('CF1446EF0F3B481684E3F1E1A391E182')/dca.demo.sap.weatherstation:M_Weather_Station/IG_Measurements0?timerange=2019-06-01T00:00:00Z-2019-06-02T00:00:00Z"
When you now Refresh the Indicator Chart or send the Get request to the API again, the data should be gone:
To upload larger amount of data is advisable to use a scripting language like Python to construct the payload for the API.
That concludes this part of the blog post series, in which you have seen how to bring sensor data into PdMS through Leonardo IoT.