The Yocto Project enables the creation of custom Linux-based systems for embedded devices.

The TeamViewer Embedded Agent will run on Yocto Linux devices given minimum requirements and configurations are met.

This article is an example of how to build Yocto Image with TeamViewer Embedded Agent for Raspberry using the layer provided in GitHub.

For more information, please visit: https://github.com/teamviewer/meta-teamviewer-iot-agent

📌Note: When using ssh with the built image, the username is root and the password is raspberry.

Requirements

Make sure that you have prepared the following points:

  • The edge device is set up with a TeamViewer Embedded Agent.
  • The edge device is connected to the internet.
  • Your PC is set up with the TeamViewer Client.
  • Your login credentials for the edge device (user name, and password).
  • Installed dependencies (based on the operating system of Raspberry). Please install the following packages on the system: build-essential
    • lz4
    • git
    • texinfo
    • python3-distutils
    • libncurses5-dev
    • gawk
    • diffstat
    • chrpath

📌Note: On Ubuntu, you can install these packages with the following command:

:~$ sudo apt-get install build-essential chrpath diffstat gawk libncurses5-dev python3-distutils texinfo git lz4

Setup

1. On your PC open the TeamViewer Client and log in.

2. On the left side open the Computers & Contacts tab.

3. Double-click the device.

  • The Control Window opens and the connection will be established.

4. In the Control Window on the top, open the Remote Terminal tab.

5. Type in your user password and press Enter.

6. To get the Yocto build environment, first git clone the latest Yocto and checkout a specific branch. It is generally not recommended to use main/master.

:~$ git clone -b kirkstone git://git.yoctoproject.org/poky.git kirkstone

This will download the latest kirstone branch from Yocto in the folder kirkstone.

7. Go to the kirkstone folder and clone the following repos to install the packages necessary to build an OS for Raspberry Pi with a desktop and with all the dependencies for the TeamViewer Agent:

  • meta-openembedded - This is needed for having a desktop, network and other basic OS components on the device.
  • meta-raspberrypi - This is needed for Raspberry Pi specific software and configuration, like the proprietary boot loader.
  • meta-qt - This is needed for having QT on the device. This one is optional.
  • meta-security

This can be done using the following commands:

~$ cd kirkstone
~/kirkstone$ git clone -b kirkstone git://git.openembedded.org/meta-openembedded
~/kirkstone$ git clone -b kirkstone https://github.com/meta-qt5/meta-qt5
~/kirkstone$ git clone -b kirkstone git://git.yoctoproject.org/meta-raspberrypi
~/kirkstone$ git clone -b kirkstone git://git.yoctoproject.org/meta-security.git

8. Make sure that all the branches match the one for the Yocto Project. If this is not the case, please make sure that the meta layers are compatible with the Yocto Project branch by checking the variable LAYERSERIES_COMPAT_${PN} found in the conf/layer.conf file. The ${PN} is the package name.

# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
 
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
        ${LAYERDIR}/recipes-*/*/*.bbappend"
 
BBFILE_COLLECTIONS += "filesystems-layer"
BBFILE_PATTERN_filesystems-layer = "^${LAYERDIR}/"
BBFILE_PRIORITY_filesystems-layer = "6"
 
# This should only be incremented on significant changes that will
# cause compatibility issues with other layers
LAYERVERSION_filesystems-layer = "1"
 
LAYERDEPENDS_filesystems-layer = "core openembedded-layer"
 
LAYERSERIES_COMPAT_filesystems-layer = "kirkstone"

If the LAYERSERIES_COMPAT_${PN} is missing, this means there are no hard compatibility dependencies.

The TeamViewer Embedded Agent Yocto recipe

A typical Yocto recipe has the following folder structure:

image.png

The important files are the layer.conf and the teamviewer-iot-agent.bb. The *.bb file is the bitbake recipe that contains the instructions necessary for the Yocto Project to build and incorporate the TeamViewer agent into the operating system.

layer.conf

# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
 
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
            ${LAYERDIR}/recipes-*/*/*.bbappend"
 
BBFILE_COLLECTIONS += "teamviewer-iot-agent"
BBFILE_PATTERN_teamviewer-iot-agent = "^${LAYERDIR}/"
BBFILE_PRIORITY_teamviewer-iot-agent = "6"
 
LAYERDEPENDS_teamviewer-iot-agent = "core"
LAYERSERIES_COMPAT_teamviewer-iot-agent = "kirkstone"

teamviewer-iot-agent.bb

SUMMARY = "TeamViewer Embedded Agent provides easy, fast and secure remote access to your device."
DESCRIPTION = "The TeamViewer Embedded agent provides an out-of-the-box \
secure remote access and monitoring solution for your IoT environment \
and connected devices. . The agent seamlessly integrates with the \
latest TeamViewer client, which enables you to remotely access your \
device & remotely view live monitoring data. The Teamviewer Client can \
be downloaded at http://www.teamviewer.com/. . TeamViewer Embedded Agent is \
currently available for free trial. As licensing may be subject to \
change, please visit https://teamviewer-iot.com. . Notes . Use of the \
TeamViewer Embedded Agent must adhere to the end user license agreement. \
Reference http://www.teamviewer.com/link/?url=653670 . TeamViewer Embedded \
Agent contains Free Software components. Reference \
/usr/share/doc/teamviewer-iot-agent/Third_Party_License.txt"
HOMEPAGE = "http://www.teamviewer.com"
 
SECTION = "non-free/misc" LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://../LICENSE;md5=42d92b6e835edaca7b91d7007b64e737"
SRC_URI += "file://LICENSE;md5=42d92b6e835edaca7b91d7007b64e737"  RDEPENDS:${PN} += "${@bb.utils.contains('DISTRO_FEATURES', 'X11', ' xserver-xorg-xvfb xserver-xorg xkeyboard-config xauth', '', d)}"
RDEPENDS:${PN} += "bash perl glibc glibc-utils procps curl ca-certificates"
RRECOMMENDS:${PN} += "dbus libavahi-core libavahi-common libavahi-client"
 
TEAMVIEWER_IOT_AGENT_VERSION="3.0.3"
 
SRC_URI += "https://download-iot.teamviewer.com/agents/linux/${TEAMVIEWER_IOT_AGENT_VERSION}/armv7/teamviewer-iot-agent-armv7_${TEAMVIEWER_IOT_AGENT_VERSION}_armhf.deb"
SRC_URI[md5sum] = "d6a958aa7acc451eb4872eaf01600cce"
SRC_URI[sha1sum] = "cff3842ffb2b26fe873e86227ce6ae70e7dbca68"
SRC_URI[sha256sum] = "e39aff3580b4d528dec10bbe5052cefa7de31e797b607017092e615ba3de8b35"
SRC_URI[sha384sum] = "81e114ad448b9553e8c79ab17a09dcd36852f0be5efca77dc655b9eba215895f86fe644d5b0565d080d09233d04aac0d"
SRC_URI[sha512sum] = "0780438803c63938a2dac247dab205d4954b2e87a3b6949df89ca721dedc2da02502335c96d82c2eaa6a244c0c0a6297471ca69bbd504876cd2c68308329f5a0"  do_configure () {
    # Specify any needed configure commands here
    :
}
 
do_compile () {
    # Specify compilation commands here
    :
}
 
do_install () {
    #TeamViewer IoT Agent
    cp -r ${WORKDIR}/etc ${D}/etc
    cp -r ${WORKDIR}/lib ${D}/lib
    cp -r ${WORKDIR}/usr ${D}/usr
    cp -r ${WORKDIR}/var ${D}/var
    cp -r ${WORKDIR}/usr/share/doc ${D}/usr/share/teamviewer-iot-agent-layer-docs
 
    #Installation scripts
    ar x ${DL_DIR}/teamviewer-iot-agent-armv7_${TEAMVIEWER_IOT_AGENT_VERSION}_armhf.deb  
    tar xf control.tar.gz --no-same-owner
    install -m 0700 preinst ${D}/usr/share/teamviewer-iot-agent/
    install -m 0700 postinst ${D}/usr/share/teamviewer-iot-agent/
    install -d ${D}/var/log/teamviewer-iot-agent/
    install -d ${D}/etc/default/
}
 
pkg_postinst_ontarget:${PN} () {
    mkdir -p /usr/share/doc /var/log/teamviewer-iot-agent
    mv /usr/share/teamviewer-iot-agent-layer-docs/* /usr/share/doc/
    /usr/share/teamviewer-iot-agent/preinst
    /usr/share/teamviewer-iot-agent/postinst
    rm -f /usr/share/teamviewer-iot-agent/preinst
    rm -f /usr/share/teamviewer-iot-agent-layer-docs
}
 
FILES:${PN} += "/etc/* \
        /var/* \
        /lib/* \
        /usr/*"
 
INSANE_SKIP:${PN} += "already-stripped ldflags"

The SRC_URI variable tells the Yocto build system where to download the package from and it gives it the hash and checksum of the package to validate it.

The RDEPENDS variable tells the Yocto build system which software packages are a hard requirement for this package to work. The Yocto build system will try to find these software packages in all of its layers and report an error if none can be found that provide these software packages.

The RRECOMMENDS variable tells the Yocto build system which software packages are a soft requirement for this package. The Yocto build system will try to provide them, but will not generate an error if no meta layer provides them.

The do_install() function will be executed to install the software package in the deployment folder. This script will be executed on the build host system.

The pkg_postinst_ontarget will be used by the Yocto build system to generate a bash script that will be executed on the target system after the first boot. The script will be located in the /etc/deb-postinsts folder and will be deleted after the first boot.

The FILES variable tells the Yocto build system which files to copy from the software package to the deployment folder.

The INSANE_SKIP variable tells the Yocto build system which errors to ignore for this software package.

How to build it all and test it

To create the workspace for building the OS:

1. Source the oe-init-build-env script.

~/kirkstone$ source oe-init-build-env build
You had no conf/local.conf file. This configuration file has therefore been
created for you from /home/adrian/kirkstone/meta-poky/conf/local.conf.sample
You may wish to edit it to, for example, select a different MACHINE (target
hardware). See conf/local.conf for more information as common configuration
options are commented.
 
You had no conf/bblayers.conf file. This configuration file has therefore been
created for you from /home/adrian/kirkstone/meta-poky/conf/bblayers.conf.sample
To add additional metadata layers into your configuration please add entries
to conf/bblayers.conf.
 
The Yocto Project has extensive documentation about OE including a reference
manual which can be found at:
    https://docs.yoctoproject.org
 
For more information about OpenEmbedded see the website:
    https://www.openembedded.org/
 
 
### Shell environment set up for builds. ###
 
You can now run 'bitbake <target>'
 
Common targets are:
    core-image-minimal
    core-image-full-cmdline
    core-image-sato
    core-image-weston
    meta-toolchain
    meta-ide-support
 
You can also run generated qemu images with a command like 'runqemu qemux86'
 
Other commonly useful commands are:
 - 'devtool' and 'recipetool' handle common recipe tasks
 - 'bitbake-layers' handles common layer tasks
 - 'oe-pkgdata-util' handles common target package tasks

This command will setup the build environment and create the folder build.

2. Add all of the meta layers to the build system.

~/kirkstone$ cd build
~/kirkstone/build$ bitbake-layers add-layer ../meta-openembedded/meta-oe \
        ../meta-openembedded/meta-filesystems/ \
        ../meta-openembedded/meta-gnome/ \
        ../meta-openembedded/meta-initramfs/ \
        ../meta-openembedded/meta-multimedia/ \
        ../meta-openembedded/meta-networking/ \
        ../meta-openembedded/meta-perl/ \
        ../meta-openembedded/meta-python/ \
        ../meta-openembedded/meta-webserver/ \
        ../meta-openembedded/meta-xfce/ \
        ../meta-teamviewer-iot-agent \
        ../meta-raspberrypi \
        ../meta-qt5 \
        ../meta-security

3. Configure the build system to build the correct type of OS with the OS features and software packages the user needs.

#MACHINE ?= "beaglebone-yocto"
#MACHINE ?= "genericx86"
#MACHINE ?= "genericx86-64"
#MACHINE ?= "edgerouter"
#
# This sets the default machine to be qemux86-64 if no other machine is selected:
MACHINE ??= "raspberrypi3"
# For building a Raspberry pi
DISTRO_FEATURES:append = " security"
 
IMAGE_INSTALL:append = " openssh-sftp-server sudo python3 python3-pip rpi-gpio raspi-gpio"
 
IMAGE_FEATURES:append = " ssh-server-openssh"
 
IMAGE_FSTYPES = "wic.bz2 rpi-sdimg"
 
LICENSE_FLAGS_ACCEPTED = "commercial"
 
# For TeamViewer Embedded Agent
DISTRO_FEATURES:append = " X11"
 
IMAGE_INSTALL:append = " teamviewer-iot-agent"
 
IMAGE_ROOTFS_EXTRA_SPACE = "256000"
 
VOLATILE_LOG_DIR = "no"

The variable IMAGE_FSTYPES tells the Yocto build system what type of file system image to generate and can take many different values. These can be specified with a space between them. Some of the supported file system types are:

  • rpi-sdimg
  • wic.bz
  • tar, tar.gz, tar.bz2, tar.xz, tar.lz3
  • ext2, ext2.gz, ext2.bz, ext2.lzma
  • ext3, ext3.gz
  • jffs2, jffs2.sum
  • iso
  • hddimg
  • squashfs, squashfs-xz
  • ubi, ubifs

For a more comprehensive list of supported file system types, please check the Yocto documentation.

4. To start the build process, please call the bitbake command with the image name.

:~/kirkstone/build$ bitbake core-image-minimal-xfce

The resulting image will be located under kirkstone/build/tmp/deploy/images/raspberrypi3 and follows this naming convention image_type-arch.fstype

-rw-r--r-- 2 adrian adrian     7807 Nov 17 16:03 core-image-minimal-xfce.env
-rw-r--r-- 2 adrian adrian 746586112 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64-20221117150143.rootfs.ext3
-rw-r--r-- 2 adrian adrian   153011 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64-20221117150143.rootfs.manifest
-rw-r--r-- 2 adrian adrian 801112064 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64-20221117150143.rootfs.rpi-sdimg
-rw-r--r-- 2 adrian adrian 144049131 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64-20221117150143.rootfs.wic.bz2
-rw-r--r-- 2 adrian adrian   421745 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64-20221117150143.testdata.json
lrwxrwxrwx 2 adrian adrian       66 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64.ext3 -> core-image-minimal-xfce-raspberrypi3-64-20221117150143.rootfs.ext3
lrwxrwxrwx 2 adrian adrian       70 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64.manifest -> core-image-minimal-xfce-raspberrypi3-64-20221117150143.rootfs.manifest
lrwxrwxrwx 2 adrian adrian       71 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64.rpi-sdimg -> core-image-minimal-xfce-raspberrypi3-64-20221117150143.rootfs.rpi-sdimg
lrwxrwxrwx 2 adrian adrian       68 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64.testdata.json -> core-image-minimal-xfce-raspberrypi3-64-20221117150143.testdata.json
lrwxrwxrwx 2 adrian adrian       69 Nov 17 16:03 core-image-minimal-xfce-raspberrypi3-64.wic.bz2 -> core-image-minimal-xfce-raspberrypi3-64-20221117150143.rootfs.wic.bz2

5. To flash the image to an SD Card, the user can use either the dd command or the bmaptool command based.

:~$ sudo dd if=kirkstone/build/tmp/deploy/images/raspberrypi3/core-image-minimal-xfce-raspberrypi3-64.rpi-sdimg of=/dev/sdc bs=4M status=progress
or
:~$ sudo bmaptool copy kirkstone/build/tmp/deploy/images/raspberrypi3-64/core-image-minimal-xfce-raspberrypi3.wic.bz2 /dev/sdc -nobmap

Please make sure to replace the sdc with the device name of the mounted SD Card.

6. To test the image just insert the SD card in a Raspberry Pi 3 and power it on. The core-image-minimal-xfce will have a desktop so attaching a monitor to it will help. The image has port 22 open and the login is root without password.

If you want to generate the SDK necessary to cross-compile any software for this specific device instead of the image, please also include the argument -c populate_sdk.

:~/kirkstone/build$ bitbake core-image-minimal-xfce -c populate_sdk

The SDK will be generate under kirkstone/build/tmp/deploy/sdk and has the following naming convention: poky-glibc-host_system-image_type-arch-toolchain-release_version.sh. For the Raspberry Pi 3 32 bits OS this SDK will be named poky-glibc-x86_64-core-image-minimal-xfce-cortexa53-raspberrypi3-toolchain-4.0.5.sh

How to keep the recipe up to date

There are two main things that need to be done in order to upgrade the recipe to a newer version of the Embedded agent:

  1. Increase the version number stored in the TEAMVIEWER_IOT_AGENT_VERSION variable at line 25 of the recipe to a newer version of the agent.
  2. Make sure the hashes of the debian package and the license files is up to date. The open ssl command line application can be used to generate these hashes.
:~$ wget https://download-iot.teamviewer.com/agents/linux/3.0.3/armv7/teamviewer-iot-agent-armv7_3.0.3_armhf.deb

The next thing is to generate the hashes from the downloaded package:

:~$ openssl md5 teamviewer-iot-agent-armv7_3.0.3_armhf.deb
MD5(teamviewer-iot-agent_3.0.5_arm64.deb)= d6a958aa7acc451eb4872eaf01600cce
:~$ openssl sha1 teamviewer-iot-agent-armv7_3.0.3_armhf.deb
SHA1(teamviewer-iot-agent_3.0.5_arm64.deb)= cff3842ffb2b26fe873e86227ce6ae70e7dbca68
:~$ openssl sha256 teamviewer-iot-agent-armv7_3.0.3_armhf.deb
SHA256(teamviewer-iot-agent_3.0.5_arm64.deb)= e39aff3580b4d528dec10bbe5052cefa7de31e797b607017092e615ba3de8b35
:~$ openssl sha384 teamviewer-iot-agent-armv7_3.0.3_armhf.deb
SHA384(teamviewer-iot-agent_3.0.5_arm64.deb)= 81e114ad448b9553e8c79ab17a09dcd36852f0be5efca77dc655b9eba215895f86fe644d5b0565d080d09233d04aac0d
:~$ openssl sha512 teamviewer-iot-agent-armv7_3.0.3_armhf.deb
SHA512(teamviewer-iot-agent_3.0.5_arm64.deb)= 0780438803c63938a2dac247dab205d4954b2e87a3b6949df89ca721dedc2da02502335c96d82c2eaa6a244c0c0a6297471ca69bbd504876cd2c68308329f5a0

If the license file or the copyright file has been changed, the md5 hash of the new files also have to be updated in the recipe file.

:~$ ar x teamviewer-iot-agent-armv7_3.0.3_armhf.deb
:~$ tar xf data.tar.gz
:~$ ls
control.tar.gz  data.tar.gz  debian-binary  etc  lib  teamviewer-iot-agent-armv7_3.0.3_armhf.deb  usr  var
:~$ openssl md5 usr/share/doc/teamviewer-iot-agent/copyright
MD5(usr/share/doc/teamviewer-iot-agent/copyright)= bba9e4971ef9b41df8f0113317b5e06b
:~$ openssl md5 usr/share/doc/teamviewer-iot-agent/Third_Party_License_IoT.txt
MD5(usr/share/doc/teamviewer-iot-agent/Third_Party_License_IoT.txt)= 7da68f03f4b43e808e993cbd25748688

Please keep in mind that different versions of Yocto have a different naming conventions for the variables. For example, older versions of Yocto use VARIABLE_NAME_${PN} and newer ones use VARIABLE_NAME:${PN}. Other naming conventions that may vary are "IMAGE_INSTALL:append =" vs "IMAGE_INSTALL +=".

Please check this document for the specific version of Yocto that you are using Variable glosary for Yocto 3.2.4