171 lines
6.5 KiB
Markdown
Raw Normal View History

2024-03-22 01:37:32 +01:00
## Einstellungen Feature {#headerSettingsFeature}
Das Einstellungen Feature zeigt auf der Startseite eine Liste an Optionen,
die der Benutzer konfigurieren kann. Dazu gehören visuelle Einstellungen,
wie das Aktivieren des Dark Modes, die Möglichkeit vom Material 3 Design
zum Material 2 Design zu wechseln, eine Auswahl an Farben für den ColorSeed
der App und das Anzeigen des eingebauten Performance Overlays von Flutter.
Ansonsten gibt es nur die Möglichkeit, das WLAN zu konfigurieren (siehe Abbildung \ref{settings}).
Der aktivierte Dark Mode und die Farbauswahl können in Abbildung \ref{settingsDark} betrachtet
werden. Alle visuellen Einstellungen werden mit von Riverpod generierten Providern
angesprochen und alle Einstellungen außer dem "Performance Overlay" nutzen dabei die
SharedPreferences, um die Einstellungen zu speichern. Im Test gab es dabei in der
finalen Version mit Yocto Linux manchmal das Problem, dass die SharedPreferences
nicht richtig gespeichert werden. Erst kam die Vermutung auf, dass der Nutzer
keine Schreibrechte auf das Verzeichnis von SharedPreferences hat, doch nach
einem oder auch zwei Neustarts funktioniert das Speichern der Einstellungen
problemlos. Der genaue Fehler konnte also nicht gefunden werden, da es keine
Fehlermeldungen gab und es ein merkwürdiges Verhalten aufweist, da der Nutzer
nicht plötzlich Schreibrechte auf das Verzeichnis bekommen kann, das Problem
sich aber nach mehreren Neustarts "von selbst" löst.
Im Falle von Flutter-Pi werden die Einstellung in der Datei
_~/.local/share/flutter-pi/shared_preferences.json_ gespeichert, diese
kann manuell bearbeitet werden und auch zum Vorkonfigurieren von
Einstellungen genutzt werden.
\pagebreak
\Begin{multicols}{2}
\begin{figure}[H]
\caption{Startseite der Einstellungen}
\label{settings}
\centering
{\shadowimage[width=7cm]{./assets/screenshots/settings.png}}
\end{figure}
\begin{figure}[H]
\caption{Einstellungen mit aktiviertem Dark Mode und Farbauswahl}
\label{settingsDark}
\centering
{\shadowimage[width=7cm]{./assets/screenshots/settingsDark.png}}
\end{figure}
\End{multicols}
Die WLAN-Einstellungen sind in einer eigenen Ansicht untergebracht in der
eine Liste an verfügbaren WLAN-Netzwerken angezeigt wird (siehe Abbildung \ref{settingsWifiList}).
Wählt der Benutzer ein Netzwerk aus, so werden die Details des Netzwerks
in einem Dialogfenster im Vollbildmodus angezeigt (siehe Abbildung \ref{settingsWifiDetails}).
Von da aus kann der Benutzer sich mit dem Netzwerk verbinden und kann
falls nötig ein Passwort eingeben. Die Eingabe des Passworts geschieht wie
auch beim Morsecode Feature in einem eigenen Fenster mit der Tastatur.
\begin{multicols}{2}
\begin{figure}[H]
\caption{WLAN Netzwerke Liste}
\label{settingsWifiList}
\centering
{\shadowimage[width=7cm]{./assets/screenshots/settingsWifiList.png}}
\end{figure}
\begin{figure}[H]
\caption{WLAN Netzwerk Details}
\label{settingsWifiDetails}
\centering
{\shadowimage[width=7cm]{./assets/screenshots/settingsWifiDetails.png}}
\end{figure}
\end{multicols}
In der Implementierung wird das Paket _nm_ genutzt, welches von
Canonical, dem Unternehmen hinter der weltbekannten Linux Distribution Ubuntu, entwickelt wurde.
Dieses Paket bietet eine Schnittstelle zum NetworkManager, welcher
das Netzwerkmanagement unter Linux übernimmt. Diese Schnittstelle
wird über die D-Bus API vom NetworkManager angesprochen, dazu
wird das Paket _dbus_ genutzt, welches auch von Canonical entwickelt wurde.
Canonical gibt hiermit auch eine Beispielimplementierung in Dart, die
zeigt wie man eine DBUS-Schnittstelle in Dart implementiert.
Das nm Paket ist unter GitHub verfügbar [@CanonicalNmDart2023].
In der Geschäftslogikschicht wurde zur Ansteuerung des nm Pakets
ein eigener Controller _WifiController_ implementiert, der die
Funktionalität des nm Pakets kapselt. In dem Controller sind
Funktionen wie _disconnectFromWifiNetwork_ und _connectToWifiNetwork_
implementiert und es kann ein _wifiStream_ abonniert werden, der
den aktuellen Status des WLANs zusammen mit verfügbaren WLAN Netzwerken zurückgibt.
Der Stream nutzt hierzu das neue Records Feature von Dart, welches
seit Version 3.0 verfügbar ist [@googleinc.Records]. Records funktionieren technisch ähnlich zu
klassischen Tuplen und werden im Stream genutzt, um Objekte der Klassen _NetworkManagerDevice_
und _NetworkManagerClient_ zusammen zu übergeben. Auflistung \ref{wifiStream}
zeigt den Ausschnitt des _WifiController_ mit dem _wifiStream_.
Die Implementierung des WifiControllers ist nur sehr rudimentär und
deckt nur die nötigsten Funktionen ab, um auf dem Raspberry Pi
sich mit einem WLAN Netzwerk zu verbinden. Das Abspeichern der
Verbindung wird von dem NetworkManager selbst übernommen und es
funktioniert in der Applikation problemlos.
```{.java .number-lines caption="Auszug aus dem WifiController mit dem wifiStream" captionpos=t label=wifiStream}
@riverpod
class WifiController extends _$WifiController {
...
NetworkManagerDevice get _device => state.value!.devices
.firstWhere((d) => d.deviceType == NetworkManagerDeviceType.wifi);
Stream<(NetworkManagerDevice, NetworkManagerClient)> wifiStream() {
return Stream.periodic(const Duration(milliseconds: 100), (_) {
return (_device, state.value!);
});
}
...
}
```
Dieser WifiController wird auch für den Status des WLANs in der
Statusleiste genutzt, um den aktuellen Status des WLANs anzuzeigen.
<!-- \begin{multicols}{2}
\begin{figure}[H]
\caption{Home Screen}
\centering
{\shadowimage[width=7cm]{./assets/screenshots/settingsWifiConnect.png}}
\label{fig:screeplot}
\end{figure}
\begin{figure}[H]
\caption{Home Screen}
\centering
{\shadowimage[width=7cm]{./assets/screenshots/settingsMaterial2.png}}
\label{fig:screeplot}
\end{figure}
\end{multicols} -->
<!-- \pagebreak
\lstinputlisting[language=Java, caption=Implementierung des Wifi Controllers, captionpos=t]
{code/flutter_elinux/lib/features/settings/business/wifi_controller.dart} -->
<!-- \begin{figure}[H]
\caption{Example caption}
\centering
\begin{minipage}{7cm}
\dirtree{%
.1 settings/.
.2 business/.
.3 wifi\char`\_controller.dart.
.2 presentation/.
.3 settings\char`\_screen/.
.4 widgets/.
.5 color\char`\_seed\char`\_button.dart.
.4 settings\char`\_screen.dart.
.3 wifi\char`\_settings\char`\_screen/.
.4 widgets/.
.5 ap\char`\_pw\char`\_dialog.dart.
.5 ap\char`\_tile\char`\_demo.dart.
.5 ap\char`\_tile.dart.
.5 wifi\char`\_bar\char`\_icon.dart.
.4 accesspoint\char`\_screen.dart.
.4 wifi\char`\_settings\char`\_screen.dart.
}
\end{minipage}
\end{figure} -->
# Erstellung der Yocto-Distribution {#yoctoChapter}