Meet Keggy – the IoT kegerator powered by OpenUI5 and SAP HANA
In this blog (being my first one) I’m going to explain to you a UI5 application that receives and displays data from an IoT device we named Keggy – an Arduino with WiFi shield connected to a kegerator. Keggy also likes to tweet a lot – but more on this later.
Reaching out to people at GlueCon is an important step towards bringing new technologies to the market such as HCP, OpenUI5 or even first approaches of IoT.
This year, SAP went to GlueCon with a very exciting use-case: a beer kegerator that communicates with a HANA instance to transfer data every time beer is poured, the door is opened or the temperature changes. In order to showcase that we actually get real time data from the kegerator, we implemented a web app with OpenUI5. We wanted it to be a monitor, optimized for mobile devices, as the web app would be running on tablets. That being said, what would be a better fitting framework than OpenUI5?
Let’s start with the design of our XML-Views for the beginning, but first of all have a view on this wonderful kegerator and the application which can be seen on the devices in the back (just to get a first impression):
First of all, we want to depict what we are going to build. The Ardunio connected to the kegerator gives us information about:
- How much beer is poured at which point of time?
- When is the door being closed or opened?
- How much beer is left in the barrel?
- What is the temperature of the beer inside at which point of time?
With this data, we started building an UI that refreshes itself every three seconds and gives the user the opportunity to see what’s going on inside the barrel – everything being responsive enough and especially designed to run on a mobile device. So, what we want to do is create an XMLView that shows us information about the beer brand, type of beer, barrel size etc. in a bar at the top of the screen. It shall then provide the IoT kegerators data in different charts on the main area of the screen. The data is refreshed every third second. To save space, we are going to add another bar to the bottom of the screen to show the percentage of the capacity of our barrel and the date and time when the door has been opened/closed recently. We are going to use a lightweight and easy-to-use JS library called “Chart.js” which allows us to generate charts on the screen. Obviously, that saves a lot of time. Now that our goal is set, let’s get started!
We’ll build the UI with the Web-Development-Workbench of SAP HANA, but for a first approach Plunker (an easy-to-use online web development environment, http://plnkr.co/) will serve us great. Its ability to directly show the results of your programming on the right side of the screen (refreshing automatically) is perfect for fast UI development.
For our app we’ll only want one MasterView which displays all of the information. An XMLView will work just fine for that, as it enforces the separation between model, view and controller. In case you didn’t know: An XMLView works descriptively which means that there is no functional logic in it. This helps us implement the MVC concept in a cleaner way. The MasterView is placed on a JSView which only sets up the initial processes and adds the MasterView as its first and only page.
It’ll need a lot of CSS customization afterwards because of several features and containers which cannot be added as simple and flawless as UI5 claims it to be. The following pictures show you the final UI of the app. The first one is displaying the temperature over time, while the second is displaying the beer flow for specific points of time.
Now that the view is defined we can start adding components. The view needs a sap.m.Page to display the content of course. Because we want a lot of information being displayed in the top, the page’s aggregation “customHeader” will provide a customizable sap.m.Bar that we can insert. It needs an ID to edit its design properties afterwards in the CSS file “style.css” that is going to be referenced in the “index.html”. The bar will have a lot of content so it makes sense to distribute the information to the bar’s aggregations contentLeft, contentMiddle and contentRight. On the left side there’s going to be a sap.ui.layout.VerticalLayout (or after the namespace identifier in the view’s properties <l:VerticalLayout>) which contains the barrel-size and unit, the beer type, brewery location and brewery type. The content in the middle will only be a sap.m.Image which is filled with the icon of our beer brand being currently used. Because the text of our picture is quite small, we want to do some CSS customization to give it more space on the screen. This will make our sap.m.Bar bigger, therefore the picture better readable and it will align our objects right. The right side contains a RatingIndicator for the beer type and an indicator for which chart is currently active. All information is retrieved by the “LocalModel.json” which is bound to the view and contains all relevant information displayed on the screen like size, unit, brand, rating and the measures provided by the ODATA service. The model is initially loaded from the controller and allows us to communicate with the view without having to use a lot of variables. It is also bound to the respective UI components. The following picture shows an excerpt:
The main area of the view contains a sap.m.Carousel which includes three pages. Those pages represent the different charts that can be displayed. Because of the size of one chart and the requirement to make it readable for the user on a mobile device you can swipe easily between the three screens. The carousel, unlike tabs e.g., is optimized for mobile devices and adds value to the UX. The following picture shows the way the carousel is described in our XMLView. Pure HTML code is integrated into the screen of the carousel. This allows us to use Chart.js without writing a new component.
The view’s footer is another customized sap.m.Bar which contains information about the door being opened or closed recently (just sap.m.Labels and sap.m.Texts bound to the model) on the left, a sap.m.ProgressIndicator in the middle which shows the current percentage of beer left in the barrel and the current temperature of the beer in the right content.
The MasterView’s controller implements all the logic of receiving, formatting and passing data from the ODATA service to the view.
It initially sets the JSONModel for our view to have an appropriate binding from the beginning on. After the model is defined and we declared some global variables in the onInit() function, the onAfterRendering() function is invoked. This one is going to call an anonymous function after an interval of 3s which permanently loads the most recent temperature, pours and other activities via the following functions (which use Chart.js http://www.chartjs.org/docs/#getting-started ):
This function loads the most recent pours with an AJAX call which then will update the complete consumption in the model as well as the beer left in the current barrel. Those changes regard the model only in the first place, but as the model’s data is changed the UI elements will also change after refreshing the model. That leads to the progressIndicator in our footer being updated e.g.
After the updates on the model are done, it is time to change the charts. Those are recreated every time new data is provided and filled with it. It’s a very descriptive procedure which I won’t elaborate right now. Let’s just say that you need to read the documentation of Chart.js carefully and find the properties of Chart.Line and Chart.Bar that are necessary.
This function loads the most recent temperature values with an AJAX call, updates the model to make sure the TextFields are labeled correctly and fills an array with temperature values and dates to then display them on another chart which is filled just as mentioned before.
This function loads the most recent changes of the kegerator’s door whether it’s been opened or closed and applies the changes to the model (which then applies the changes to the UI). If there has been a change in the doors state the controller will fire a tweet via Twilio API
Another little easter egg in our application would be an API that allows us to send POST requests to Twitter. Twilio combined with IFTTT provide us with such a functionality so that we can easily send an AJAX POST request to Twilio, if the most recent pour date is higher than the last date. Twilio then forwards the message to IFTTT via SMS where a tweet is posted every time a message with specific information from Twilios number arrives.
Issues and Conclusion
Another lesson learned is the variety of opportunities to customize OpenUI5. Being able to react to data model changes with Twitter posts (via Twilio and IFTTT) is a great thing. The flawless integration of an external library (Chart.js) was essential in creating dynamic charts with ease. Plunker as a web development environment is able to integrate the UI5 framework. It is a great way of testing your app or little functions as it usually runs a lot faster than the HANA Web-based Development workbench and a lot more stable than the current WebIDE.
For any questions on the blog, please reach out via mail 🙂