<![CDATA[Peters Blog]]>https://flutterdev.at/https://flutterdev.at/favicon.pngPeters Bloghttps://flutterdev.at/Ghost 6.21Sat, 21 Mar 2026 11:45:25 GMT60<![CDATA[Was Neues wagen...]]>Nach dem Launch der Flutter-App ESP32-Cam ist in mir die Idee gereift, meine App-Entwicklung auch kommerziell auszurichten. Für diesen Zweck wurde nun eine kleine Website, https://flutterdev.app, eingerichtet, die unsere Dienstleistungen nach außen hin präsentieren soll.

Ich rede bewusst von unseren Dienstleistungen, da

]]>
https://flutterdev.at/was-neues-wagen/6982fc64abae79b1de494de9Wed, 04 Feb 2026 08:37:26 GMT

Nach dem Launch der Flutter-App ESP32-Cam ist in mir die Idee gereift, meine App-Entwicklung auch kommerziell auszurichten. Für diesen Zweck wurde nun eine kleine Website, https://flutterdev.app, eingerichtet, die unsere Dienstleistungen nach außen hin präsentieren soll.

Was Neues wagen...

Ich rede bewusst von unseren Dienstleistungen, da mich seit Dezember 2025 nun auch ein kleines Team aus Polen, beheimatet im schönen Racibórz, bei der Entwicklung unterstützt – https://flutterdev.pl.

Was Neues wagen...
Zwei Teams

Aktuell entwickeln wir einige spannende neue Apps, die bald auch hier ihren Niederschlag in schriftlicher Form erfahren werden.

]]>
<![CDATA[Es ist vollbracht...]]>Ein weiterer Punkt, den ich im Rahmen des Flutter-Projekts ESP32-Cam austesten wollte, war das Deployen der App, neben den klassischen Stores von Apple und Google, in weitere App Stores wie: Amazon Store (Android Version), Microsoft Windows Store und für Linux in snapcraft.io, dem App Store fü

]]>
https://flutterdev.at/es-ist-vollbracht/6929f1519cecb301a5a58fd5Sat, 29 Nov 2025 16:25:34 GMT

Ein weiterer Punkt, den ich im Rahmen des Flutter-Projekts ESP32-Cam austesten wollte, war das Deployen der App, neben den klassischen Stores von Apple und Google, in weitere App Stores wie: Amazon Store (Android Version), Microsoft Windows Store und für Linux in snapcraft.io, dem App Store für snap basierte Pakete.

Da Flutter neben iOS und Android auch Desktop-Betriebssysteme wie MacOS, Windows und Linux unterstützt, ist dies machbar. Folgende Belange sind aber zu bedenken:

Spezifische Funktionen, wie z.B. eine einheitliche Bezahlfunktion über alle Stores hinweg ist eine Herausforderung. Die ESP32-Cam App hat eine Bezahlfunktion für Apple und Google implementiert, die eine Spende für das Projekt ermöglicht. Dieser freiwillige Obulus ist aber mit keiner Funktionalität der App verknüpft. Für die restlichen Varianten habe ich den Spenden-Dienst Buy Me a Coffee eingebunden.

Bei Zahlungsdiensten ist überhaupt Vorsicht an den Tag zu legen, da dies ein Punkt ist. der bei einer App-Review leicht Ärger machen kann. Für Apple und Google sind nur direkte oder indirekte Zahlungen über das jeweilige hauseigene Zahlungssystem möglich. Mit indirekten Zahlungen sind Flutter-Plugins á flutter-stripe gemeint, die zwar eine einheitliche Zahlung für iOS und Android anbieten, dies aber einhergehend mit dem Wermutstropfen, Geld an Apple/Google UND Stripe anteilsmäßig abführen zu dürfen.

Abhängig von der App, respektive der Anzahl der verwendeten Plugins kann die Unterstützung über die verschiedenen Betriebssysteme hinweg einiges an Mehrarbeit nach sich ziehen, da Plugins in den wenigsten Fällen für alle Plattformen zur Verfügung stehen.

Im Fall der ESP32-Cam App war dies nur die Methode, die den Pfad der Bilder für das jeweilige OS ermittelt, um dort auf Knopfdruck Bilder der Kamera speichern zu können. Für die mobilen OS-Varianten kam das Plugin image_gallery_saver_plus zum Einsatz, für die Desktop Varianten war dann OS-spezifischer Code von Nöten. z.B die Windows-Variante

String getWindowsPicturesPath() {
  final pathPtr = calloc>();
  // KnownFolderId for Pictures
  final result = SHGetKnownFolderPath(
    GUIDFromString(FOLDERID_Pictures),
    0,
    NULL,
    pathPtr,
  );

  if (result == S_OK) {
    final path = pathPtr.value.toDartString();
    calloc.free(pathPtr);
    return path;
  } else {
    calloc.free(pathPtr);
    return "";
  }
}

Und wenn man legis artis programmiert, dann sollte man diese OS-Spezifika alle derart trennen, sodass z.B. beim Android-Build der Windows-Code nicht eingebunden wird. Da Dart/Flutter keine Makros kennt, á C, ist die Trennung etwas eine Spielerei.

Zurück zu den Erfahrungen mit dem Deployment der App in die einzelnen Stores:

Apple: Das Apple-Review-Team hatte zwei Punkte moniert. Da sie diese Art von App nicht direkt testen können, wollten sie ein Video von der App samt Kamera in Aktion. Beim zweiten Punkt hatte ich einen Schreck bekommen. Die App wurde aus Copyright-Gründen aus dem Store entfernt - meine App könnte ja Rechte von Espressif verletzten. Diese mögliche Tatsache wird einem juristisch ausformuliert um die Ohren gehauen.

Als Entgegnung wurde eine Architektur-Beschreibung der App abgeliefert, dass diese nur auf einen Webserver, der auf der ESP32-Cam läuft, zugreift, und somit keine Rechte jeglicher Art verletzt werden sollten. Dem Einspruch wurde stattgegeben und per Button in der Apple-Store Oberfläche konnte ich die App wieder in den Store einbringen.

Dies war eine harte Lernkurve, aber nun ist es klar, wie man bei Apple diese Art von Hardware-App einbringen sollte.

Google Play: Keine Besonderheiten, außer dass das Durchwinken der App über eine Woche gedauert hat.

Windows Store: Keine wirklichen Probleme, der Store ist etwas bürokratisch gestaltet - was da alles an Forms ausgefüllt werden will. Wenn man dies noch nie getan hat, dann sind einige Iterationsschleifen vonnöten, bis dem Store alles passt.

snapcarft.io: Der Store an sich war keine Herausforderung - eher die fummelige snapcraft-Umgebung, die zum Bauen eines snap Pakets von Nöten ist. Das hat mich doch einiges an Zeit gekostet.

Es ist vollbracht...


Und bei jeder Herausforderung gibt es einen finalen Endgegner, und den hätte ich so nicht erwartet, der Amazon Store:

Aus den Erfahrungen mit dem Apple Store habe ich wohlweislich Video und Architekturbeschreibung mitgeschickt. Diese Info hat aber scheinbar keiner gelesen. Die App wurde im Store-System mit einem legal issue markiert - Rechte am generischen Begriff ESP32. Also etwas frustriert einen Support-Case eröffnet und nochmals alle Informationen eingebracht und betont, dass diese App in den anderen Stores zur Verfügung steht.

Fast zwei Wochen ist nichts passiert - case is pending. Dann habe ich den KI-Chat-Bot von Amazon gefragt. Dieser hat gemeint, er verstehe meine Frustration - aber vielleicht verletzte ich Richtlinien von Amazon, die für Apple und Google kein Problem seinen. Amazon und Copyright, und päpstlicher als der Papst - selten so gelacht.

Die KI hat aber einen guten Tipp gegeben - ich sollte mich an das Amazon-Entwickler- Forum mit meinem Problem wenden. Getan, aber meine Problembeschreibung war dann schon ehrlicherweise ein rant. So ein Beitrag im Forum muss aber von einem Moderator freigschaltet werden. Nur diese Freischaltung war dann für die nächsten Tage im Status pending.

Meine emotionale Ausgeglichenheit, was den Amazon-Store betrifft, ist auf nicht jugendfreies Niveau an Invektiven gerutscht. Aber das Posting hat intern was ausgelöst - nach 4 Tagen ist dann die App mit einer Entschuldigung ob der Verzögerung freigeschaltet worden.

Was noch fehlt? Drei Punkte:

Es fehlen noch die App Versionen für MacOS und die ARM64-Varianten für Linux/Windows, zusätzlich zur X86 Variante.

App-Store Screenshots sollten grafisch aufbereitet werden, nicht nur der reine Screenshot - und diese Spielchen für alle Stores in den der vom Store geforderten Auflösung.

Eine Flutter App ist in der Desktop-Umgebung, was das Fenster betrifft, in der die App läuft, doch etwas ein Fremdkörper.

Es ist vollbracht...

Um diese Manko zu beseitigen gibt es Flutter-Plugin wie bitsdojo_window, das die Anpassung des Windows ermöglicht.




]]>
<![CDATA[ESP32-Cam]]>ESP32-Cam ist mein erster ernsthafter Versuch, eine vollständige Flutter-App mit Hilfe einer AI-IDE von der Idee bis zur fertigen App in den jeweiligen Stores von Apple und Google umzusetzen. Eher zufällig bin ich durch ein YouTube-Video auf Kiro, die AI-IDE von Amazon aufmerksam geworden. Mit der

]]>
https://flutterdev.at/esp32-cam/6915cda8feae79b71fc34bf8Thu, 13 Nov 2025 19:02:46 GMT

ESP32-Cam ist mein erster ernsthafter Versuch, eine vollständige Flutter-App mit Hilfe einer AI-IDE von der Idee bis zur fertigen App in den jeweiligen Stores von Apple und Google umzusetzen. Eher zufällig bin ich durch ein YouTube-Video auf Kiro, die AI-IDE von Amazon aufmerksam geworden. Mit der Warteliste dieser IDE, die sich damals noch in der Preview-Phase befand, hatte ich Glück. Zwei Tage nach der Anmeldung konnte ich mit der AI-IDE loslegen.

ESP32-Cam

Ziel war es eine App zu entwickeln, die möglichst friktionsfrei eine ESP32-Cam mit dem CameraWebServer Sketch als Image einbindet. Installation und technische Details zu dieser Kamera find sich hier.

ESP32-Cam

Die Bilder der Kamera werden über einen Link nach dem Schema

http://192.168.1.2:81/stream

als Stream von JPEG-Bildern abgerufen.

Als Erstes habe ich Kiro die Aufgabe gestellt ein Widget zu programmieren, das gleichsam einem Daumenkino in einer Schleife die Bilder der Kamera abruft und darstellt. Diese Problemstellung hat Kiro im ersten Anlauf mit Bravour gemeistert.

ESP32-Cam


Die zweite Aufgabenstellung war es eine Funktion zu schreiben, die ein Netzwerksegment nach laufenden ESP32-Kameras durchsucht, indem jeweils 1 KB von jeder IP, die auf Port 80 antwortet, eingelesen wird, und dann diese Daten nach einem bestimmten String durchsucht werden. In der ersten Version wollte diese Funktion nicht wirklich, was aber mein Fehler war, weil die Web-Oberfläche der Kamera ihre HTML-Daten gzip-ed ausliefert. Den Prompt um diese Funktionalität erweitert lieferte dann das gewünschte Ergebnis.

Als weiterer Wunsch wurde der Prompt um Parallelisierung der Suche ergänzt.

ESP32-Cam


Da hat mich die KI vom Code her beeindruckt. Jeder der das Isolate-Konzept von Dart kennt, um Multithreading zu implementieren, das doch umständlicher ist als die Multithreading-Implementierungen anderer Programmiersprachen, wie zum Beispiel Java. Der KI-Code war sofort lauffähig und strukturiert aufgebaut.

Als nächsten Schritt sollte mir die KI gut aussehende Widgets zur Ansteuerung der Kamera erzeugen. Und auch hier hat mich die KI überrascht - schöne Widgets, wo ich selbst als Flutter-Entwickler mit Erfahrung lange gebraucht hätte. Die Kunst beim Stylen von Flutter-Widgets ist die deklarativen kaskadierenden Styling-Elemente so anzuordnen, dass das Endergebnis gut aussieht.

ESP32-Cam


Nachdem die Core-Logik und benötigten UI-Elemente fertiggestellt waren, habe ich was die Gruppierung betrifft, doch selbst Hand angelegt. Bei dieser Aufgabenstellung neigt die KI doch manchmal zu viel des Guten zu tun.


Sehr spezielle Logik, wie z.B. der Context-Switch, zwischen der Kamera im Preview-Mode und in der Vollansicht habe ich dann doch selbst programmiert. Wahrscheinlich hätte die KI dies auch bewerkstelligen können. Da ich aber danach trachte jeden Code, den die KI erzeugt, zu reviewen, kostet das selbst schreiben manchmal doch weniger Zeit, als den Code der KI vollumfänglich zu verstehen.

Fazit - mit Hilfe der KI habe ich sicherlich die Hälfte der Zeit eingespart. Mit der gewonnen Erfahrung werde ich beim nächsten Projekt sicherlich mehr KI wagen.

Die ESP32-Cam App steht im Apple App Store, Google Play, snapcraft.io (Linux), Amazon App Store und im Microsoft Store zur Verfügung.

]]>
<![CDATA[Einfach ist anders...]]>Im letzten Monat hatte ich endlich die Muße meine private Spielerei, eine Flutter-App zum Lösen von stöchiometrischen Gleichungen auch für Google Play zu veröffentlichen. Die iOS-Version hatte ich schon im Frühjahr dieses Jahres in den Apple-Store eingebracht.

Apple

]]>
https://flutterdev.at/einfach-ist-anders/68ab38d997065d94ee4c9264Mon, 25 Aug 2025 11:24:39 GMT

Im letzten Monat hatte ich endlich die Muße meine private Spielerei, eine Flutter-App zum Lösen von stöchiometrischen Gleichungen auch für Google Play zu veröffentlichen. Die iOS-Version hatte ich schon im Frühjahr dieses Jahres in den Apple-Store eingebracht.

Apple App Store iOS und macOS-Version.
Google Play Store Android Version

Die in diesem Artikel beschriebene App als Flutter-Web-Version.



Die Veröffentlichung beider Apps in der Retrospektive betrachtet:

Damit die App im Apple-Store zur Verfügung gestellt wird, ist ein Entwickler-Account mit Kosten von 99$ pro Jahr von Nöten. Dies kann ich mir dank meines Brotberufes als Entwickler leisten. Aber für ein Hobby-Projekt sind diese Kosten schon ein gewichtiges Argument, das eher gegen das Publizieren einer App für iOS/macOS spricht.

Abgesehen von diesem pekuniären Wermutstropfen, ist das Publizieren der App problemlos über die Bühne gegangen. Nur die Veröffentlichung der macOS Version wurde im ersten Anlauf mit dem Grund, dass diese Debug-Informationen enthalte, nicht angenommen.

Einfach ist anders...

Als Debug-Information wurde die im About-Tab angezeigte Flutter-Version moniert. Meinen Einwand, dass eine Versions-Information keine Debug-Information sei, und dass dieses Detail bei der Einreichung der iOS-Version kein Hindernis war, wurde aber stattgegeben, und die macOS-Version ging online. Aber diese Erfahrung zeigt, je nach Prüfer wird eine eingereichte App sehr unterschiedlich beurteilt.

Die Veröffentlichung der Android Version hat sich deutlich schwieriger gestaltet. Zwar kostet ein Google Developer Account einmalig nur 25$, die Hürden über einen privaten Google Account eine App zu publizieren sind aber deutlich höher.

Der verpflichtende interne Vorabtest der App mit mindestens 20 Testern über 14 Tage ist bei solchen Nischen-App schon ein ziemlicher Mehraufwand. Mit Arbeitskollegen und Freundeskreis bekommt man diese Zahl schon zusammen. Aber man steht in der Bringschuld die App, deren Hintergrund und warum diese installieren werden soll, den Leuten näher zu bringen. Das hat einige E-Mails und erklärende Telefonate bedurft. Google begründet diesen Schritt, die Qualität einer App mit dieser Maßnahme zu steigern. Aber die Anzahl von 20 Testern ist meiner Meinung nach für kleine privates Projekt zu hoch gegriffen.

Nachdem diese Hürde umschifft war, ist die App zur endgültigen Begutachtung zwecks Veröffentlichung eingereicht worden. Die App wurde aber stante pede abgelehnt, da die App angeblich nur statischen Inhalt, und somit keinen Mehrwert bieten würde. ??? - scheinbar hat da eine KI oder ein Tester, ohne die App zu verstehen, diese einfach abgelehnt. Natürlich wurde Einspruch erhoben, dass die App nicht statisch sei, und sehr wohl ihren Zweck erfülle. Als Reaktion habe ich einige automatische E-Mails bekommen, die sich für meine Geduld bedanken und dass sich innerhalb von 14 Tagen ein Experte der Sache annehmen und meinen Einspruch beurteilen wird. Natürlich ist in dieser Frist nichts geschehen.

Also habe die App einfach noch einmal nach 14 Tagen ohne jegliche Änderung eingereicht - dieses Mal ist die App innerhalb von Stunden positiv geprüft und im App-Store veröffentlicht worden. Warum nicht gleich?

Da ich vorhabe weitere Flutter Apps zu veröffentlichen, habe ich einen geschäftlichen Google Developer Account angelegt, der nicht diesen verpflichtenden Vorabtests unterliegt. Dafür war aber ein Eintrag einer Firmenbuchnummer nötig, um an die von Google geforderte D-U-N-S Nummer zu kommen - inklusive Kosten und Rennereien zum Notar.

Und als ich erneut die 25$ für den geschäftlichen Account löhnen wollte, ist meine Kreditkarte nicht akzeptiert worden. Scheinbar wurde eine weitere Zahlung mit dieser Karte, dieses Mal für einen weiteren Account als verdächtig eingestuft. Wieder ein Ticket eröffnet, was denn das Problem mit meiner Kreditkarte sei. Das Problem wurde innerhalb von 2 Tagen gelöst, und ich konnte den Account bezahlen.

Ich kann mir aber einfach nicht helfen - Google und ich stehen irgendwie auf Kriegsfuß, oder einfach geht nichts...

]]>
<![CDATA[Flutter-Installation unter Arch-based CachyOs]]>Über folgenden Artikel in der Online-Ausgabe von heise.de bin ich auf CachyOS gestoßen, das den Ruf auf UI-Performance optimiert zu sein. Ich war so frei diese Distribution auf einer VM unter Proxmox im Rechenzentrum zu installieren. Selbst über den remote freigegebenen Bildschirm fühlt

]]>
https://flutterdev.at/flutter-installation-unter-arch-based-cachyos/6886430cbec2cee15cceb25eSun, 17 Aug 2025 15:33:55 GMT

Über folgenden Artikel in der Online-Ausgabe von heise.de bin ich auf CachyOS gestoßen, das den Ruf auf UI-Performance optimiert zu sein. Ich war so frei diese Distribution auf einer VM unter Proxmox im Rechenzentrum zu installieren. Selbst über den remote freigegebenen Bildschirm fühlt sich das UI dieser Distrbution flüssig an.

Als Flutter Entwickler wollte ich mein aktuelles Flutter Projekt als Desktop-App auf diesem System testen.

Die Flutter-Installation kann der offiziellen Dokumentation für Linux entnommen werden.

Nur die Installation der benötigten Tool-Chain für eine Linux-Desktop-App musste wie folgt an Arch-Linux angepasst werden.

sudo pacman -Syu ninja cmake glu xz  curl git unzip clang pkg-config
]]>
<![CDATA[I2C-Bus auf dem Banana Pi F3 aktivieren]]>English version

Langsam, aber doch drängen immer mehr SoCs auf Basis von der RISC-V-Architektur auf den Markt. Da Dart nun auch für RISC-V unterstützt wird, kam bei mir der Wunsch auf, ein RISC-V basiertes Board im Rahmen meines Projekts dart_periphery zu evaluieren.

Die

]]>
https://flutterdev.at/i2c-bus-auf-dem-banana-pi-bpi-f3-aktivieren/67aee03ef3219c443bad546cFri, 14 Feb 2025 20:09:01 GMT

English version

Langsam, aber doch drängen immer mehr SoCs auf Basis von der RISC-V-Architektur auf den Markt. Da Dart nun auch für RISC-V unterstützt wird, kam bei mir der Wunsch auf, ein RISC-V basiertes Board im Rahmen meines Projekts dart_periphery zu evaluieren.

Die Wahl fiel auf einen Banana Pi BPI-F3, der über Aliexpress direkt beim Hersteller SinoVoip Co., Limited bezogen wurde. Das Board, in einer schlichten Schachtel ohne jegliches Zubehör und Dokumentation verpackt, wurde innerhalb von knapp drei Wochen ohne Probleme geliefert.

Armbian wird für dieses Board als Rolling Release in Form einer Entwicklerversion unterstützt. Unter Armbian können Schnittstellen wie I2C, SPI etc. komfortabel mit dem Tool armbian-config verwaltet werden. Dieses Tool steht aber noch nicht für die aktuelle RISC-V-Version zur Verfügung.

Somit muss die I2C-Schnittstelle händisch eingebunden werden. Folgende Schritte wurden nun folgendem Beitrag aus dem Banana-Pi-Forum in angepasster Form entnommen. Root-Rechte sind vonnöten!

cd /boot/dtb/spacemit
cp k1-bananapi-f3.dtb k1-x_deb1.dtb.org
dtc -I dtb -O dts -o k1-bananapi-f3.dts k1-bananapi-f3.dtb
nano k1-bananapi-f3.dts 

Nun muss im I2C-4 Block der Status von disabled auf okay geändert werden...

    //i2c4
	i2c@d4012800 {
        .....
		status = "okay";
	};

...und dann die Änderungen am Device-Tree wieder zurückgeschieben werden.

 dtc -I dts -O dtb -o k1-bananapi-f3.dtb k1-bananapi-f3.dts

Nach einem Neustart und dem Laden des i2c-dev Modules sollte nun folgendes Device /dev/i2c-4 verfügbar sein.

modprobe i2c-dev
ls /dev/i2*
/dev/i2c-0  /dev/i2c-2  /dev/i2c-4  /dev/i2c-8

Nun wird das i2c-dev Modul der bestehenden Liste, der beim Start zu ladenden Modulen, hinzugefügt.

echo 'i2c-dev' >> /etc/modules-load.d/bananapif3.conf

Aber Achtung, ein OS Update, das bei dieser Rolling Release täglich per nightly build verfügbar ist, überschreibt folgende Dateien wieder.

/boot/dtb/spacemit/k1-bananapi-f3.dtb
/etc/modules-load.d/bananapif3.conf


Am Schluss wird das I2C-4 Device noch meinem Benutzer peter über eine Gruppe i2c zur Verfügung gestellt.

groupadd i2c
usermod -aG i2c peter
echo 'KERNEL=="/dev/i2c-4", GROUP="i2c", MODE="0660"' > /etc/udev/rules.d/99-i2c.rules
apt-get install i2c-tools
reboot

Nach dem Reboot logge ich mich mit meinem Benutzer peter an lasse mir alle Geräte auf dem Bus I2C-4 anzeigen.

peter@bananapif3:~$ i2cdetect -y -r 4
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

An der Adresse 0x68 des I2C-Busses hängt eine DS3231 Real-Time-Clock, die nun mit Hilfe von dart_periphery angesteuert wird. Der Beispiel-Code wird noch an die I2C-Bus-Nummer 4, und dass ein DS3231 mit Temperatursensor in Verwendung ist, angepasst.

void main() {
  // Select the right I2C bus number /dev/i2c-?
  // 1 for Raspberry Pi, 0 for NanoPi (Armbian), 2 Banana Pi (Armbian)
  var i2c = I2C(4); // Banana Pi BPI-F3
  try {
    print("dart_periphery Version: $dartPeripheryVersion");
    print("c-periphery Version   : ${getCperipheryVersion()}");
    print('I2C info: ${i2c.getI2Cinfo()}');
    print("DS1307 real time clock");

    var rtc = DS1307(i2c,true); // for DS3231 set DS1307(i2c, true)

Beispiel starten

peter@bananapif3:~/dart_periphery/example$ dart i2c_ds1307.dart

Bildschirmausgabe

dart_periphery Version: 0.9.15
c-periphery Version   : v2.4.2
I2C info: I2C (fd=9)
DS1307 real time clock
Get current RTC date and time
2025-02-14 18:43:50.000
RTC on board temperature sensor: 24.75
Set RTC to current sytem time?
Do you want to continue? (yes/no): 
]]>
<![CDATA[Flutter und Android Studio Ladybug]]>https://flutterdev.at/flutter-und-android-studio-ladybug/671724872308c703411204baTue, 22 Oct 2024 04:49:57 GMT

Mit der Version Android Studio Ladybug und Flutter 3.24.3 kommt es zu Fehlermeldungen beim Compilieren des Android-Ports des Flutter Projekts auf Grund des Wechsels des Java-JDKs von 17 auf 21.

flutter doctor -v
...
[✓] Android Studio (version 2024.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.3+-79915917-b509.11)

Die Fehlermeldungen monierten meistens das Flutter-Plugins auf Grund des JDK-Wechsels nicht übersetzt werden können:

Execution failed for task ':connectivity_plus:compileReleaseJavaWithJavac'.
> Could not resolve all files for configuration ':connectivity_plus:androidJdkImage'.

Hier findet sich eine detailierte Beschreibung wie dieses Problem behoben werden kann. Die einzelnen Schritte hier kurz zusammengefasst:

Java-Version in android/app/build.gradle von 8 auf 17 anpassen:

compileOptions {
      sourceCompatibility JavaVersion.VERSION_17
      targetCompatibility JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_17
    }

Dann die Gradle-Version android/gradle/wrapper/gradle-wrapper.properties anpassen:

distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip

Die Relation von der Gradle und der JDK Version kann dieser Matrix entnommen werden.

Am Schluss wird noch folgender Eintrag android/settings.gradle angepasst:

  id "com.android.application" version "8.3.1" apply false

Fehlermeldungen bezüglich des NDKs können scheinbar ignoriert werden. Diese Art von Fix wird aber wahrscheinlich nur bis zur nächsten Flutter-Version von Nöten sein.


]]>
<![CDATA[gitlab und rinetd - Verbindungsprobleme]]>https://flutterdev.at/gitlab-und-rinetd-verbindungsprobleme/671685912308c7034112043eMon, 21 Oct 2024 18:42:19 GMT

Seit Jahren verwende ich den Linux-Dienst rinetd auf meinem Proxmox-Server, um den Port 22 unkompliziert an einen LXC mit einer gitlab-Instanz durchzureichen. Diese Kombination hat bis vor einiger Zeit klaglos funktioniert, bis rinetd ständig derart hängen blieb, dass git remote keine Verbindung mehr zur der gitlab-Instanz aufbauen konnte.

Erst ein Neustart des rinetd-Services behob das Problem. Aber auch nicht wirklich, einige Stunden später stellte sich das gleiche Problem wieder ein. Scheinbar hat sich bei gitlab über die vielen Updates auf die jeweils neueste Version ein diffiziles Problem eingeschlichen.

Um das Problem einzugrenzen, habe ich die Port-Durchreichung testweise mit

socat -T30 TCP4-LISTEN:22,bind=<PUBLIC_IP>,fork TCP4:192.168.10.103:22

realisiert. Aber auch socat zeigte nach einiger Zeit das gleiche Verhalten in Kombination mit gitlab. Erst mit der Ergänzung des Kommandos um ein explizites Timeout von 30 Sekunden schuf dieses lästige Problem aus der Welt.

Da rinetd ebenfalls mit einer Timeout-Option konfiguriert werden kann, konnte dieser Trick auch dort angewendet werden, um das Problem endgültig zu beheben.

# rinetd 
<PUBLIC_IP>      22    192.168.10.103        22  [timeout=30]

]]>
<![CDATA[flutter_pi_sensor_tester]]>Dieses neue Projekt hat das Ziel für dart_periphery die fehlende Unterstützung von Nebenläufigkeit, die in der Dart/Flutter-Welt mit Hilfe von isolates realisiert wird, nachzureichen.

Messungen von Sensoren, wie zum Beispiel einem BME680, einem kombinierten Sensor für Temperatur, Luftdruck, Luftfeuchtigkeit und

]]>
https://flutterdev.at/flutter-pi-sensor-tester/66a62ce20b7969042592f449Sun, 28 Jul 2024 13:44:35 GMT

Dieses neue Projekt hat das Ziel für dart_periphery die fehlende Unterstützung von Nebenläufigkeit, die in der Dart/Flutter-Welt mit Hilfe von isolates realisiert wird, nachzureichen.

Messungen von Sensoren, wie zum Beispiel einem BME680, einem kombinierten Sensor für Temperatur, Luftdruck, Luftfeuchtigkeit und Luftqualität finden in einem isolate satt. Stehen Messwerte zur Verfügung, so werden diese per Daten-Stream an das Flutter-UI durchgereicht. Die Kommunikation zwischen dem Haupt-Isolate, der Applikation selbst, und den gestarten Isolates ist eingeschränkt bidirektional.

flutter_pi_sensor_tester
Raspberry Pi 3 Testaufbau

Auf dem Bild sieht man die Led-Demo mit folgendem Aufbau: ein Raspberry Pi 3, ein kleiner Touch-Screen und drei farbige Leds. Durch Drücken der Led-Symbole auf dem Bildschirm können die Leds ein- und ausgeschaltet werden.

Das Flutter auf einem Raspberry Pi überhaupt möglich ist, verdanken wir dem großartigen Projekt flutter-pi von Hans Winkler.

Die einzelnen UI-Elemente können am Bildschirm umgruppiert werden.

0:00
/0:10

Video-Snippet - Umgruppieren von UI-Elementen

]]>
<![CDATA[flutterpi_tool und macOS]]>In einem älteren Artikel, inzwischen korrigiert, schrieb ich, dass flutterpi_tool, sein Linux only Tool sei. Nachdem mir diese Fehlannahme bewußt wurde, habe ich die .zshrc auf meinem Mac um ein alias ergänzt, dass folgende Befehle aufruft:

# call alias inside the flutter project directory
flutterpi_
]]>
https://flutterdev.at/flutterpi_tool/65efd4865435a32ff91c491aTue, 12 Mar 2024 05:45:29 GMT

In einem älteren Artikel, inzwischen korrigiert, schrieb ich, dass flutterpi_tool, sein Linux only Tool sei. Nachdem mir diese Fehlannahme bewußt wurde, habe ich die .zshrc auf meinem Mac um ein alias ergänzt, dass folgende Befehle aufruft:

# call alias inside the flutter project directory
flutterpi_tool build --arch=arm --cpu=pi3 --release

# sync asset data to the pi
rsync -a ./build/flutter_assets/ pi@raspberry:/home/pi/my_apps_flutter_assets
  
# start flutter-pi remote
ssh pi@raspberry "flutter-pi --release /home/pi/my_apps_flutter_assets"

Alias-Definition:

alias flutter-pi="flutterpi_tool build --arch=arm --cpu=pi3 --release && rsync -a ./build/flutter_assets/ pi@raspberry:/home/pi/my_apps_flutter_assets && ssh pi@raspberry \"flutter-pi --release /home/pi/my_apps_flutter_assets\""

Um sich das Leben zu vereinfachen und nicht ständig das Passwort des Raspberry Pis eingeben zu müssen, wurde der entsprechende SSH-Schlüssel auf dem Pi hinterlegt.

Mit diesem alias war es dann ein Einfaches diese nette Seil-Simulation auf einem Raspberry Pi 3 mit angeschlossenem UPERFECT 7 Zoll Portable Monitor mit einem Befehö zum Laufen zu bekommen.

0:00
/0:16

]]>
<![CDATA[flutter (snap) in einem LXC installieren]]>https://flutterdev.at/flutter-unter-linux-installieren/65ebf9815435a32ff91c4898Sat, 09 Mar 2024 06:59:29 GMT

Dieser Artikel ist als Ergänzung zu einem älteren Eintrag von mir gedacht. Wenn man ohne großen Aufwand flutter unter Linux installieren will, dann ist die Linux Distribution Ubuntu wahrscheinlich die erste Wahl, da snap die Installation von Flutter deutlich vereinfacht.

Um die neueste Flutter-Version und das neue Plugin flutterpi_tool unter Linux zu testen, habe ich auf meinem Proxmox-Server einen LXC mit Ubuntu 23 angelegt, um dann in diesem Container mit einer Zeile flutter zu installieren.

sudo snap install snapd
sudo snap install flutter --classic

Dieses Unterfangen scheiterte aber sogleich an der Tatsache, dass die LXC-Variante von Ubuntu keinen FUSE-Support bietet.

Aber etwas im Internet gesucht, konnte auch für dieses Problem eine Abhilfe gefunden werden:

Den FUSE-Support im LXC nachrüsten und die Konfiguration des LXC auf dem Proxmox-Host entsprechend anpassen.

sudo apt update && sudo apt dist-upgrade
sudo apt install squashfuse fuse
sudo apt install snapd
sudo mkdir /lib/modules

/etc/pve/lxc/<CTID>.conf

# Mounting fuse (for snap squashfs)
lxc.mount.entry = /dev/fuse dev/fuse none bind,create=file,optional

# Mount cgroup in rw to get snaps working
lxc.mount.auto=cgroup:rw
]]>
<![CDATA[The following signatures were invalid: EXPKEYSIG 3F01618A51312F3F GitLab B.V]]>https://flutterdev.at/the-following-signatures-were-invalid-expkeysig-3f01618a51312f3f-gitlab-b-v/65e9dc575435a32ff91c481bThu, 07 Mar 2024 16:17:26 GMT

Mit Anfang März 2024 konnte ich die VMs, der von mir betreuten virtualisierten GitLab Instanzen nicht mehr updaten, da der Update-Befehl

apt-get update

mit folgendem Fehler endete.

The following signatures were invalid: EXPKEYSIG 3F01618A51312F3F GitLab B.V...

Dieser Fehler war verwunderlich, da der gpg Key für das GitLab repository bezüglich der Gültigkeit nicht abgelaufen war.

Im Internet findet man zu diesem Fehler den Tipp, dass man den gpg Key wie folgt updaten möge.

apt-key del 3F01618A51312F3F
curl -s "https://packages.gitlab.com/gpg.key" | apt-key add -
apt-key list 3F01618A51312F3F

Dies hat aber das aktuelle Signaturproblem nicht behoben.

Nach längerem Suchen bin ich dann bei folgender Dokumentation, von GitLab selbst verfasst fündig geworden.

Das folgende Kommando

grep 'deb \[signed-by=' /etc/apt/sources.list.d/gitlab_gitlab-?e.list

hat dann angezeigt, dass der signed-by Mechanismus für die Updates relevant ist. Folgender Update-Befehl hat dann das Problem wirklich gelöst

awk '/deb \[signed-by=/{
       pubkey = $2;
       sub(/\[signed-by=/, "", pubkey);
       sub(/\]$/, "", pubkey);
       print pubkey
     }' /etc/apt/sources.list.d/gitlab_gitlab-?e.list | \
   while read line; do
     curl -s "https://packages.gitlab.com/gpg.key" | gpg --dearmor > $line
   done

The following signatures were invalid: EXPKEYSIG 3F01618A51312F3F GitLab B.V
]]>
<![CDATA[Stöchiometrie-Flutter-App]]>https://flutterdev.at/stoechiometrie/64c0d8d9d1f8d80169977f96Tue, 08 Aug 2023 06:52:44 GMT

In diesem Post geht es um die Portierung eines Stöchiometrie-Servlets, das ich vor gefühlten Ewigkeiten entwickelt hatte, nach Flutter. Die Erkenntnisse, die ich aus dieser Umsetzung gezogen habe, sind folgende:

  • Flutter ist eine mächtige Entwicklungsumgebung, die fast keine Wünsche offenlässt. Bei diesem Projekt waren es eher die Kleinigkeiten, die einiges an Aufwand, hauptsächlich in der UI-Umsetzung, nach sich gezogen haben.
  • Die Verwendung des Flutter WebView Plugins für die Darstellung der Formeln und der Texte wurde als ein overkill erachtet. Zielsetzung war es eine kleine App zu schreiben, die möglichst wenige Plugins involviert. Die Konsequenz aus dieser selbst auferlegten Restriktion führte schlussendlich zu der Entwicklung einer eigen einfachen Seitenbeschreibungssprache, die die Texte alleinig mit Hilfe des Widegts RichText darstellt.
  • Eigentlich wollte ich die Subindizes der chemischen Formeln, wie z.B. HNO₃ mit Unicode-Zeichen bestreiten. Nur ist es so, die meisten Monospace-Zeichensätze bieten nur die Ziffern 1-4 tiefergestellt an. Das Problem wurde mit der vorher erwähnten eigenen Auszeichunssprache gelöst.

Vollfunktionsfähige Flutter-Web-App per iframe eingebunden:

]]>
<![CDATA[Linux uname() per FFI in dart/flutter einbinden]]>https://flutterdev.at/uname/622de5450d9bc32c0ad0fe30Sun, 29 May 2022 17:11:48 GMT

Mit Pi OS 64 wurde das Paket system_info, das in meinem Projekt dart_periphery die CPU Archtitektur des SoC bestimmt hat, dysfunktional. system_info hat für die Bestimmung der CPU Architektur die relevanten Elemente des Device-Tree /proc/cpuinfo ausgelesen. Im Gegensatz zur 32-Bit Version liefert aber die 64-Bit Version des Device-Trees diese benötige Information nicht mehr zurück. Abgesehen von diesem technischen Problem, hat das Paket den Status discontinued erlangt. Als Ersatz wurde daher folgender Dart-Code entwickelt, der die CPU Architektur unter Linux per Aufruf von uname() per FFI ermittelt.

import 'dart:ffi'; // For FFI
import 'package:ffi/ffi.dart';

typedef NativeCall = int Function(Pointer);

/// Supported CPU architectures
enum CPU_ARCHITECTURE { x86, x86_64, arm, arm64, notSupported, undefinded }

final DynamicLibrary nativeAddLib = DynamicLibrary.open("libc.so.6");
NativeCall uname = nativeAddLib
    .lookup)>>("uname")
    .asFunction();

/// Class which holds the CPU architecture of the SoC.
/// Supported uname values provided by https://en.wikipedia.org/wiki/Uname 
class CpuArch {
  static CpuArch? _cpuArch;
  String machine;
  CPU_ARCHITECTURE cpuArch;

  factory CpuArch() {
    _cpuArch ??= CpuArch._internal();
    return _cpuArch as CpuArch;
  }

  CpuArch._internal()
      : machine = "",
        cpuArch = CPU_ARCHITECTURE.notSupported {
    Uname uname = nativeUname();
    machine = uname.machine;
    switch (uname.machine) {
      case 'i686':
      case 'i386':
        cpuArch = CPU_ARCHITECTURE.x86;
        break;
      case 'x86_64':
        cpuArch = CPU_ARCHITECTURE.x86_64;
        break;
      case 'aarch64':
      case 'aarch64_be':
      case 'arm64':
      case 'armv8b':
      case 'armv8l':
        cpuArch = CPU_ARCHITECTURE.arm64;
        break;
      case 'armv':
      case 'armv6l':
      case 'armv7l':
        cpuArch = CPU_ARCHITECTURE.arm;
        break;
    }
  }
}

/// Uname class, container for the Linux uname struct values.
class Uname {
  String sysname;
  String nodename;
  String release;
  String version;
  String machine;
  Uname(this.sysname, this.nodename, this.release, this.version, this.machine);
}

/// Calls the native uname() function.
Uname nativeUname() {
  // allocate a memory buffer for struct utsname - size value derived from this source
  // https://man7.org/linux/man-pages/man2/uname.2.html
  const len = 6 * 257; // maxium size
  const enumElements = 5;

  Pointer data = calloc(len);

  try {
    if (uname(data) != 0) {
      throw Exception('Calling uname() failed.');
    }

    // calculate _UTSNAME_LENGTH
    var utslen = 0;
    label:
    for (int i = 0; i < len; ++i) {
      if (data[i] == 0) {
        for (int j = i + 1; j < len; ++j) {
          if (data[j] != 0) {
            utslen = j;
            break label;
          }
        }
      }
    }

    var values = [];

    // extract these 5 strings from the memory
    //
    // char sysname[];    /* Operating system name (e.g., "Linux") */
    // char nodename[];   /* Name within "some implementation-defined network" */
    // char release[];    /* Operating system release (e.g., "2.6.28") */
    // char version[];    /* Operating system version */
    // char machine[];    /* Hardware identifier */
    for (int i = 0; i < enumElements; ++i) {
      var start = utslen * i;
      StringBuffer buf = StringBuffer();
      for (int i = start; i < len; ++i) {
        if (data[i] == 0) {
          break;
        }
        buf.write(String.fromCharCode(data[i]));
      }
      values.add(buf.toString());
    }
    return Uname(values[0], values[1], values[2], values[3], values[4]);
  } finally {
    malloc.free(data);
  }
}

]]>
<![CDATA[dart_periphery]]>https://flutterdev.at/dart_periphery/61b1d7c4b22cb44767e6cef1Fri, 07 Jan 2022 15:07:43 GMT
dart_periphery | Dart Package
dart_periphery is a Dart port of the native c-periphery library for Linux Peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO and Serial peripheral I/O).
dart_periphery
dart_periphery

... war mein erstes größeres Dart-Projekt auf pub.dev, die Portierung der Bibliothek c-periphery nach Dart.

GitHub - vsergeev/c-periphery: A C library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.
A C library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux. - GitHub - vsergeev/c-periphery: A C library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.
dart_periphery

c-periphery ist eine Linux C-Bibliothek für den userpace zur Ansteuerung der diversen I/O-Schnittstellen: GPIO, LED, PWM, SPI, I2C, MMIO und Serielle.

Die Entstehungsgeschichte dieses Projekts hat ursprünglich mit einer CO2-Ampel für den Raspberry Pi in Java implementiert mit einem SGP30-CO2-Sensor, Leds für die Ampelschaltung und einem 4,2″ e-Paper aus Ausgabegerät begonnen. Den Zweck erfüllte dieses kleine Projekt, aber das Gefühl, dass die Umsetzung vom technischen Standpunkt etwas umständlich war, begleitete mich von Anfang an.

  • die GPIO-Anbindung der Leds für die Ampel wurde mit JNI/wiringpi umgesetzt.
  • der SGP30-Sensor wurde mit der Kombination JNI/Sensirion C-Bibliothek eingebunden.
  • das 4,2″ e-Paper von waveshare wurde per C-Bibliothek des Herstellers per JNI angesteuert.

Gezählte dreimal war der der Einsatz von JNI (Java Native Interface) von Nöten, um die gewünschte Hardware einzubinden.

Jetzt könnte der einer oder andere Leser überhaupt die Frage stellen, warum nicht Python die bevorzugte Sprache für Hardwarebastelein am Raspberry Pi zum Einsatz kam. Diese Entscheidung ist einfach meiner beruflichen Ausrichtung, die eines Java-Entwicklers geschuldet. Für Projekte in meiner Freizeit möchte ich nicht noch eine weitere Programmiersprache bemühen müssen. Meiner bescheidenen Meinung nach können Java und Python als gleichwertige Programmiersprachen betrachtet werden, mit der Einschränkung, dass sicherlich die eine oder andere Aufgabenstellungen von der jeweiligen Programmiersprache einfacher gelöst werden kann.

Das Einbinden von Hardware per C/C++ in die jeweilige Programmiersprache ist in meisten Fällen etwas fummelig, speziell unter JNI per javah automatisch erzeugte C/C++-Header-Dateien sind auf Grund der Überlänge eine mögliche Fehlerquelle.

/*
 * Class:     at_treedb_hardware_RaspberryPiBase
 * Method:    _i2c_readByte
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_at_treedb_hardware_RaspberryPiBase__1i2c_1readByte__I
  (JNIEnv *, jobject, jint);

/*
 * Class:     at_treedb_hardware_RaspberryPiBase
 * Method:    _i2c_readByte
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_at_treedb_hardware_RaspberryPiBase__1i2c_1readByte__II
  (JNIEnv *, jobject, jint, jint);

In der Nachbetrachtung des Projekts wurde ich dann durch längere Rechere auf folgende Projekte aufmerksam: Die am Anfang des Postings erwähnte c-periphery Bibliothek und das Projekt diozero,

diozero/diozero-core/src/main/java/com/diozero/devices at main · mattjlewis/diozero
Java Device I/O library that is portable across Single Board Computers. Tested with Raspberry Pi, Odroid C2, BeagleBone Black, Next Thing CHIP, Asus Tinker Board and Arduinos. Supports GPIO, I2C, S...
dart_periphery

ein umfangreiches Java-Projekt, das für etliche Sensoren und Peripheriegeräte wertvolle Implementierungen liefert. Übersichtlicher Code, egal in welcher Programmiersprache, ist einfach Gold wert.

Zeitgleich zu diesem Hardwareprojekt war ich damit beschäftigt meine Flutter-Kenntnisse zu verbessern, und folgendes Projekt, flutter-pi,

GitHub - ardera/flutter-pi: A light-weight Flutter Engine Embedder for Raspberry Pi that runs without X.
A light-weight Flutter Engine Embedder for Raspberry Pi that runs without X. - GitHub - ardera/flutter-pi: A light-weight Flutter Engine Embedder for Raspberry Pi that runs without X.
dart_periphery

war mir schon länger bekannt. flutter-pi ermöglicht es auf einem Raspberry Pi eine Flutter-Applikation auszuführen. Die verschienden Handlungstränge liesen in mir die Idee aufkommen die C02-Ampel mit einem moderen Userinterface, Flutter, neu zu implementieren. Was noch fehlte war ein entsprechner Dart-Port von c-periphery und die Portierung des SGP30-Sensor-Java-Codes nach Dart.

import 'package:dart_periphery/dart_periphery.dart';
import 'dart:io';

// https://wiki.seeedstudio.com/Grove-VOC_and_eCO2_Gas_Sensor-SGP30/
// The Grove-VOC and eCO2 Gas Sensor(SGP30) is an air quality detection sensor based on the SGP30 chip.
void main() {
  // Select the right I2C bus number /dev/i2c-?
  // 1 for Raspbery Pi, 0 for NanoPi (Armbian), 2 Banana Pi (Armbian)
  var s = SGP30(I2C(1));
  print('Serial number: ${s.getSerialId()}');
  print(s.getFeatureSetVersion());
  sleep(Duration(milliseconds: 1000));
  var count = 0;
  while (true) {
    s.measureIaq();
    print(s.measureRaw());
    sleep(Duration(milliseconds: 1000));
    ++count;
    if (count == 30) {
      count = 0;
      print(s.measureIaq());
    }
  }
}

In der nächsten Zeit werde ich ein Posting zum Projekt CO2-Ampel basierend auf flutter-pi und dart_periphery verfassen.

]]>