Skip to Content
Author's profile photo Nadine Gaertner

Anki Cozmo meets SAP Cloud Platform – Part 4: UI5 visualization

In this part of the blog we enhance the UI5 app we started setting up in part 1. We add two scatter plots to allow the human controller of our robot to monitor the whereabouts of the robot – as we prepared them in part 2.

This blog is for you if you like to proceed with your Cozmo app in the SAP Cloud Platform (SCP). We will be walking through the following topics:

  • creating scatter plots with VizFrames
  • generating oData services for accessing HANA tables
  • connecting the VizFrame with the oData service

So, this blog might be able to help you even if you are working on such tasks in a different context.

Outline

In the first step, we create a scatter plot based on a VizFrame UI5 element. We connect the VizFrame with the oData service provided by the SCP IoT service. The result is a scatter plot indicating Cozmo’s last locations. Recall that we make Cozmo send its location to the cloud whenever it has completed driving a lap.

In the second step we prepare an oData service which allows us to access the cluster centers from the HANA database as we created them using the Predictive Analytics Library in part 2.

Finally, in the third step, we repeat the scatter plot creation for the cluster centers.

Creating a scatter plot for locations

In this step, we create a new view with a scatter plot VizFrame. See the examples in UI5 Explored if you are interested in more details about scatter plots.

First of all, go to the UI5 Web IDE and open your UI5 application. Start by creating a new SAPUI5 view of type XML in your webapp and pick a view name, for example Location. Add a VizFrame element of vizType ='scatter'.

To adapt the scatter plot to our needs make the following settings for the VizFrame:

  • For the “flattened dataset” refer to the table T_IOT_<location_message_type> which was generated by the IoT service when you configured the message type in part 1
  • As part of the “flattened dataset” configure the columns C_POX and C_POSY as measures, i.e. axes in the scatter plot. Also, create one feed item each for POS_X and POS_Y.
  • Make the column G_CREATED the dimension of the flattened dataset. Recall that we consider the creation timestamp the unique identifier of a data record. So, by making it the dimension the scatter plot will contain one dot per location data record.

For reference, here is how I implemented this in file Location.view.xml

<mvc:View controllerName="<your_ui5_project_name>.controller.Scatter" xmlns="sap.m" xmlns:viz="sap.viz.ui5.controls" xmlns:layout="sap.ui.layout"
	xmlns:mvc="sap.ui.core.mvc" xmlns:viz.feeds="sap.viz.ui5.controls.common.feeds" xmlns:viz.data="sap.viz.ui5.data" height="40%" width="100%">
	<viz:VizFrame id="idVizFrame" uiConfig="{applicationSet:'fiori'}" vizProperties="{ title: {text : 'Cozmo locations', visible : true}}"
		 width="100%" height="100%" vizType='scatter'>
		<viz:dataset>
			<viz.data:FlattenedDataset data="{/T_IOT_<your_location_message_type>}">
				<viz.data:dimensions>
					<viz.data:DimensionDefinition name="G_CREATED" value="{G_CREATED}"/>
				</viz.data:dimensions>
				<viz.data:measures>
					<viz.data:MeasureDefinition name="C_POSX" value="{C_POSX}"/>
					<viz.data:MeasureDefinition name="C_POSY" value="{C_POSY}"/>
				</viz.data:measures>
			</viz.data:FlattenedDataset>
		</viz:dataset>
		<viz:feeds>
			<viz.feeds:FeedItem uid="valueAxis" type="Measure" values="C_POSX"/>
			<viz.feeds:FeedItem uid="valueAxis2" type="Measure" values="C_POSY"/>
		</viz:feeds>
	</viz:VizFrame>
</mvc:View>	

Next, create a controller file, Location.controller.js, for this new view. The minimum logic to be implemented in the controller is the initialization of the view (onInit method). For the initialization, access the VizFrame element from the view, create an oData model instance and link it with the generated oData service from the SCP IoT Service. Recall, that previously, we have created the path alias iotmms in the neo-app.json file and a corresponding SCP destination. This enables us to access the SCP IoT service via path /iotmms. Once the oData model has been set for the VizFrame, the scatter plot gets actually filled with data coming from the IoT Service.

Here is my Location.controller.js for reference:

sap.ui.define([
	'sap/ui/core/mvc/Controller'
], function(Controller) {
	"use strict";

	return Controller.extend("<your_ui5_project_name>.controller.Location", {
		oVizFrame: null,
		onInit: function(evt) {
			var oVizFrame = this.oVizFrame = this.getView().byId("idVizFrame");
			var dataModel = new sap.ui.model.odata.v2.ODataModel("/iotmms/v1/api/http/app.svc/");
			oVizFrame.setModel(dataModel);
		}
	});
});

Finally, embed the new Location.view.xml into the main view of the app, Cozmo.view.xml. To do so, add an element like the following at the end of the Page element:

<mvc:XMLView id="locations" viewName="<your_ui5_project_name>.view.Location"/>

Testing time!

When you now start your application you should see the new scatter plot – with more or less data points, depending on how long you have had your little robot drive around. If you have not disturbed it from driving its endless squares you should be able to roughly locate the corners of the square in the scatter plot.

In the scatter plot as just created we can only roughly see the location hotspots. Next, let’s visualize the actual hotspots as computed by the clustering algorithm in part 2.

New oData service for accessing clusters

For the scatter plot of the plain locations we could make use of the oData service as provided by the IoT Service. For the cluster analysis, so far we have only collected the outcome in a database table. To use this data in a VizFrame element, we first need to prepare an oData service for access. This is what we address in this step.

For eloborate instructions for creating an oData service with an application please check out Simmaco’s blog. For sake of speed, in this blog I am so free as to take some shortcuts – namely by hijacking an existing application.

For creating the oData service the environment to use is the editor of the SAP HANA development workbench. To get there, go to the SAP Cloud Platform Cockpit, then choose “Persistency” and “Databases & Schemas”. Follow the link to your multi-tenant database container (HANA MDC) which you created in part 1. On the overview page, choose the link to the “SAP HANA Web-based Development Workbench”, then go to the “Editor”.

In the editor, expand the content until you reach a package which you are comfortable “enhancing” (this is the hijacking part). For the chosen package, open the context menu and choose “New”, then “File”. Name the file cozmo.xsodata and enter the following content for declaring the oData service which accesses the cluster table from part 2:

service {
    "COZMO"."KM_CENTERS" as "CENTERS"  keys generate local "CENTER_ID"
        create forbidden
        update forbidden
        delete forbidden;
}

Next, save the file and execute it (as indicated in the screenshot). The oData service is now generated for you.

After triggering the execution, an XML file is displayed with the metadata of the oData service. In the XML file, find the xml:base attribute of the service element and take a note of the given URL. You will need the the URL in the next step. The URL of interest should look something like the following:

https://<your_db><your_account>.hanatrial.ondemand.com:443/<path_to_package>/cozmo.xsodata/

New destination for the oData service

Remember how we configured a destination for the message management service of the SCP IoT service? The same kind of configuration is needed for the newly generated oData service before we can use it in the UI5 app.

Once more, go to the SAP Cloud Platform Cockpit, then choose “Connectivity” and “Destinations”.  Create a new destination with a name like “palresults” and assign the properties as per the following screenshot. Note that since we are referring to an oData service in the database, the user to specify for the authentication is the database user, that is, SYSTEM.

Next, go back to the UI5 Web IDE. Recall that a new destination needs to be declared in the routes section of the neo-app.json file. So add the following lines there.

{
	"path": "/palresults",
	"target": {
		"type": "destination",
		"name": "palresults"
	},
	"description": ""
}

After saving you will be able to access the contents of the cluster table via the path /palresults.

Creating a scatter plot for clusters

Now that the oData service is prepared, we can add the second scatter plot with the clusters to the UI5 app. The approach for this is pretty much the same as for the first scatter plot with the plain locations – just that we now use a different oData service.

So, create a new view Hotspot.view.xml and a corresponding controller Hotspot.controller.js. For this, you can copy the Location view and adapt it with the following changes:

  • For the oData model to pass to the VizFrame, simply refer to /palresults/. This is the path which takes you to the destination of the oData service for the cluster table.
  • For the “flattened dataset” refer to/CENTERS for the data. Note that this is the name you declared for the COZMO.KM_CENTERS table in the xsodata file.
  • For the dimensions definition specify CENTER_ID instead of G_CREATED. By making the cluster center id the dimension, the scatter plot will contain one dot per cluster.

Having created the cluster view, implement two final bits before you are ready for testing:

  • Include the Hotspot view in the main view Cozmo.view.xml
  • Adjust the width of the view both in file Hotspot.view.xml and in Location.view.xml to a value below 50% so that both scatter plots can fit next to each other.

For reference, find my implementation regarding the hotspot scatter plot below.

Hotspot.view.xml:

<mvc:View controllerName="<your_ui5_project>.controller.Hotspot" xmlns="sap.m" xmlns:viz="sap.viz.ui5.controls"
	xmlns:layout="sap.ui.layout" xmlns:mvc="sap.ui.core.mvc" xmlns:viz.feeds="sap.viz.ui5.controls.common.feeds"
	xmlns:viz.data="sap.viz.ui5.data" height="40%" width="40%">
	<viz:VizFrame id="idVizFrameHS" uiConfig="{applicationSet:'fiori'}" vizProperties="{ title: {text : 'Hotspots', visible : true}}"
		 width="100%" height="100%" vizType='scatter'>
		<viz:dataset>
			<viz.data:FlattenedDataset data="{/CENTERS}">
				<viz.data:dimensions>
					<viz.data:DimensionDefinition name="CENTER_ID" value="{CENTER_ID}"/>
				</viz.data:dimensions>
				<viz.data:measures>
					<viz.data:MeasureDefinition name="C_POSX" value="{C_POSX}"/>
					<viz.data:MeasureDefinition name="C_POSY" value="{C_POSY}"/>
				</viz.data:measures>
			</viz.data:FlattenedDataset>
		</viz:dataset>
		<viz:feeds>
			<viz.feeds:FeedItem uid="valueAxis" type="Measure" values="C_POSX"/>
			<viz.feeds:FeedItem uid="valueAxis2" type="Measure" values="C_POSY"/>
		</viz:feeds>
	</viz:VizFrame>
</mvc:View>

Hotspot.controller.js:

sap.ui.define([
	"sap/ui/core/mvc/Controller"
], function(Controller) {
	"use strict";

	return Controller.extend("<your_ui5_project_name>.controller.Hotspot", {
		oVizFrameHS: null,
		onInit: function(evt) {
			var oVizFrameHS = this.oVizFrame = this.getView().byId("idVizFrameHS");
			var dataModelHS = new sap.ui.model.odata.v2.ODataModel("/palresults/");
			oVizFrameHS.setModel(dataModelHS);
		}
	});
});

Cozmo.view.xml:

<mvc:XMLView id="hotspots" viewName="<your_ui5_project_name>.view.Hotspot"/>

 

Testing time!

When you now start your application you should see the second scatter plot.

Congratulations for making it up to here! Hope you enjoy your extended UI5 app – and hope this tutorial also helped you understand a little more about UI5 VizFrames, oData and how they go together.

Perfectionists are now invited to tune the layout, align the min and max values of the scatter plots’ axes, add more features – and so on…

Have fun making this little starter app more beautiful and more useful!

 

Assigned Tags

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