Skip to content

Tutorial and example on how to create a Kotlin Desktop Compose app running on Raspberry Pi 5 in kiosk mode.

License

Notifications You must be signed in to change notification settings

SergeySn/PiKiosk

Repository files navigation

PiKiosk

Tutorial and example on how to create a Kotlin Desktop Compose app running on Raspberry Pi 5 in kiosk mode.

To create the jar file from scratch, open Intellij IDEA and click on the New_Project button. Choose Compose Desktop as a project type. It would create the Hello World app automatically. To create a fat jar file, click on the gradle button on the right side of IDE to open the Gradle panel. Expand on Tasks/compose_desktop/ scroll down and right-click on "packageUberJarForCurrentOS" and select Run. This will produce the "build/compose/jars/PiKiosk-linux-x64-1.0.0.jar" file.

You can build the project on RPi from sources with this command:

./gradlew build

But before running a Compose app on RPi, run this command first:

export MESA_EXTENSION_OVERRIDE="-GL_ARB_invalidate_subdata"

Otherwise you'll get an error. For explanation see: https://www.reddit.com/r/Kotlin/comments/1c5jikl/how_do_i_get_compose_working_on_my_raspberry_pi/

Then run it with:

./gradlew run

You can build fat jar on RPi with:

./gradlew packageUberJarForCurrentOS

OS Installation

  • Use Raspberry Pi Imager to flash Raspberry Pi OS 64-bit to a microSD card
    • Click the ⚙️ icon for Advanced Options
      • Check Enable SSH
        • Select Use password authentication

          OR

        • Select Allow public-key authentication only (more secure)

          • Set authorized_keys for '<username>'
      • Check Set username and password
        • Enter Username and Password in the respective fields
      • Check Configure Wireless LAN
        • Enter SSID and Password for your Wi-Fi network
        • Select Wireless LAN Country
      • Check Set locale settings
        • Select Time zone and Keyboard layout
      • Click Save
    • Select RASPBERRY PI OS(64-BIT) as Operating System
    • Click CHOOSE STORAGE and select the microSD card
    • Click WRITE

If you need to change any of these settings later, run sudo raspi-config in a terminal on the Pi 5.

Hardware Setup

  • Connect the following h/w with the Pi 5
    • a monitor/screen
    • a keyboard
    • and a mouse
  • Insert the microSD card into the Pi 5
  • Connect Pi 5 to the power supply

Pi 5 will boot up and show the desktop environment.

Setup Cage

ssh into the Pi 5 with the username and password you set during the OS installation.

ssh <username>@<hostname/IP>

Follow the steps below to install cage on Pi 5.

  1. Make sure our OS is up-to-date

    sudo apt-get update && sudo apt-get -y upgrade
  2. Install dependencies for cage:

    sudo apt-get -y install cmake libvulkan-dev libwlroots-dev
    Optional: Building man pages Append `scdoc` to above command if you need cage man pages.
    Notes Without the dependencies, `meson setup build` will fail with the following error message(s)/warning(s):
     Found CMake: NO
     Run-time dependency wlroots found: NO (tried pkgconfig and cmake)
     Build-time dependency scdoc found: NO (tried pkgconfig and cmake)
    
  3. Build and install cage

    # our workspace
    mkdir ~/devel && cd ~/devel
    
    # master branch of cage requires a higher version of libwlroots-dev
    # whereas Debian bookworm has an older version(v0.1.4). We build v0.1.5
    # here, which is the latest release at the time this writing
    git clone https://github.com/cage-kiosk/cage.git -b v0.1.5
    cd cage
    
    # Configure
    meson setup build --buildtype=release -Dxwayland=true -Dprefix=/usr
    
    # Build
    ninja -C build
    
    # Install
    sudo ninja -C build install
  4. Clone this repository

    cd ~/devel
    git clone https://github.com/SergeySn/PiKiosk.git
    cd PiKiosk
  5. Start cage on boot

    1. Install the systemd unit file for cage from this repository to the system.

      The systemd unit file template is set up to run galculator by default as it is available in stock Pi OS.

      sudo cp files/cage-template.service /etc/systemd/system/[email protected]
      Notes This is the same template as in the cage wiki

      The only difference is that the following line

      ExecStart=/usr/bin/cage /usr/bin/gtk3-widget-factory

      has been replaced with

      ExecStart=/usr/bin/cage /usr/bin/galculator
    2. Add cage user. This is required by [email protected]

      sudo useradd -m cage

      Set a password for cage user

      sudo passwd cage
    3. Disable the default display manager(lightdm)

      sudo systemctl disable display-manager
    4. Enable an instantiated service of cage

      sudo ln -s /etc/systemd/system/[email protected] \
          /etc/systemd/system/graphical.target.wants/[email protected]
    5. Change systemd's default target to the graphical target

      sudo systemctl set-default graphical.target
    6. PAM configuration

      Copy the PAM configuration file for cage

      sudo cp files/cage-pam-cfg /etc/pam.d/cage
      Notes This is the same PAM config as in thecage wiki
  6. Reboot the Pi 5

    sudo reboot

After reboot, cage will start the galculator app in kiosk mode.

Run the sample Compose app with Cage

  1. SSH into Pi again

    ssh <user>@<hostname/IP>
  2. Install JRE, required to run compose app

    sudo apt-get update && sudo apt-get -y install default-jre
  3. Optional: Force a specific resolution in Compose app

    As of https://github.com/SergeySn/PiKiosk/commit/d4b8842c9770020d417a28ebe111b171a65eb67c, the Compose app is forced to use 1920x1080 resolution. To force a different resolution replace WindowSize(1920.dp, 1080.dp) in Main.kt with the desired values for width and height.

  4. Build the sample app

    cd ~/devel/PiKiosk
    ./gradlew packageUberJarForCurrentOS

    This will produce a JAR file at ${HOME}/devel/PiKiosk/build/compose/jars/PiKiosk-linux-arm64-1.0.0.jar.

    As this .jar is supposed to be accessible by the cage user, copy it to /home/cage.

    sudo cp \
    ${HOME}/devel/PiKiosk/build/compose/jars/PiKiosk-linux-arm64-1.0.0.jar \
    /home/cage/
    sudo chown cage:cage /home/cage/PiKiosk-linux-arm64-1.0.0.jar
  5. Update cage's systemd unit file (/etc/systemd/system/[email protected]) to run your compose app instead of galculator

    #JAR=</path/to/jar>
    # replcae </path/to/jar> with actual path of the JAR file that you want to
    # run with cage
    #. e.g. if you want to run the JAR file created in the
    # previous step do:
    JAR=/home/cage/PiKiosk-linux-arm64-1.0.0.jar
    
    sudo sed -i -e \
      "s@^ExecStart=.*@ExecStart=/usr/bin/cage -- java -jar ${JAR}@" \
      /etc/systemd/system/[email protected]
  6. Workaround JetBrains/skiko#649

    sudo sed -i -e \
    's@^#Environment=.*@Environment="MESA_EXTENSION_OVERRIDE=-GL_ARB_invalidate_subdata"@' \
    /etc/systemd/system/[email protected]

    Please see the discussion here for more info.

  7. Restart cage service for the changes to take effect

    # Required when /etc/systemd/system/[email protected] is updated.
    sudo systemctl daemon-reload
    
    # Required when /etc/systemd/system/[email protected] or .jar is updated.
    sudo systemctl restart [email protected]
  8. Optional: Force cage to use a specific resolution

    # Replace 1920x1080@60 with desired <width>x<height>x<refresh-rate>.
    # For the app to appear fullscreen, make sure to use the same values as in
    # step 3.
    # Also replace HDMI-A-2 with the output <name> of your display. You can list
    # the displays using the `wlr-randr` command.
    JAR=/home/cage/PiKiosk-linux-arm64-1.0.0.jar
    WLR_RANDR_CMD="wlr-randr --output HDMI-A-2 --mode 1920x1080@60"
    
    sudo sed -i -e \
    "s|^ExecStart=.*|ExecStart=/usr/bin/cage -- sh -c '${WLR_RANDR_CMD} \&\& java -jar ${JAR}'|" \
    /etc/systemd/system/[email protected]
    
    sudo systemctl daemon-reload && sudo systemctl restart cage@tty1
    # To experiment with different output modes of your display, you need to
    # login as cage user
    su cage
    export XDG_RUNTIME_DIR=/run/user/${UID}
    wlr-randr # display available outputs and modes
    wlr-randr --output HDMI-A-2 --mode 1920x1080@60 # select desired output/mode

    ⚠️ wlr-randr only works when cage is running.

Extras

The following steps are optional and are for hardening the kiosk setup.

  1. Disable splash screen

    sudo raspi-config
    • Select System Options
    • Select Splash Screen
    • Select No
    • Select Ok
    • Select Finish
  2. Append fbcon=map:1 to /boot/firmware/cmdline.txt

    tells fbcon not to take over the console. This takes care of the messages that appear when the splash screen is disabled. See: https://www.kernel.org/doc/Documentation/fb/fbcon.txt

  3. Alternatively, you can replace the splash screen image by replacing file:

    /usr/share/plymouth/themes/pix/splash.png

    with your own image. And then running

    sudo plymouth-set-default-theme --rebuild-initrd pix

    command to persist it.

About

Tutorial and example on how to create a Kotlin Desktop Compose app running on Raspberry Pi 5 in kiosk mode.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages