04/04/2024

How to create a kiosk type plug-and-play Qt based HMI application on ctrlX CORE X7

Introduction

This article will explore the possibility to develop a kiosk type native HMI application displaying on any screen/monitor without using web interface but directly from the Display Port on the ctrlX Core X5/X7. We will start from the code all the way to the packaging the app in a snap which can be easily installed and managed from our ctrlX OS app management.

NOTE: This is only a demo example, use it at your own discretion. There is currently no official Bosch Rexroth support available for the Qt software package integration.

Requirements

  • ctrlX Core X5/X7 with System Image v1.20.9
  • Local Operating System: Ubuntu 20.4
  • Qt v6.2.x
  • Qt Creator
  • Snapcraft
    • Tool to build snaps
    • You can install it by running the following in your terminal
      sudo snap install snapcraft --classic​
  • Multipass
    • Light weight VM Manager to build snaps
    • You can install it by running the following in your terminal
      sudo snap install multipass​

Step 1: Create a project in Qt Creator

Before diving in, please make sure you have properly installed Qt and Qt Creator after which you would see something as follows:

Selecting Qt Creator from apps
 
Verify Qt version

Let's begin. Open Qt Creator and click "New Project".

Click on "New Project"

While creating new project, select a Qt Widgets Application template to start with as shown in the image below. You can also create a Qt Quick Application but we will go with widgets based application for now.

Choose "Qt Widget Application"

Choose a name and default project path for your project and click Next.

Give appropriate name for project

Select the build system as "CMake" which is generally used for cross-platform applications. CMake creates a config file in your project folder which would be used to compile the project using snapcraft off your system.

CMake build

Further, as shown below, you could rename the base classes and source code files of the template if you want but we will keep as it is for the sake of simplicity.

Keep Class and File names as it is

Then, we will skip the translation part for by clicking next. Afterwards you would see the step to select the kit (Qt versions) for your project. We would go with the Qt v6.2.4 for this example as shown below in the images (Make you have installed the Qt package before this step and updated the aptitude/apt ). Last step would be to add version control in your project like (Git, SVN, etc.) which we would not at this point so just click finish.

Skip Translation part for now

Select the Qt 6.2.4 Desktop kit

Step 2: Modify the project in Qt Creator

After the initial project selections, you should see the IDE-like space to edit and modify your project. On the left vertical pane, you should see the base header files (*.h) , C++ source files (*.cpp) and a "mainwindow.ui" file. Now lets begin with editing the "mainwindow.ui" file.

Select "mainwindow.ui" file to edit

As shown below, you can edit and design the main window just as any HMI using push buttons, checkboxes, images, sliders, etc.(Note: If you are inserting images then you would have to create a Qt Resource File (*.qrc) in your project root folder and include those images in order to pick those up by Qt).

Adding a button
    
Designing the UI

This is how you can create a Qt Resouce file (here application.qrc) and include all your images to display them while execution:

Adding a new file at root folder

Select "Qt Resource File"

Add images in Qt Resource File

Step 3: Run and test your project in the local env

Run and Test project in local env

Before running the project, make sure your CMake path is properly set in the project settings along with the QMake, Qt and other variables as follows:

Verify CMake configuration

Now, if all set and good to go then you can run the project to see the output on your local screen. You would see the output as in the following image. If you see no errors while compilation then you have done the great job so far.

Qt Project Output with no errors

Step 4: Configure Snapcraft YAML

On building or running the project, Qt Creator creates a sibling directory starting with "build_<project_name>...." and ending with "...-Debug" or "...-Release" depending on your project settings which contains the executable file of your project.

Now, copy your original project root directory and paste into one of these sibling directory (before pasting you might how to rename the executable file to prevent name conflicts).

Create a new directory "snap" at: build_your_project_name....-Debug > snap, then create a new "snapcraft.yaml" YAML file in the newly created "snap" folder.

Create a new "snap" directory

Create a new file "snapcraft.yaml"

Edit "snapcraft.yaml"

Open the "snapcraft.yaml" file in any text editor and copy paste the following contents. You can also download the "snapcraft.yaml" file from the attachments at the end of the page.

name: desktop-rexroth-qt6  # you probably want to 'snapcraft register <name>'
version: "0.1" # just for humans, typically '1.2+git' or '1.3.2'
summary: Testing GUI on X7 using DisplayPort # 79 char long summary
description: |
  This test would be exciting
confinement: strict
compression: lzo
grade: stable
base: core20


package-repositories:
  - type: apt
    ppa: daschuer/qt6-backports


apps:
  desktop-rexroth-qt6:
    command-chain: &_command-chain
      - bin/wayland-launch
    command: &_command usr/local/bin/desktop_rexroth

    plugs: &_plugs
      - opengl
      - wayland

    environment:
      QT_QPA_PLATFORM: wayland
      QT_PLUGIN_PATH: ${SNAP}/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/qt6/plugins/
      QT_QPA_PLATFORM_PLUGIN_PATH: ${SNAP}/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/qt6/plugins/platforms/
      QML2_IMPORT_PATH: ${SNAP}/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/qt6/qml
      QML_IMPORT_PATH: ${SNAP}/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/qt6/qml
      FONTCONFIG_PATH: ${SNAP}/etc/fonts/
      FONTCONFIG_FILE: ${SNAP}/etc/fonts/fonts.conf

  daemon:
    daemon: simple
    restart-delay: 3s
    restart-condition: always
    command-chain: *_command-chain
    command: *_command
    plugs: *_plugs

plugs:
  graphics-core20:
    interface: content
    target: $SNAP/graphics
    default-provider: mesa-core20

environment:
  # This is one of four snippets that relate to providing the userspace graphics needed by your application.
  LD_LIBRARY_PATH:    $SNAP/graphics/lib
  LIBGL_DRIVERS_PATH: $SNAP/graphics/dri
  LIBVA_DRIVERS_PATH: $SNAP/graphics/dri
  __EGL_VENDOR_LIBRARY_DIRS: $SNAP/graphics/glvnd/egl_vendor.d
  # Other, generally useful environment settings...
  # XDG config
  XDG_CACHE_HOME:  $SNAP_USER_COMMON/.cache
  XDG_CONFIG_HOME: $SNAP_USER_DATA/.config
  XDG_CONFIG_DIRS: $SNAP/etc/xdg
  # XKB config
  XKB_CONFIG_ROOT: $SNAP/usr/share/X11/xkb
  

layout:
  # This is one of four snippets that relate to providing the userspace graphics needed by your application.
  # These paths (/usr/share/libdrm and /usr/share/drirc.d) are hardcoded in mesa.
  /usr/share/libdrm:  # Needed by mesa-core20 on AMD GPUs
    bind: $SNAP/graphics/libdrm
  /usr/share/drirc.d:  # Used by mesa-core20 for app specific workarounds
    bind: $SNAP/graphics/drirc.d
  # Other, generally useful paths
  /usr/share/fonts:
    bind: $SNAP/usr/share/fonts
  /usr/share/icons:
    bind: $SNAP/usr/share/icons
  /usr/share/sounds:
    bind: $SNAP/usr/share/sounds
  /etc/fonts:
    bind: $SNAP/etc/fonts


parts:
  qtwayland:
    source: https://download.qt.io/official_releases/qt/6.2/6.2.3/submodules/qtwayland-everywhere-src-6.2.3.tar.xz
    plugin: cmake
    build-packages:
      - libvulkan-dev
      - libwayland-dev
      - libxkbcommon-dev
      - qt6-base-dev
      - qt6-base-private-dev
      - qt6-declarative-private-dev
    stage-packages:
      - libwayland-cursor0
      - libwayland-egl1

  app:
    plugin: cmake
    source: /root/project/desktop_rexroth
    source-type: local
    build-packages:
      - git
      - libglu1-mesa-dev
      - libqt6opengl6-dev
      - qt6-declarative-dev
    stage-packages:
      #- qt6-base-dev         # added for QtWidgets
      - libqt6svg6-dev       # added for QtWidgets
      #- qt6-base-private-dev # added for QtWidgets
      - qml6-module-qt-labs-settings
      - qml6-module-qtqml-workerscript
      - qml6-module-qtquick  
      - qml6-module-qtquick-controls
      - qml6-module-qtquick-layouts
      - qml6-module-qtquick-templates
      - qml6-module-qtquick-window
    
  wayland-launch:
    plugin: dump
    source: wayland-launch
    override-build: |
      # The plugs needed to run Wayland. (wayland-launch checks them, setup.sh connects them)
      # You may add further plugs here if you want these options
      PLUGS="opengl wayland graphics-core20"
      sed --in-place "s/%PLUGS%/$PLUGS/g" $SNAPCRAFT_PART_BUILD/bin/wayland-launch
      sed --in-place "s/%PLUGS%/$PLUGS/g" $SNAPCRAFT_PART_BUILD/bin/setup.sh
      snapcraftctl build
    stage-packages:
      - inotify-tools

  resources:
    plugin: dump
    source: resources
    organize: 
      'fonts/*' : 'usr/share/fonts/'

  # This is one of four snippets that relate to providing the userspace graphics needed by your application.
  # This ensures that your snap doesn't contain its own copy of the userspace drivers
  cleanup:
    after:
      - app
      - wayland-launch
    plugin: nil
    build-snaps: [ mesa-core20 ]
    override-prime: |
      set -eux
      cd /snap/mesa-core20/current/egl/lib
      find . -type f,l -exec rm -f $SNAPCRAFT_PRIME/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/{} \;
      rm -fr "$SNAPCRAFT_PRIME/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/dri"
      for CRUFT in bug drirc.d glvnd libdrm lintian man; do
        rm -rf "$SNAPCRAFT_PRIME/usr/share/$CRUFT"
      done
      for CRUFT in apport doc doc-base fonts pkgconfig xml ; do
        rm -rf "$SNAPCRAFT_PRIME/usr/share/$CRUFT"
      done

architectures:
  - build-on: amd64

 

Step 5 : Build a snap (using multipass)

  • Before jumping on to build the snaps, we need some scripts to run after installing our application to configure wayland plugs and slots properly to run the snap on our Core X7. You can direcly download zip file from the attachments here at the end of the page or follow these steps :
    • Download the zip file
    •  Extract the zip file and copy "wayland-launch" directory
    • Copy "wayland-launch" directory to "build-your-project-name....-Debug"
      Copied folder "wayland-launch" in project folder
  • Now lets build the snap
    • Open terminal > go to your "build-....-Debug" directory and fire command "sudo snapcraft"
      Build snap using terminal
    • As shown above in the image, make sure you have following sub directories before building the snap:
      • snap
      • wayland-launch
      • <your original project root directory>
  • After successful snapping of your application, you would see the terminal output as in the image below and a snap package "<your-project-name>_0.1_amd64.snap" being "<your-project-name>" replaced with whatever name you chose in your snapcraft YAML file. Here in our case you would see a file with name "desktop-rexroth-qt_0.1_amd64.snap"

Step 6 : Install the dependencies (Ubuntu Frame , mesa )

  • Okay, now its time to install the dependencies which would be critical to provide a base for our custom "desktop-rexroth" application
  • mesa-core20
    • A content snap providing the mesa userspace libraries and drivers for core20. This supplies the graphics-core20 content interface required by Ubuntu frame to display our application on the screen. More details at: Click here 

    • It is recommended to download the snap directly from the snap store
      snap download mesa-core20​
      Download "mesa-core20" snap from snapstore
    • You can also directly download it from the attachments at the end of the page.
    • Install the snap in your Core X7
      Install "mesa-core20" in ctrlX OS
  • Ubuntu Frame
    • It is the base or the foundation for many embedded graphical display implementations. It is a simple fullscreen shell (based on Wayland) used for kiosks, industrial displays, digital signage, smart mirrors, etc. Using Ubuntu Frame, our example application we developed here gets a fullscreen window (or windows) and input from touch, keyboard and mouse without needing to deal with the specific hardware. More details can found be - here

    • Download directly from the snap store
      snap download ubuntu-frame --channel=20/stable​
      Download "ubuntu-frame" snap from snapstore
    • Or you can also find it from the attachments
    • Install the snap in your Core X7
      Install "ubuntu-frame" in ctrlX OS

Step 7 : Install our snapped application

  • Finally, its time to test our application on our ctrlX Core X7
  • Connect the display port on the Core X7 to the monitor or any screen. If you see the black background in your screen lit up that means Ubuntu Frame is working.
  • Install the app the same way we did as for other dependencies  
    Select our custom built snap to install
    Install our custom built snap

After installing, "desktop-rexroth-qt_0.1_amd64.snap" snap package you would see a koisk-type GUI (Graphical User Interface) / HMI on the screen displaying directly through the Display Port present on the Core X7. It is even more interesting that you do not have to install any additional drivers for keyboard or mouse inputs. You can connect keyboard or mouse directly through the XF01C USB port.

Result

Here is the final output on the screen connected via Display Port without using any web interface

HMI Output on a monitor connected via HDMI port in ctrlX Core X7

Related Links

3
snapcraft.txt
4.94KB

Latest published/updated articles

Types
Example
Categories
HMI
Attachments
Project