{"id":36584,"date":"2022-05-31T14:36:28","date_gmt":"2022-05-31T12:36:28","guid":{"rendered":"https:\/\/www.inovex.de\/?p=36584"},"modified":"2022-11-14T12:36:12","modified_gmt":"2022-11-14T11:36:12","slug":"migrate-to-linux-with-yocto-and-flutter-in-embedded-devices","status":"publish","type":"post","link":"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/","title":{"rendered":"Migrate to Linux with Yocto and Flutter in Embedded Devices"},"content":{"rendered":"<p>In this blog article we show how we migrated our meeting room displays from Android Things to a solution combining Raspberry Pi, Yocto, Flutter and Mender.<!--more--><\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\"><\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Use-case-Managing-meeting-room-status\" >Use case: Managing meeting room status<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Raspberry-Pi-hardware\" >Raspberry Pi hardware<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Android-Things\" >Android Things<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Farewell-to-Android-Things-Hello-Raspberry-Pi-Flutter-Yocto\" >Farewell to Android Things: Hello Raspberry Pi, Flutter, Yocto<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Embedded-Linux-The-Yocto-Project\" >Embedded Linux: The Yocto Project<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Mender-for-OTA-updates-with-Raspberry-Pi-Yocto-and-Flutter\" >Mender for OTA updates with Raspberry Pi, Yocto and Flutter<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Embedded-Flutter\" >Embedded Flutter<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Cross-compilation-toolchain\" >Cross-compilation toolchain<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Putting-it-all-together\" >Putting it all together<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Use-case-Managing-meeting-room-status\"><\/span>Use case: Managing meeting room status<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>When approaching a meeting room, one would ideally like to see the occupation status of the room without consulting your phone\u2019s calendar or disturbing an attendee of the meeting. Key information that the display should provide are:<\/p>\n<ul>\n<li>What is the name of the room?<\/li>\n<li>Is it currently booked?<\/li>\n<li>When will the next meeting begin?<\/li>\n<\/ul>\n<p>At inovex, Google Workspace is used as a calendar synchronization solution, being the single source of truth for meetings and events. From a server perspective, this fulfills all the requirements for the project. Additionally, with the default Google Calendar set, <a href=\"https:\/\/workspace.google.com\/intl\/en\/products\/calendar\/\" target=\"_blank\" rel=\"noopener\">Google Workspace<\/a>\u00a0offers the ability to specify meeting rooms as resources that can be reserved when creating calendar events. Additional room details such as capacity or available equipment can be set by the workspace administrator. The meeting room display checks periodically for new or edited events through the <a href=\"https:\/\/developers.google.com\/calendar\/api\" target=\"_blank\" rel=\"noopener\">Google Calendar API<\/a> and updates its views to match the state of the event. Each display is assigned to a single room. Being able to book a meeting room immediately using the display is a very useful feature. Just as long as the room is not occupied!<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Raspberry-Pi-hardware\"><\/span>Raspberry Pi hardware<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-36587 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/display-components.jpg\" alt=\"Raspberry Pi Hardware \" width=\"1999\" height=\"953\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/display-components.jpg 1999w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-components-300x143.jpg 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-components-1024x488.jpg 1024w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-components-768x366.jpg 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-components-1536x732.jpg 1536w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-components-1920x915.jpg 1920w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-components-400x191.jpg 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-components-360x172.jpg 360w\" sizes=\"auto, (max-width: 1999px) 100vw, 1999px\" \/><\/h2>\n<p>On the hardware side, our current setup is made of:<\/p>\n<ul>\n<li>Raspberry Pi 3 Model B<\/li>\n<li>Touchscreen display<\/li>\n<li>Display case including cabling<\/li>\n<li>Heat sinks<\/li>\n<li>PoE splitter<\/li>\n<\/ul>\n<p>The case is needed to mount the display to the wall. Using <a href=\"https:\/\/en.wikipedia.org\/wiki\/Power_over_Ethernet\" target=\"_blank\" rel=\"noopener\">Power over Ethernet<\/a> (PoE) removes the need for an additional power supply unit. Because the Raspberry Pi does not have onboard PoE support, the splitter allows to supply power via the Micro-USB port. Due to its widespread use, the Raspberry Pi benefits from good general software support and was supported by Android Things. But it has some <a href=\"https:\/\/www.inovex.de\/de\/blog\/raspberry-pi-in-professional-products\/\" target=\"_blank\" rel=\"noopener\">flaws<\/a>, like under-voltage issues when using a PSU that does not provide sufficiently stable 5V \u2014 so we will move to <a href=\"https:\/\/www.raspberrypi.com\/products\/compute-module-4\/?variant=raspberry-pi-cm4001000\" target=\"_blank\" rel=\"noopener\">compute modules<\/a> in the next hardware revision.<\/p>\n<h4><span class=\"ez-toc-section\" id=\"Android-Things\"><\/span>Android Things<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>Android Things was <a href=\"https:\/\/android-developers.googleblog.com\/2019\/02\/an-update-on-android-things.html\" target=\"_blank\" rel=\"noopener\">deprecated<\/a> on January 5th, 2022 and so it needed to be replaced in the project. Originally code-named Brillo, Google announced Android for embedded devices at the Google IO 2015. Later, the name was changed to Android Things. Version 1.0 was released in 2018 and several smart devices based on it have been released by the likes of Lenovo, LG, and JBL. These devices have included smart home displays and speakers.<\/p>\n<p>Android Things offered building apps using the Android stack. Starting and debugging an app on a Raspberry Pi could be easily done with the Android Debug Bridge (ADB), without any noticeable differences to the development on an Android phone. The Raspberry Pi 3B and NXP i.MX7D were, for example, announced as supported devices for development.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-36597 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/things-starter-kit.png\" alt=\"Android Things Box mit Hardware und Android Figur\" width=\"1999\" height=\"1506\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/things-starter-kit.png 1999w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-starter-kit-300x226.png 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-starter-kit-1024x771.png 1024w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-starter-kit-768x579.png 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-starter-kit-1536x1157.png 1536w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-starter-kit-1920x1446.png 1920w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-starter-kit-400x301.png 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-starter-kit-360x271.png 360w\" sizes=\"auto, (max-width: 1999px) 100vw, 1999px\" \/> Android Things starter kit<\/p>\n<p>In contrast to the usual Android world, additional Things-specific Android <a href=\"https:\/\/developer.android.com\/reference\/com\/google\/android\/things\/classes.html\" target=\"_blank\" rel=\"noopener\">APIs<\/a> were offered. An interesting feature was the support for user-space drivers. User-space drivers allowed developers to access peripherals such as sensors without the need to touch the privileged kernel world. By building on top of well-defined Android APIs, the drivers could be easily <a href=\"https:\/\/github.com\/androidthings\/contrib-drivers\" target=\"_blank\" rel=\"noopener\">shared<\/a> and used as a library dependency. On the other hand, it was not possible to add features that run out of the scope of the provided APIs for user drivers, which would again require additional Linux kernel drivers.<\/p>\n<figure id=\"attachment_36599\" aria-describedby=\"caption-attachment-36599\" style=\"width: 700px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-36599 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/things-user-space-drivers.png\" alt=\"Android Things architecture overview\" width=\"700\" height=\"244\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/things-user-space-drivers.png 700w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-user-space-drivers-300x105.png 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-user-space-drivers-400x139.png 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/things-user-space-drivers-360x125.png 360w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><figcaption id=\"caption-attachment-36599\" class=\"wp-caption-text\">Android Things architecture overview<\/figcaption><\/figure>\n<h5>Android Things Developer Console<\/h5>\n<p>The Android Things Developer Console allowed project\/device management and Over-the-Air software updates (OTA). When creating a new release, a user-provided app in the form of a .apk file could be uploaded with the web interface. The app was bundled with an Android OS image. The resulting ISO could be downloaded and written to an SD card. Alternatively, it could be used with the OTA update mechanism as well. As known from usual Android devices, <a href=\"https:\/\/source.android.com\/devices\/tech\/ota\/ab\" target=\"_blank\" rel=\"noopener\">A\/B updates<\/a> provided a fault-tolerant update mechanism and were also added to Android Things. The OTA deployment procedure could take up to five hours and crucially it missed detailed progress monitoring. Furthermore, it was not possible to define an updated deployment schedule. It would have been very nice to be able to set it just to update devices at night but this was not possible.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Farewell-to-Android-Things-Hello-Raspberry-Pi-Flutter-Yocto\"><\/span>Farewell to Android Things: Hello Raspberry Pi, Flutter, Yocto<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>With news of the deprecation, a more modern solution had to be found to support a new platform for the meeting room displays and preferably, one that would resolve issues such as the vendor lock-in we had experienced earlier. So a solution combining Raspberry Pi, Yocto, Flutter and Mender was selected as the best option.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Embedded-Linux-The-Yocto-Project\"><\/span>Embedded Linux: The Yocto Project<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>An inovex <a href=\"https:\/\/www.inovex.de\/de\/blog\/remote-system-updates-with-mender\/\" rel=\"\">Smart Building project<\/a> had already made use of the <a href=\"https:\/\/www.yoctoproject.org\/\" target=\"_blank\" rel=\"noopener\">Yocto Project<\/a>. In contrast to Android Things, Yocto offers more flexibility regarding platform and driver support, by taking control of the Linux image creation process. A drawback with this flexibility is the requirement to tackle the complexity of embedded system development and Yocto itself. An example of this is the requirement to create different OS images for development and production. SSH access during development is useful but is a security issue for production.<\/p>\n<p>A core feature of any build system for usage with <a href=\"https:\/\/www.inovex.de\/de\/blog\/what-i-want-from-an-embedded-build-system\/\">embedded devices<\/a> is reproducibility. Our preference is to build deterministic environments, but interactively modifying a running Linux instance and cloning the finished image from the SD card will sacrifice this because changes are not transparent and version-controlled.<\/p>\n<p>Yocto uses <a href=\"https:\/\/docs.yoctoproject.org\/what-i-wish-id-known.html\">layers of metadata<\/a> to represent a platform and its capabilities. Composing these layers creates a new template, serving as a declaration for our custom embedded Linux. Layers are used as foundations and often provided by OEMs. On top of these layers, new ones are built, describing the application use case. The layers contain build recipes, and bitbake executes the necessary steps according to the steps defined by the recipe instructions when started. After steps like fetching, patching, compiling and linking, the bootable Linux image is produced.<\/p>\n<p>Instead of using a pre-built Android Things image, building it yourself enables the use of different devices in parallel. For example, the discontinuation of the Raspberry Pi 3 would not require replacing all our other devices. Successive integration of newer platforms like the Raspberry Pi 4 or the <a href=\"https:\/\/www.raspberrypi.com\/products\/compute-module-4\/?variant=raspberry-pi-cm4001000\" target=\"_blank\" rel=\"noopener\">Raspberry Pi Compute Module<\/a> is possible. <a href=\"https:\/\/docs.mender.io\" target=\"_blank\" rel=\"noopener\">Mender<\/a> makes it possible to manage a plethora of different devices with different specifications and architectures, preventing the distribution of an incompatible update. Furthermore, an embedded build system can be used in a CI\/CD pipeline context, in order to automate the build process.<\/p>\n<p>With Yocto as the main building block for the Linux system, there is still a need to replace several Android Things Console capabilities, such as:<\/p>\n<ul>\n<li>Over-the-air updates<\/li>\n<li>A\/B partitioning to apply system updates in a fail-safe manner<\/li>\n<li>Deterministic system updates<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Mender-for-OTA-updates-with-Raspberry-Pi-Yocto-and-Flutter\"><\/span>Mender for OTA updates with Raspberry Pi, Yocto and Flutter<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Mender provides \u201csecure, risk-tolerant and efficient over-the-air updates for all device software\u201c, which removes the need to create a DIY solution. The OTA implementation <a href=\"https:\/\/mender.io\/resources\/product-briefs\/_resources\/requirements-for-over-the-air-updates.pdf\" target=\"_blank\" rel=\"noopener\">checklist<\/a> demonstrates just how difficult and non-trivial it is to build and manage an OTA updates solution.<\/p>\n<p>Besides OTA updates and device fleet management options, Mender has additional benefits for our prospect including:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.mender.io\/add-ons\/remote-terminal\" target=\"_blank\" rel=\"noopener\">Remote terminal<\/a> for debugging and remote file access<\/li>\n<li><a href=\"https:\/\/docs.mender.io\/add-ons\/port-forward\" target=\"_blank\" rel=\"noopener\">Port forwarding<\/a><\/li>\n<li><a href=\"https:\/\/docs.mender.io\/add-ons\/monitor\" target=\"_blank\" rel=\"noopener\">Monitoring<\/a><\/li>\n<\/ul>\n<p>In contrast to the Android Things developer console, self-hosting is possible, too. For the meeting room project, we decided to use the hosted solution provided by Mender, but depending on the progress and scope of this and other projects it might be beneficial to change to an on-premise setup.<\/p>\n<p>On the client-side, the Mender client is required for communicating with the management server and supervising the device update cycle. The meta-mender <a href=\"https:\/\/docs.mender.io\/system-updates-yocto-project\/overview\" target=\"_blank\" rel=\"noopener\">layer<\/a> can be used for easy Yocto integration. Other platforms and build tools are supported as well.<\/p>\n<p>When a device running software including the Mender integration boots for the first time, it will be registered at the management server. Without <a href=\"https:\/\/docs.mender.io\/server-integration\/preauthorizing-devices\" target=\"_blank\" rel=\"noopener\">preauthorization<\/a>, devices are manually accepted using the web UI. A default set of attributes is populated by Mender per device, like the city name, which is based on the geolocation IP. This conveniently enables sorting the devices into groups based on the device location. There are two types of groups: static and dynamic. Devices can be manually added to static groups, which needs to be done for every new device. On the other hand, a dynamic group can be defined by attribute filters. A device will be automatically added to a group specified by the filter.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-36593 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-device-groups.png\" alt=\"\" width=\"1999\" height=\"670\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-device-groups.png 1999w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-device-groups-300x101.png 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-device-groups-1024x343.png 1024w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-device-groups-768x257.png 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-device-groups-1536x515.png 1536w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-device-groups-1920x644.png 1920w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-device-groups-400x134.png 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-device-groups-360x121.png 360w\" sizes=\"auto, (max-width: 1999px) 100vw, 1999px\" \/> Mender Web UI showing the Cologne device group<\/p>\n<p>Depending on the type of the Mender <a href=\"https:\/\/docs.mender.io\/overview\/artifact\" target=\"_blank\" rel=\"noopener\">artifact<\/a>, it contains a full Linux image or a customizable set of application data. Included in both cases is additional metadata, such as the target architecture. This is necessary because the management server should be able to decide which clients are compatible with an update. The signing of the artifacts is required for authenticated updates. Releasing updates can be limited to groups.<\/p>\n<p>Scheduled deployments are part of the Mender professional plan and enable fine-grained control of the update process.<\/p>\n<p>&nbsp;<\/p>\n<figure id=\"attachment_36595\" aria-describedby=\"caption-attachment-36595\" style=\"width: 780px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-36595 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-update-schedule.png\" alt=\"Update Schedule\" width=\"780\" height=\"656\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-update-schedule.png 780w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-update-schedule-300x252.png 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-update-schedule-768x646.png 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-update-schedule-400x336.png 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/mender-update-schedule-360x303.png 360w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><figcaption id=\"caption-attachment-36595\" class=\"wp-caption-text\"><a href=\"https:\/\/mender.io\/blog\/synchronized-ota-software-update\" target=\"_blank\" rel=\"noopener\">Scheduling update deployments<\/a><\/figcaption><\/figure>\n<h2><span class=\"ez-toc-section\" id=\"Embedded-Flutter\"><\/span>Embedded Flutter<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Flutter is a multi-platform UI development framework. It is primarily targeting the prevailing mobile operating systems Android and iOS. <a href=\"https:\/\/flutter.dev\/multi-platform\/desktop\" target=\"_blank\" rel=\"noopener\">Desktop<\/a> (Linux, macOS, Windows) and the <a href=\"https:\/\/flutter.dev\/multi-platform\/web\" target=\"_blank\" rel=\"noopener\">web<\/a> (browser, V8) are also supported as well.<\/p>\n<p>Flutter uses the Dart programming language, following a <a href=\"https:\/\/docs.flutter.dev\/get-started\/flutter-for\/declarative\" target=\"_blank\" rel=\"noopener\">declarative <\/a>approach for UI modeling. Instead of writing state transitions in an imperative style, this is handled by the framework.<\/p>\n<figure id=\"attachment_36585\" aria-describedby=\"caption-attachment-36585\" style=\"width: 700px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-36585 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/dart-platforms.png\" alt=\"Platforms supported by the Dart compiler\" width=\"700\" height=\"355\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/dart-platforms.png 700w, https:\/\/www.inovex.de\/wp-content\/uploads\/dart-platforms-300x152.png 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/dart-platforms-400x203.png 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/dart-platforms-360x183.png 360w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><figcaption id=\"caption-attachment-36585\" class=\"wp-caption-text\"><a href=\"https:\/\/dart.dev\/overview#platform\" target=\"_blank\" rel=\"noopener\">Platforms supported by the Dart compiler<\/a><\/figcaption><\/figure>\n<p>Dart was initially aiming at web and JavaScript (dart2js). But since the early stages, Dart has evolved to target more platforms and has been aligned to the specific needs of the Flutter framework. By creating release builds, the dart compiler generates native machine code using ahead-of-time (AOT) compilation (dart2native) to provide more consistent startup times. During the development stage just-in-time (JIT) compilation can be used, cutting down the round trip time and enabling hot code reloading.<\/p>\n<figure id=\"attachment_36591\" aria-describedby=\"caption-attachment-36591\" style=\"width: 918px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-36591 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/flutter-architectural-layers.png\" alt=\"Architectural layers of Framework, Engine and Embedder\" width=\"918\" height=\"753\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/flutter-architectural-layers.png 918w, https:\/\/www.inovex.de\/wp-content\/uploads\/flutter-architectural-layers-300x246.png 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/flutter-architectural-layers-768x630.png 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/flutter-architectural-layers-400x328.png 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/flutter-architectural-layers-360x295.png 360w\" sizes=\"auto, (max-width: 918px) 100vw, 918px\" \/><figcaption id=\"caption-attachment-36591\" class=\"wp-caption-text\"><a href=\"https:\/\/docs.flutter.dev\/resources\/architectural-overview#architectural-layers\" target=\"_blank\" rel=\"noopener\">Architectural layers<\/a><\/figcaption><\/figure>\n<p>By decoupling the framework, engine and embedder enable apps developed with Flutter to be run on different platforms without the need to change the Dart source code. A custom embedder can be implemented by adhering to a single C <a href=\"https:\/\/github.com\/flutter\/engine\/blob\/main\/shell\/platform\/embedder\/embedder.h\" target=\"_blank\" rel=\"noopener\">header file<\/a>. This interface defines the minimum runtime requirements expected for an embedder implementation, like the app lifecycle or fundamental rendering capabilities. Features beyond this scope, e.g. camera access, can be implemented via <a href=\"https:\/\/docs.flutter.dev\/development\/platform-integration\/platform-channels\" target=\"_blank\" rel=\"noopener\">Platform Channel<\/a>. A Platform Channel communicates with JSON messages between Dart and platform-specific code.<\/p>\n<p>The Flutter team officially supports major mobile and desktop platforms and maintains the corresponding embedders.<\/p>\n<p>Specialized embedders targeting devices like the Raspberry Pi have been created by the community:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/ardera\/flutter-pi\" target=\"_blank\" rel=\"noopener\"><code>flutter-pi<\/code> embedder<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/sony\/flutter-embedded-linux\" target=\"_blank\" rel=\"noopener\">Sony Flutter Embedder<\/a><\/li>\n<\/ul>\n<p>We use the <code>flutter-pi<\/code> embedder, due to its use of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Direct_Rendering_Manager\" target=\"_blank\" rel=\"noopener\">Direct Rendering Infrastructure<\/a> (DRI)\u00a0 eliminating the need for X or Wayland. This gives Flutter the capability to be started from the command line and run in <a href=\"https:\/\/en.wikipedia.org\/wiki\/Kiosk_software\" target=\"_blank\" rel=\"noopener\">kiosk<\/a> mode. A user cannot move the application to the background or open different applications.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Cross-compilation-toolchain\"><\/span>Cross-compilation toolchain<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The Raspberry Pi 3B and later versions are equipped with 64-bit ARM (aarch64) processors. Cross-compilation is needed when using an x86-64 development platform because it is not possible to run x86-64 binaries on aarch64 platforms without emulation. Despite the Flutter toolchain having cross-compilation support for Android and iOS, it is <a href=\"https:\/\/github.com\/flutter\/flutter\/issues\/74929\" target=\"_blank\" rel=\"noopener\">currently<\/a> not possible to use it for targeting other desktop platforms. To use the default Flutter frontend server, the host platform needs to match the target platform. Since our development machine and CI pipeline are x86-64 machines, an alternative was required.<\/p>\n<p>It is possible to instruct the Dart compiler to build aarch64 machine code, by using the Dart compiler frontend. But the engine and the embedder have to be compiled for the Raspberry Pi as well.<\/p>\n<p>Until the cross-compilation situation improves, the following steps are necessary to run a release build of the application.<\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Build step<\/b><\/td>\n<td><b>Command<\/b><\/td>\n<td><b>Output<\/b><\/td>\n<\/tr>\n<tr>\n<td>Build release Flutter asset bundle<\/td>\n<td><code>flutter build bundle<\/code><\/td>\n<td><code>flutter_assets\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>Build Dart AOT <a href=\"https:\/\/github.com\/dart-lang\/sdk\/wiki\/Kernel-Documentation\" target=\"_blank\" rel=\"noopener\">kernel<\/a> snapshot (DartVM)<\/td>\n<td><code>dart frontend_server.dart.snapshot<\/code><\/td>\n<td>kernel_snapshot.dill<\/td>\n<\/tr>\n<tr>\n<td>Flutter AOT <a href=\"https:\/\/github.com\/flutter\/flutter\/wiki\/Flutter-engine-operation-in-AOT-Mode\" target=\"_blank\" rel=\"noopener\">snapshot generation<\/a><\/td>\n<td><code>gen_snapshot_linux_x64_release<\/code><\/td>\n<td><code>app.so<\/code><\/td>\n<\/tr>\n<tr>\n<td>Build <code>flutter-pi<\/code> embedder and cli<\/td>\n<td><code>make -j `nproc`<\/code><\/td>\n<td><code>flutter-pi<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Docker is a convenient tool for this task. It is possible to run the build tasks locally and by a continuous integration pipeline, by specifying all necessary steps in a <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\" target=\"_blank\" rel=\"noopener\">Dockerfile<\/a>.<\/p>\n<p>When successfully built locally or in a CI context, the <code>flutter_assets<\/code> directory can be transferred to the Raspberry Pi with e.g. <code>scp<\/code>.<\/p>\n<p>One pitfall is that the engine version does not match with the flutter version used to build the asset bundle when running <code>flutter-pi --release flutter_assets<\/code>. Showing one of the following errors at runtime:<\/p>\n<ul>\n<li>Invalid kernel binary format version<\/li>\n<li>Invalid SDK hash or Invalid engine hash<\/li>\n<\/ul>\n<p>Details regarding the Flutter version can be shown by running <code>flutter --version<\/code>. The resulting output might be:<\/p>\n<pre>Flutter 3.0.1 \u2022 channel stable \u2022 https:\/\/github.com\/flutter\/flutter.git\r\nFramework \u2022 revision fb57da5f94 (4 days ago) \u2022 2022-05-19 15:50:29 -0700\r\nEngine \u2022 revision caaafc5604\r\nTools \u2022 Dart 2.17.1 \u2022 DevTools 2.12.2<\/pre>\n<p>The revision hash, shown in the example, should match the <a href=\"https:\/\/github.com\/flutter\/flutter\/blob\/stable\/bin\/internal\/engine.version\" target=\"_blank\" rel=\"noopener\">engine version hash<\/a>\u200b\u200b. If this is not the case, one needs to upgrade or downgrade the Flutter version used to build the application bundle to align with the engine version. Alternatively, a different Flutter engine version can be chosen.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Putting-it-all-together\"><\/span>Putting it all together<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Instead of running the application on the host OS, it is wrapped in a Docker container, which also increases container and application interchangeability. But this is rather limited due to requirements for kernel modules by the application layer. For example, the host system needs to load the Raspberry Pi backlight device tree overlay, in order that the application can control the display brightness. This cannot be done in the container, as it does not have access to hardware.<\/p>\n<p>In addition to the application files, the container provides the runtime dependencies required by <code>flutter-pi<\/code> and the engine, such as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Fontconfig\" target=\"_blank\" rel=\"noopener\">fontconfig<\/a>.<\/p>\n<figure id=\"attachment_37364\" aria-describedby=\"caption-attachment-37364\" style=\"width: 460px\" class=\"wp-caption alignleft\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-37364\" style=\"display: inline-block; margin-right: 15px;\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/display-before-1024x768.jpg\" alt=\"Old display\" width=\"460\" height=\"345\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/display-before-1024x768.jpg 1024w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-before-300x225.jpg 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-before-768x576.jpg 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-before-400x300.jpg 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-before-360x270.jpg 360w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-before.jpg 1280w\" sizes=\"auto, (max-width: 460px) 100vw, 460px\" \/><figcaption id=\"caption-attachment-37364\" class=\"wp-caption-text\">Old display<\/figcaption><\/figure>\n<figure id=\"attachment_36589\" aria-describedby=\"caption-attachment-36589\" style=\"width: 460px\" class=\"wp-caption alignleft\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-36589\" style=\"display: inline-block; margin-right: 15px;\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/display-jobs-1024x768.jpg\" alt=\"display after\" width=\"460\" height=\"345\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/display-jobs-1024x768.jpg 1024w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-jobs-300x225.jpg 300w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-jobs-768x576.jpg 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-jobs-1536x1152.jpg 1536w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-jobs-400x300.jpg 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-jobs-360x270.jpg 360w, https:\/\/www.inovex.de\/wp-content\/uploads\/display-jobs.jpg 1823w\" sizes=\"auto, (max-width: 460px) 100vw, 460px\" \/><figcaption id=\"caption-attachment-36589\" class=\"wp-caption-text\">New display<\/figcaption><\/figure>\n<h2><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>There is still room for improvement in the project with regards to the degree of automation and flexibility:<\/p>\n<ul>\n<li>Instead of relying on pre-built flutter engine binaries, <a href=\"https:\/\/github.com\/flutter\/flutter\/wiki\/Compiling-the-engine\" target=\"_blank\" rel=\"noopener\">doing<\/a> this by yourself allows the usage of an arbitrary Flutter version. Faster adoption of newer Flutter versions is another advantage.<\/li>\n<li>The Sony embedder has broader device support and can be used in more traditional Linux desktop environments using X or Wayland display server. This allows for multiple windows to be visible at once. Using the Direct Rendering Interface is supported as well.<\/li>\n<li>Running the Docker without privileged permissions to circumvent access to the host system from a malicious container or app.<\/li>\n<li>Currently, the Mender artifact built and signed by the CI pipeline is uploaded manually using the Web UI. Automatic artifact upload after successful CI job execution can be achieved with the <a href=\"https:\/\/docs.mender.io\/api\/#introduction\" target=\"_blank\" rel=\"noopener\">Mender API<\/a>.<\/li>\n<li>Using the Raspberry Pi 4 Compute Module as new hardware revision, instead of relying on the aged Raspberry Pi 3, for instance because of the supply availability.<\/li>\n<\/ul>\n<p>Moreover, Mender provides many features which we are not using at the time. These include delta updates or application monitoring.<\/p>\n<p>Due to the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Separation_of_concerns\" target=\"_blank\" rel=\"noopener\">separation of concerns<\/a>, editing or replacing a component should have limited consequences for adjacent components. Introducing the Raspberry Pi 4 or the Compute Module as a new platform to our fleet should have implications only regarding Yocto. In the same sense, the exchange of the Flutter embedder should not require refactorings to the application code or the Yocto build.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog article we show how we migrated our meeting room displays from Android Things to a solution combining Raspberry Pi, Yocto, Flutter and Mender.<\/p>\n","protected":false},"author":294,"featured_media":36627,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"ep_exclude_from_search":false,"footnotes":""},"tags":[149,510,378,74,353],"service":[420,712],"coauthors":[{"id":294,"display_name":"Wolfhard Prell","user_nicename":"wprell"}],"class_list":["post-36584","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-android","tag-apps-2","tag-flutter","tag-iot","tag-mobile","service-apps","service-internet-of-things-iot"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Migrate to Linux with Yocto and Flutter in Embedded Devices - inovex GmbH<\/title>\n<meta name=\"description\" content=\"In this blog article we show how we migrated our meeting room displays from Android Things to a solution combining Raspberry Pi, Yocto, Flutter and Mender.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Migrate to Linux with Yocto and Flutter in Embedded Devices - inovex GmbH\" \/>\n<meta property=\"og:description\" content=\"In this blog article we show how we migrated our meeting room displays from Android Things to a solution combining Raspberry Pi, Yocto, Flutter and Mender.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\" \/>\n<meta property=\"og:site_name\" content=\"inovex GmbH\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/inovexde\" \/>\n<meta property=\"article:published_time\" content=\"2022-05-31T12:36:28+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-11-14T11:36:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-smart-building-ota-update.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Wolfhard Prell\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-smart-building-ota-update-1024x576.png\" \/>\n<meta name=\"twitter:creator\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:site\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Wolfhard Prell\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"16\u00a0Minuten\" \/>\n\t<meta name=\"twitter:label3\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data3\" content=\"Wolfhard Prell\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\\\/\"},\"author\":{\"name\":\"Wolfhard Prell\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/600941337ef6e1eb19bf8cc5e4dfdc5d\"},\"headline\":\"Migrate to Linux with Yocto and Flutter in Embedded Devices\",\"datePublished\":\"2022-05-31T12:36:28+00:00\",\"dateModified\":\"2022-11-14T11:36:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\\\/\"},\"wordCount\":2585,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/mender-smart-building-ota-update.png\",\"keywords\":[\"Android\",\"Apps\",\"Flutter\",\"IoT\",\"Mobile\"],\"articleSection\":[\"Applications\",\"English Content\",\"General\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\\\/\",\"url\":\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\",\"name\":\"Migrate to Linux with Yocto and Flutter in Embedded Devices - inovex GmbH\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/mender-smart-building-ota-update.png\",\"datePublished\":\"2022-05-31T12:36:28+00:00\",\"dateModified\":\"2022-11-14T11:36:12+00:00\",\"description\":\"In this blog article we show how we migrated our meeting room displays from Android Things to a solution combining Raspberry Pi, Yocto, Flutter and Mender.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#primaryimage\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/mender-smart-building-ota-update.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/mender-smart-building-ota-update.png\",\"width\":1920,\"height\":1080,\"caption\":\"Raumdisplay mit Cloud Zeichnung\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/mender.io\\\/blog\\\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Migrate to Linux with Yocto and Flutter in Embedded Devices\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"name\":\"inovex GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\",\"name\":\"inovex GmbH\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"width\":1921,\"height\":1081,\"caption\":\"inovex GmbH\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/inovexde\",\"https:\\\/\\\/x.com\\\/inovexgmbh\",\"https:\\\/\\\/www.instagram.com\\\/inovexlife\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/inovex\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UC7r66GT14hROB_RQsQBAQUQ\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/600941337ef6e1eb19bf8cc5e4dfdc5d\",\"name\":\"Wolfhard Prell\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ebcb83bb7ff66e11ca3d3f386684d0d7bd5bdfb0959625dfae5683a2a6d90b69?s=96&d=retro&r=gfc3ac4bbf03272b93afe750691b79ce7\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ebcb83bb7ff66e11ca3d3f386684d0d7bd5bdfb0959625dfae5683a2a6d90b69?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ebcb83bb7ff66e11ca3d3f386684d0d7bd5bdfb0959625dfae5683a2a6d90b69?s=96&d=retro&r=g\",\"caption\":\"Wolfhard Prell\"},\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/author\\\/wprell\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Migrate to Linux with Yocto and Flutter in Embedded Devices - inovex GmbH","description":"In this blog article we show how we migrated our meeting room displays from Android Things to a solution combining Raspberry Pi, Yocto, Flutter and Mender.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/","og_locale":"de_DE","og_type":"article","og_title":"Migrate to Linux with Yocto and Flutter in Embedded Devices - inovex GmbH","og_description":"In this blog article we show how we migrated our meeting room displays from Android Things to a solution combining Raspberry Pi, Yocto, Flutter and Mender.","og_url":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices","og_site_name":"inovex GmbH","article_publisher":"https:\/\/www.facebook.com\/inovexde","article_published_time":"2022-05-31T12:36:28+00:00","article_modified_time":"2022-11-14T11:36:12+00:00","og_image":[{"width":1920,"height":1080,"url":"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-smart-building-ota-update.png","type":"image\/png"}],"author":"Wolfhard Prell","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-smart-building-ota-update-1024x576.png","twitter_creator":"@inovexgmbh","twitter_site":"@inovexgmbh","twitter_misc":{"Verfasst von":"Wolfhard Prell","Gesch\u00e4tzte Lesezeit":"16\u00a0Minuten","Written by":"Wolfhard Prell"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#article","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/"},"author":{"name":"Wolfhard Prell","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/600941337ef6e1eb19bf8cc5e4dfdc5d"},"headline":"Migrate to Linux with Yocto and Flutter in Embedded Devices","datePublished":"2022-05-31T12:36:28+00:00","dateModified":"2022-11-14T11:36:12+00:00","mainEntityOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/"},"wordCount":2585,"commentCount":0,"publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"image":{"@id":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-smart-building-ota-update.png","keywords":["Android","Apps","Flutter","IoT","Mobile"],"articleSection":["Applications","English Content","General"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.inovex.de\/de\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices\/","url":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices","name":"Migrate to Linux with Yocto and Flutter in Embedded Devices - inovex GmbH","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#primaryimage"},"image":{"@id":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-smart-building-ota-update.png","datePublished":"2022-05-31T12:36:28+00:00","dateModified":"2022-11-14T11:36:12+00:00","description":"In this blog article we show how we migrated our meeting room displays from Android Things to a solution combining Raspberry Pi, Yocto, Flutter and Mender.","breadcrumb":{"@id":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#primaryimage","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-smart-building-ota-update.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/mender-smart-building-ota-update.png","width":1920,"height":1080,"caption":"Raumdisplay mit Cloud Zeichnung"},{"@type":"BreadcrumbList","@id":"https:\/\/mender.io\/blog\/migrate-to-linux-with-yocto-and-flutter-in-embedded-devices#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.inovex.de\/de\/"},{"@type":"ListItem","position":2,"name":"Migrate to Linux with Yocto and Flutter in Embedded Devices"}]},{"@type":"WebSite","@id":"https:\/\/www.inovex.de\/de\/#website","url":"https:\/\/www.inovex.de\/de\/","name":"inovex GmbH","description":"","publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.inovex.de\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/www.inovex.de\/de\/#organization","name":"inovex GmbH","url":"https:\/\/www.inovex.de\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","width":1921,"height":1081,"caption":"inovex GmbH"},"image":{"@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/inovexde","https:\/\/x.com\/inovexgmbh","https:\/\/www.instagram.com\/inovexlife\/","https:\/\/www.linkedin.com\/company\/inovex","https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ"]},{"@type":"Person","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/600941337ef6e1eb19bf8cc5e4dfdc5d","name":"Wolfhard Prell","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/ebcb83bb7ff66e11ca3d3f386684d0d7bd5bdfb0959625dfae5683a2a6d90b69?s=96&d=retro&r=gfc3ac4bbf03272b93afe750691b79ce7","url":"https:\/\/secure.gravatar.com\/avatar\/ebcb83bb7ff66e11ca3d3f386684d0d7bd5bdfb0959625dfae5683a2a6d90b69?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ebcb83bb7ff66e11ca3d3f386684d0d7bd5bdfb0959625dfae5683a2a6d90b69?s=96&d=retro&r=g","caption":"Wolfhard Prell"},"url":"https:\/\/www.inovex.de\/de\/blog\/author\/wprell\/"}]}},"_links":{"self":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/36584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/users\/294"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/comments?post=36584"}],"version-history":[{"count":5,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/36584\/revisions"}],"predecessor-version":[{"id":37370,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/36584\/revisions\/37370"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media\/36627"}],"wp:attachment":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media?parent=36584"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/tags?post=36584"},{"taxonomy":"service","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/service?post=36584"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/coauthors?post=36584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}