/hyelicht

IoT/embedded project for home decoration/automation

Primary LanguageC++GNU General Public License v2.0GPL-2.0

Hyelicht

REUSE status Linux (Onboard) Android (Client) Documentation

Hyelicht is an IoT/embedded project for home decoration/automation. Its software allows you to do colorful painting and animations on a LED-backlit shelf, using an embedded touchscreen and a companion app for phones and PCs. It also offers integration with a smart lights system.

Hyelicht's reference hardware is a 5x5 IKEA Kallax shelf with multiple rows of LED backlighting and a side-mounted 7″ touchscreen integrated into an aesthetically-pleasing picture frame. A single-board computer running Linux, a helper MCU and two 12A 5V bench power supplies are hidden inside the shelf.

A photo of the assembled shelf can be found here.

Features

  • Responsive Touch GUI with support for landscape and portrait orientations
    • Turn shelf on/off, adjust brightness, painting tools, trigger animations
    • Runs synchronized on embedded touchscreen and multiple Android/PC devices
    • Runs in-process or standalone
  • SK9822/APA102 LED paint engine supporting gamma correction and HSV-based brightness derivation
  • Animation framework
    • Fireplace animation 🔥
  • Embedded display backlight control with MCU-generared PWM signal
    • Smooth display fade-in on user interaction, fade-out on idle timeout
  • HTTP REST API
  • CLI frontend utility hyelichtctl (HTTP-based), works locally and over the network
  • Home Assistant integration
  • systemd integration (service unit)
  • Doxygen-based documentation
  • REUSE- and SPDX-compliant free software written in C++17 and QML

Screenshots

Screenshot of onboard Touch GUI Screenshot of Touch GUI on Android phone

A photo of the assembled shelf can be found here.

Licensing

Most of Hyelicht is available under GNU GPL v2. All licenses used in the project:

  • GNU GPL v2.0, v3.0 or any later version approved by KDE e.V. (Most source code)
  • LGPL-3.0-or-later (Most icons)
  • CC-BY-4.0 (Most other graphical assets, metadata and documentation)
  • BSD 3-Clause "New" or "Revised" License
  • Creative Commons Zero v1.0 Universal

The codebase is REUSE- and SPDX-compliant. See files in LICENSES/ and .reuse/dep5.


Table of Contents


Documentation

Architecture

The full Hyelicht system contains the following elements:

System diagram

(See below for additional detail on wiring.)

Hyelicht has a main application codebase with multiple build+runtime modes for onboard (embedded with or without in-process Touch GUI) and standalone Touch GUI (client) use. A monolithic-by-default single-application architecture was chosen to minimize resource needs and loading times in onboard mode. Internally, the application heavily optimizes for each mode. For details on how to choose the mode, see the sections on build options and command line options.

In onboard mode, the application controls the LED strip and the display backlight (with the help of additional software on a companion MCU) and offers servers for instances running in Touch GUI mode as well as HTTP clients. In standalone Touch GUI mode, these features are disabled and the application acts as a pure client only.

Additionally, the onboard application can also be run in headless mode. This disables the in-process Touch GUI. An additional instance in Touch GUI mode can then be run as a pure client on the same device, if process separation is desired.

Included clients to the HTTP REST API include a command line frontend utility hyelichtctl and a Home Assistant integration.

Source code

Hyelicht's source code has full Doxygen-based documentation. You can browse a generated snapshot of the latest documentation here.

If you want to generate the documentation locally yourself, please check the build instructions.


Installation and using

Supported platforms

Hyelicht has a largely platform-agnostic codebase that should build and run on any platform providing its build dependencies. However, its custom LED paint engine makes use of a Linux-specific API for SPI communication.

Hyelicht is being tested on the following hardware and software:

  • Onboard mode:
    • Raspberry Pi 4B running Raspberry OS
    • Waveshare 7″ 1024x600 capacitive touchscreen, version H
  • Standalone Touch GUI mode:
    • Desktop PC: Fedora Linux
    • Android phone: Android+Qt+KDE SDK via the KDE Android Docker image and several Android 11/12 phones
  • LED strips: 416x SK9822, 60 LEDs/m
  • Helper MCU: Android Nano 3.0 (AVR ATmega328)

See section Architecture for an explanation of the modes.

LEDs

The reference hardware for the project uses SK9822 LEDs from 60 LED/m strip reels. However, the custom LED paint engine should also be compatible with APA102 LEDs. The SK9822 is a later clone of APA102 with minimal differences in the accepted input.

Helper MCU (PWM signal generator)

In onboard mode, the Hyelicht application uses serial communication to a helper MCU that drives the embedded display backlight with a PWM signal. The helper MCU is expected to read 8-bit integer values between 0 and 255 on serial and convert them to the corresponding signal. In principle, any MCU programmed to conform to this expectation will work.

The reference hardware used in the project is an Android Nano 3.0 (AVR ATmega328). See src/arduino_pwm_generator.cpp for the reference program.

Dependencies

General build dependencies

  • C++17-supporting C++ compiler
  • CMake v3.16+
  • Qt v5.15+ modules QtCore, QtNetwork, QtQML, QtQuick, QtRemoteObjects
  • KDE Frameworks 5 v5.78+ modules Extra CMake Modules/ECM, KCoreAddons, KConfig, KI18n from
  • Linux headers (for SPI)

Optional build dependencies

  • For onboard builds:
    • Qt v5.15+ module QtSerialPort
    • QHttpEngine v1.0.1+
  • For Android builds:
    • Qt v5.15+ module QtAndroidExtras
    • Android v30+ SDK+NDK (see below)
  • For documentation builds:
    • Doxygen v1.8.8+
    • Doxyqml

A convenient way to access a complete Android+Qt+KDE SDK is via the KDE Android Docker image.

Optional runtime dependencies

  • Raspberry OS: SPI enabled
  • For clang-tidy developer build configuration: clang-tidy

Build dependencies for included helper MCU program

Build instructions

Hyelicht has a CMake-based build system. Here are some general build commands:

(Hyelicht codebase is in directory `hyelicht`.)
$ cd hyelicht/
$ mkdir build && cd build/
$ cmake ../build -DCMAKE_INSTALL_PREFIX=<install path>
$ make
$ sudo make install

When running the cmake command, you may want to pass additional build options, like so:

$ cmake ../build -DSOME_OPTION=value

See below for available build options and their default values.

Android

Building for Android is easy using the KDE Android Docker image.

See the support/kde_android_docker_build.sh build script and its embedded comments for specific instructions.

Doxygen

To generate source code documentation using Doxygen during a build, enable the BUILD_DOCS build option.

Build options

See the build instructions for how to set these options when building Hyelicht.

User options

Option Default Description
BUILD_ONBOARD TRUE unless Android build When enabled, additional features and command line options become available that only make sense when Hyelicht is running in onboard mode on the hardware embedded into the shelf. For example, code driving the LEDs and the embedded display backlight, and servers for the Touch GUI and HTTP clients. This alters the list of build dependencies.
BUILD_CLI TRUE unless Android build Builds the HTTP-based hyelichtctl command line utility.

Developer options

Option Default Description
BUILD_DOCS FALSE Generates project documentation using Doxygen. This alters the list of build dependencies. The generated documentation will appear inside the docs/html/ sub-directory of the build directory.
CLANG_TIDY FALSE Reformats the source code using clang-tidy.
COMPILE_QML TRUE Pre-compiles QML source files for faster loading speeds.
DEBUG_QML FALSE Enables the QML debug server.

Deployment

systemd service unit

In the onboard build configuration, Hyelicht installs a systemd service unit. It is recommended to use it as a user unit, like so:

$ systemctl --user enable hyelicht

If you just installed Hyelicht, you may need to run systemctl --user daemon-reload first. For user units to start at boot, you may need to enable lingering (see enable-linger) for the user.

The service unit starts the application in onboard mode and sets several environment variables specific to the project's embedded reference hardware. It instructs Qt to select the EGLFS backend plugin, which handles GPU interaction for the Touch GUI. Other variables set the screen resolution for the embedded touchscreen. See the Qt for Embedded Linux page for additional information.

Home Assistant integration

Plugin code for simple integration with Home Assistant is provided at support/homeassistant/hyelicht.

Copy the hyelicht folder into <Your Home Assistant config dir>/custom_components (create the folder custom_components if necessary), then add the integration from your Home Assistant settings menu. You will be prompted for the host address and port of the Hyelicht shelf.

The integration plugin acts as a client to the HTTP REST API.

Wiring

The LEDs are connected to the Raspberry Pi 4B and the bench PSUs (part of the reference hardware used by the project) as follows:

Wiring diagram for Raspberry Pi and LEDS

In the actual shelf, there are two 12A 5V bench PSUs to power 416 LEDs (50 mA each at full brightness). Both PSUs are connected to both ends (5V and GND) of two LED strips each, with each LED strip having 104 LEDs. Connecting to both ends potentially improves signal integrity (GND) and avoids a one-sided brownout if (5V), should your PSUs be too weak (instead, the brownout would occur in the middle of the strips). All grounds are connected, including the Raspberry Pi's, to ground the SPI connection.

The Raspberry Pi, and the helper MCU and the embedded touchscreen connected to it, is seperately powered via the official Raspberry Pi USB-C power supply. The inputs and outputs of all three PSUs are connected on a single wall power plug.

See also the system diagram.

Running

The main application executable is named hyelicht. It can be run manually:

$ hyelicht

Or via the included systemd service unit, which conveniently sets command line options and environment variables suitable for an embedded deployment. Check the linked section for detailed information.

If you want to try out Hyelicht's embedded GUI on your PC without having LEDs handy, run a default build like this:

$ hyelicht --onboard --simulate-shelf --simulate-display

The hyelichtctl command line utility is described below.

Command line options

hyelicht supports standard command options options such as -h, --help.

Various command line options will override an equivalent setting that can be changed via the config file.

Command line options unique to hyelicht:

Option Default Description
-r, --remotingApiServerAddress from Settings Overrides the address Touch GUI client instances contact the remoting API server on. If unset, the listen address is taken from the settings (see the section Config file).

Additional command line options for onboard build configuration

Option Default Description
-o, --onboard UNSET Runs the application in onboard mode. This is used by the systemd service unit.
--headless UNSET Disables the in-process Touch GUI. Useful if running the GUI out-of-process as a standalone client instance is desired.
--simulateDisplay UNSET Disables serial communication to the helper MCU and simulates display backlight status in the Touch GUI.
--simulateShelf UNSET Disables SPI communication with the LED strip. The Touch GUI and all APIs can be used regardless.
-s, --httpListenAddress from Settings Overrides the listen address for the HTTP REST API server. If unset, the listen address is taken from the settings (see the section Config file).
-p, --httpListenPort from Settings Overrides the port the HTTP REST API server listens on. If unset, the listen address is taken from the settings (see the section Config file).
--disableHttpApi from Settings If set, disables the HTTP REST API server. If unset, whether to enable this API server is taken from the settings (see the section Config file).
-l, --remotingApiListenAddress from Settings Overrides the listen address for the remoting API server used by Touch GUI client instances. If unset, the listen address is taken from the settings (see the section Config file).
--disableRemotingApi from Settings If set, disables the remoting API server. If unset, whether to enable this API server is taken from the settings (see the section Config file).

Config file

Hyelicht supports a config file in INI-style format. It should be located at $XDG_CONFIG_HOME/hyelichtrc or in an equivalent system or user location following the XDG Base Directory specification.

See the XML source file src/settings/hyelicht.kcfg for the INI group and key names and the description and default value of each setting. Those attempting to build their own shelf (something the authors hope you may do!) will are likely to take special interest in the various settings related to shelf size and server addresses.

Logging

Hyelicht's applications can output error and debug messages on stdout and stderr using Qt's categorized logging framework.

When you run hyelicht or hyelichtctl manually, you should enable its logging categories to see this output:

$ export QT_LOGGING_RULES=com.hyerimandeike.*=true
$ hyelicht

If the application is run via the included systemd service unit, the categories are enabled by default and messages can be looked up in the journal:

$ journalctl --user -u hyelicht.service

The complete list of logging categories:

Name Description
com.hyerimandeike.hyelicht General messages
com.hyerimandeike.hyelicht.Animations Animation framework
com.hyerimandeike.hyelicht.DisplayController Serial communication with helper MCU for display backlight control
com.hyerimandeike.hyelicht.HttpServer HTTP REST API server
com.hyerimandeike.hyelichtctl hyelichtctl command line utility
com.hyerimandeike.hyelicht.LedStrip SPI communication with LED strip and LED paint engine
com.hyerimandeike.hyelicht.Remoting Communication between onboard and standalone Touch GUI clients

HTTP REST API

In onboard mode, the main application offers a HTTP REST API (unless disabled via the Config file or command line option.) with the following available resources:

Resource Supported methods
v1/shelf GET
v1/shelf/enabled GET, PUT
v1/shelf/brightness GET, PUT
v1/shelf/averageColor GET, PUT
v1/shelf/animating GET, PUT
v1/squares GET, PUT
v1/square/:index/averageColor GET, PUT

Data is returned and accepted in JSON format.

See the system diagram to understand the numbering of squares for square indices.

The HTTP REST API is used by the included hyelichtctl command line frontend and the Home Assistant integration.


hyelichtctl CLI utility

The hyelichtctl command line utility can be used to check on and control various aspects of the shelf. It is a client to the HTTP REST API of the onboard application and can therefore run both locally and remotely, depending on the onboard configuration.

hyelichtctl is run like this:

$ hyelichtctl [options] command [args...]

Supported commands are:

Command Parameters Description
status none Returns shelf status, including enabled, brightness, average color, etc.
enabled [bool] Reads or sets enabled status of the shelf.
enable none Enables the shelf.
disable none Disables the shelf.
brightness [0.0 - 1.0] Reads or sets the shelf brightness.
color [square index] [color] Reads or sets the color of the shelf or a square.
animating [bool] Starts or stops the animation.

See the system diagram to understand the numbering of squares for square index.

A color can be a CSS color name or a RGB HEX color code.

Supported command line options are:

Option Default Description
-s, --server 127.0.0.1 The server address to contact the onboard application at.
-p, --port 8082 The port to contact the onboard application on.
-j, --json UNSET If set, the output is in JSON format instead of more easily-read INI-style.

Additionally, standard command line options such as -h, --help are supported as well.