diff --git a/README.md b/README.md index 0c5661dc7825ea979fcd049b3dddd34424eb7661..d65bc9a38ca3a45bdf27843a844fbd153bd0b72d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,10 @@ With this software, you can controlle DMX fixture via Art-Net ## Project status Sofwtare: DONE -Documentation: WORK IN PROGRESS +Documentation: DONE + +## Issues +#1 Light control unit crashes if there are too many Art-Net packages ## Author Sebastian Böttger diff --git "a/doc/projectDocumentation/Abk\303\274rzungen.tex" "b/doc/projectDocumentation/Abk\303\274rzungen.tex" new file mode 100644 index 0000000000000000000000000000000000000000..c2ea37a384e3d39434c27ddcb13dfffb263de633 --- /dev/null +++ "b/doc/projectDocumentation/Abk\303\274rzungen.tex" @@ -0,0 +1,15 @@ +\acro{acn}[ACN]{Architecture for Control Networks} +\acro{app}[App]{Applikation} +\acro{csa}[CSA]{Connectivity Standards Alliance} +\acro{dmx}[DMX]{Digital Multiplex} +\acro{eeprom}[EEPROM]{Electrically Erasable Programmable Read-Only Memory} +\acro{erp}[ERP]{Enterprise-Resource-Planning} +\acro{esta}[ESTA]{Entertainment Services and Technology Association} +\acro{ifa}[IFA]{Internationale Funkausstellung} +\acro{kiwi}[KIWI]{\textbf{K}IWI~(is~an)~\textbf{I}llumination~\textbf{W}eeny~\textbf{I}nterface} +\acro{lan}[LAN]{Local Area Network} +\acro{led}[LED]{Light Emitting Diode} +\acro{sacn}[sACN]{streaming Architecture for Control Networks} +\acro{udp}[UDP]{User Datagram Protocol} +\acro{usb}[USB]{Universal Serial Bus} +\acro{wlan}[WLAN]{Wireless Local Area Network} \ No newline at end of file diff --git a/doc/projectDocumentation/Abstract.tex b/doc/projectDocumentation/Abstract.tex new file mode 100644 index 0000000000000000000000000000000000000000..6fba42cdc25135b2f0a715b4ee74f5e644a097be --- /dev/null +++ b/doc/projectDocumentation/Abstract.tex @@ -0,0 +1,9 @@ +Diese Ausarbeitung befasst sich mit der Beleuchtung im Heimbereich und ihre Steuerung, die gemeinsam als Heimilluminationssystem bezeichnet werden. +Das Heimilluminationssystem besteht aus einer lokalen Lichtsteuereinheit, welche \acs{dmx}-fähige Lampen über \acs{dmx} ansteuert und einer Lichtsteuersoftware, mit dieser Kommuniziert.\par +Es wird dargestellt, dass eine netzwerkbasierte Kommunikation zwischen der Lichtsteuersoftware und der Lichtsteuereinheit vorteilhaft ist. +Diese ermöglicht eine Ortsunabhängigkeit zwischen den beiden Komponenten und die gleichzeitige Nutzung von mehreren Lichtsteuereinheiten an unterschiedlichen Orten. +Die Ausarbeitung erläutert, warum Art-Net ein geeignetes Netzwerkprotokoll für diesen Anwendungsfall ist.\par +Sie beschreibt, wie das Art-Net-Protokoll in die lokale Lichtsteuereinheit und in die Lichtsteuersoftware integriert werden kann. +Darüber hinaus erläutert die Arbeit die Konzepte hinter der Gestaltung der Benutzeroberfläche und zeigt, wie der Softwarekern der Lichtsteuersoftware mit Hilfe des Model-View-ViewModel-Entwurfsmuster mit der Benutzeroberfläche verbunden ist.\breath + +Abschließend werden die aktuellen Herausforderungen durch einen Leistungsengpass der Lichtsteuereinheit beim Verarbeiten von Art-Net-Paketen und fehlerhafte Animationen und Listenaktualisierungen in der Benutzerstelle beschrieben. \ No newline at end of file diff --git a/doc/projectDocumentation/Aktuelle_Herausforderungen.tex b/doc/projectDocumentation/Aktuelle_Herausforderungen.tex new file mode 100644 index 0000000000000000000000000000000000000000..0efb458c17f508aea6a3cc776c8792ce28fee438 --- /dev/null +++ b/doc/projectDocumentation/Aktuelle_Herausforderungen.tex @@ -0,0 +1,60 @@ +Zum Zeitpunkt der Verfassung dieser Arbeit bestehen zwei Probleme in der aktuellen Konfiguration des Systems. +Zum einen stürzt die lokale Lichtsteuereinheit bei zu hoher Belastung durch Netzwerkpakete ab und zum anderen sind manche Animationen und Listen bei Aktualisierung der Benutzerschnittstelle fehlerhaft. + +\subsection{Leistungsengpass der Lichtsteuereinheit} +\label{sec_Leistungsenpass_Lichtsteuereinheit} +Beim Dauerbetrieb der lokalen Lichtsteuereinheit ist aufgefallen, dass bei einer zu hohen Paketlast der Mikrocontroller abstürzt oder falsche Befehle ausführt. +Nach aktuellen Erkenntnissen ist dies auf eine Art von fehlerhaften Speicherzugriffen oder überlaufendem Speicher zurückzuführen. +In durchgeführten Tests, bei denen alle Paket-Typen einzeln versendet wurden, konnte ein fehlerfreies Verhalten nachgewiesen werden. +Alle Befehle werden korrekt erkannt und im erwarteten Zeitraum umgesetzt. +Auch die Befehle und Informationen, die von der lokalen Lichtsteuereinheit versendet werden, konnten mit Hilfe von WireShark auf Korrektheit überprüft und bestätigt werden. + +\subsection{Grafikanimationen und Listenaktualisierungen} +\label{sec_Grafikanimationen_Listenaktualisierungen} +\begin{wrapfigure}{R}{0.42\textwidth} + \begin{center} + \vspace{-36pt} + \includegraphics[width=0.4\columnwidth] {./Medien/ThreeStageToggle.png} + \caption{Zustände des ThreeStageSwitchButtons} + \label{fig_ThreeStageSwitchButton} + \vspace{-26pt} + \end{center} +\end{wrapfigure} + +Ein weiteres Problem sind Grafikanimationen von JavaFX Elementen und die Aktualisierungen von Listen. +Für die Statusanzeige einer Gruppe wird ein sogenannter ThreeStageSwitchButton verwendet. +Dieser Switch-Button hat drei Zustände: AN, AUS und MITTE. +Abbildung \ref{fig_ThreeStageSwitchButton} zeigt die drei Zustände des Switch-Buttons. +Die Position und Farbe des Switch-Buttons ist mit Hilfe eines Listeners an eine ObjectProperty des Listenelements gebunden. +Ändert sich der Status der Gruppe, so wird eine Positions- und Farbanimation vom alten Zustand zum neuen durchgeführt. +Quellcode \ref{src_ThreeStageSwitchButton} zeigt den Listener im Switch-Button-Objekt. \breath + +\begin{lstlisting}[caption={Statelistener im ThreeStageSwitchButton}, label=src_ThreeStageSwitchButton] +buttonState.addListener((obs, oldState, newState) -> { + switch (newState) { + case ON: + translateAnimation.setToX(background.getWidth() - background.getArcHeight()); + fillAnimation.setFromValue(oldState == State.OFF ? Color.WHITE : Color.GOLD); + fillAnimation.setToValue(Color.LIGHTGREEN); + break; + case MID: + translateAnimation.setToX((background.getWidth() - background.getArcHeight())/2); + fillAnimation.setFromValue(oldState == State.OFF ? Color.WHITE : Color.LIGHTGREEN); + fillAnimation.setToValue(Color.GOLD); + break; + case OFF: + translateAnimation.setToX(0); + fillAnimation.setFromValue(oldState == State.ON ? Color.LIGHTGREEN : Color.GOLD); + fillAnimation.setToValue(Color.WHITE); + break; + } + animation.play(); +}); +\end{lstlisting} + +Wird der Status der Gruppe jedoch zu schnell geändert, wird die Animation nicht mehr korrekt durchgeführt. +Wird eine Gruppe z.~B. schnell hintereinander auf den Status \glqq TEILAKTIV\grqq \space und dann auf den Status \glqq ACTIV\grqq \space gesetzt, so bleibt der Switch-Button in der mittleren Position stehen.\breath + +Auch bei den Aktualisierungen von Listen kommt es häufig zu Ungleichheiten zwischen der View und dem Model. +Fügt man z.~B. eine neue Lichtstimmung einer Gruppe hinzu, so kann es passieren, dass die neu erstellte Lichtstimmung mehrfach in der Gruppe angezeigt wird. +Wechselt man zwischen den Gruppen hin und her, wird beim erneuten Laden der Lichtstimmungen die Anzahl wieder korrekt angezeigt. \ No newline at end of file diff --git a/doc/projectDocumentation/Aufbau_der_Lichtsteuersoftware.tex b/doc/projectDocumentation/Aufbau_der_Lichtsteuersoftware.tex new file mode 100644 index 0000000000000000000000000000000000000000..b7d4ddc6dc8f5092b58fadde4ed334ea8c1cbadf --- /dev/null +++ b/doc/projectDocumentation/Aufbau_der_Lichtsteuersoftware.tex @@ -0,0 +1,512 @@ +Die Lichtsteuersoftware \acs{kiwi} ist das zentrale Bedienelement des Heimilluminationssystems. +Der Name \acs{kiwi} steht dabei für \ac{kiwi}. +Die Software steuert alle Lampen des Systems und programmiert die Presets der lokalen Lichtsteuereinheit. +Das folgende Kapitel stellt die Software- und Datenstruktur des Programms dar und erläutert den Aufbau der Benutzerschnittstelle. +Aufbauend auf Kapitel \ref{sec_Art-Net} stellt Kapitel \ref{sec_Integration_des_Netzwerkkommunikationsprotokolls} die Integration des Art-Net-Protokolls in der Software dar. +Abschließend beschreibt Kapitel \ref{sec_Realisierung_des_Model_View_ViewModel_Entwurfsmuster}, wie mit Hilfe von Listenern und Bindings das Model-View-ViewModel-Prinzip umgesetzt ist. + +\subsection{Softwarearchitektur} +\label{sec_Softwarearchitektur} +\lstset{style=java} + +\begin{wrapfigure}{R}{0.52\textwidth} + \begin{center} + \vspace{-28pt} + \includegraphics[width=0.5\columnwidth] {./Medien/Klassendiagramme/Lichtsteuersoftware/Klassendiagramm_Packages.pdf} + \caption{Paketdiagramm der Lichtsteuersoftware.} + \label{fig_Paketdiagramm} + \vspace{-36pt} + \end{center} +\end{wrapfigure} + +Die Lichtsteuersoftware besteht im Groben aus den vier Haupt-Paketen \lstinlinemap{application}, \lstinlinemap{model}, \lstinlinemap{viewModel} und \lstinlinemap{view}. +Diese Pakete enthalten jeweils eine Hauptklasse und weitere Pakete. +Abbildung \ref{fig_Paketdiagramm} zeigt in vereinfachter Form die Zusammenhänge zwischen den Paketen. +Das Paket \lstinlinemap{application} besteht nur aus der Klasse \lstinlinemap{MainKiwi}. +Diese Klasse enthält die Main-Methode, in welcher die jeweiligen Handlerklassen der anderen Pakete erzeugt werden und die Benutzeroberfläche gestartet wird.\par +Die Logik der Software ist im Paket \lstinlinemap{model} enthalten, welches die Komponenten des Heimilluminationssystems abbildet. +Abbildung \ref{fig_Klassendiagramm_Model} gibt eine Übersicht aller Klassen des Pakets und stellt deren Abhängigkeiten dar. +Die Hauptklasse des Pakets ist die Klasse \lstinlinemap{KiwiModelHandler}. +Diese erstellt die drei Repositories (für Fixtures, Groups und Presets) und den Art-Net-Controller. +Sie stellt Methoden zur Verfügung, durch die das ViewModel auf die Model-Objekte zugreifen kann.\par +Die jeweiligen Repositories verwalten Objekte wie \lstinlinemap{Fixture}, \lstinlinemap{Group} und \lstinlinemap{Preset}. +Zur Speicherung und Verwaltung wird eine \lstinlinemap{Map<>} verwendet. +Als Key wird das Attribut \lstinlinemap{name} verwendet, welches alle drei Objekte besitzen. +Die Repositories stellen Methoden zum Erstellen, Löschen und Bearbeiten der Objekte zur Verfügung.\par +Die Klasse \lstinlinemap{ArtNetController} besitzt ebenfalls eine Repository-Klasse, in der die Art-Net-Nodes verwaltet werden. +Sie implementiert das Interface \lstinlinemap{LightControllable}, damit andere Objekte des Paketes auf einen Licht-Controller zugreifen können, ohne die genaue Protokollimplementierung dahinter kennen zu müssen. +Des Weiteren besitzt sie ein Objekt vom Typ \lstinlinemap{UdpListener}, welches in einem eigenen Thread gestartet wird.\par +Die Klasse \lstinlinemap{PropertyItem} wird an alle Klassen vererbt. +Sie besitzt die beiden Methoden \lstinlinemap{addPropertyChangeListener} und \lstinlinemap{removePropertyChangeListener}, mit denen die Klassen des Viewmodels Listener für Attributwerte an- und abmelden können.\par + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth]{./Medien/Klassendiagramme/Lichtsteuersoftware/classDiagramLightControlSoftwareModelPackage.pdf} + \caption{Klassendiagramm des Pakets \lstinlinemap{model}.} + \label{fig_Klassendiagramm_Model} + \end{center} +\end{figure} + +\begin{wrapfigure}{R}{0.42\textwidth} + \begin{center} + \vspace{-32pt} + \includegraphics[width=0.4\columnwidth] {./Medien/Klassendiagramme/Lichtsteuersoftware/Interface_LightingScene.pdf} + \caption{Aufbau des Interfaces \lstinlinemap{LightingScene}.} + \label{fig_Interface_LightingScene} + \vspace{-32pt} + \end{center} +\end{wrapfigure} +Die Klassen \lstinlinemap{Composition} und \lstinlinemap{LightingMood} implementieren das Interface \lstinlinemap{LightingScene}. +Der Begriff Lichtszene (eng. LightingScene) ist ein Oberbegriff für Lichtstimmung und Komposition. +Das Interface wird von der Klasse \lstinlinemap{Preset} und \lstinlinemap{Group} verwendet. +Da ein Preset sowohl eine Lichtstimmung, als auch eine Komposition enthalten kann, wird hier eine gemeinsame übergeordnete Struktur benötigt. +Das Objekt der Gruppe besitzt ebenfalls ein Attribut, welches sowohl eine Lichtstimmung als auch eine Komposition sein kann. +Die Methode \lstinlinemap{getLightingSceneType} ermöglicht es herauszufinden, ob es sich um eine Lichtstimmung oder eine Komposition handelt. +Die Gruppe benötigt diese Information, um das Objekt im entsprechenden Repository zu suchen. \breath + +\begin{wrapfigure}{L}{0.55\textwidth} + \begin{center} + \vspace{-40pt} + \includegraphics[width=0.54\columnwidth] {./Medien/Klassendiagramme/Lichtsteuersoftware/Klasse_Group.pdf} + \caption{Aufbau der Klasse \lstinlinemap{Group}.} + \label{fig_Klasse_Group} + \vspace{-32pt} + \end{center} +\end{wrapfigure} + +Das zentrale Element des Pakets ist die Klasse \lstinlinemap{Group}. +Eine Übersicht der Methoden und Attribute der Klasse ist in Abbildung \ref{fig_Klasse_Group} zu sehen. +Sie besitzt ein Fixture"~, LightingMood- und Composition-Repository. +Das Fixture-Repository beinhaltet alle Lampen der Gruppe und ist unabhängig vom globalen Fixture-Repository. +Das Attribut \lstinlinemap{currentLightingScene} vom Typ \lstinlinemap{LightingScene} enthält die aktuell aktive Lichtstimmung oder Komposition. +Da in einer Gruppe immer nur eine Lichtstimmung oder eine Komposition aktiv sein kann, muss der Gruppe beim Aktivieren einer weiteren Lichtstimmung oder Komposition bekannt sein, welche Lichtszene gerade aktiv ist, um diese zu deaktivieren. +Die Klasse \lstinlinemap{Group} stellt Methoden zur Verfügung, mit denen Lampen hinzugefügt oder auch entfernt werden können. +Das Hinzufügen und Entfernen einer Lampe findet nicht direkt über das Fixture-Repository der Gruppe statt, sondern über eigene Funktionen der Gruppe. +Wird eine Lampe einer Gruppe hinzugefügt oder gelöscht, so hat dies auch Auswirkungen auf die Repositories der Lichtstimmung und Komposition.\par +Der Quellcode \ref{src_addFixture} zeigt die Methode \lstinlinemap{addFixture} der Klasse \lstinlinemap{Group}. +In Zeile 1 wird die Lampe dem Fixture-Repository hinzugefügt. +In Zeile 2 bis 9 wird die neue Lampe allen vorhandenen Kompositionen der Gruppe hinzugefügt. +Hierbei werden alle \ac{dmx}-Werte der Lampe auf 0 gesetzt. +Falls aktuell eine Lichtstimmung aktiv ist, werden der Lampe die \ac{dmx}-Werte der Lichtstimmung zugewiesen (vgl. Zeile 11 bis 14). +In Zeile 22 wird anschließend noch überprüft, ob die Gruppe aktuell aktiv ist und, falls ja, wird die Lampe ebenfalls auf aktiv gesetzt. \breath + +\begin{lstlisting}[caption={Methode \lstinlinemap{addFixture} der Klasse \lstinlinemap{Group}.}, label=src_addFixture] +this.fixtureRepository.addFixture(fixture); +this.compositionRepository + .getCompositionMap() + .forEach((String name, Composition composition) -> { + composition + .setDmxValuesForFixture( + fixture.getName(), + new DmxValues()); +}); +if(this.currentLightingScene != null) { + if(this.currentLightingScene.getLightingSceneType() == LightingSceneType.LIGHTING_MOOD) { + fixture.setDmxValues( + ((LightingMood) this.currentLightingScene) + .getDmxValues()); + } else if( + this.currentLightingScene.getLightingSceneType() == LightingSceneType.COMPOSITION) { + fixture.setDmxValues( + ((Composition) this.currentLightingScene) + .getDmxValuesForFixture(fixture.getName())); + } +} +if(this.currentState == State.AKTIV) { + fixture.activate(); +} +\end{lstlisting} + +\begin{wrapfigure}{R}{0.55\textwidth} + \begin{center} + \vspace{-36pt} + \includegraphics[width=0.54\columnwidth] {./Medien/Klassendiagramme/Lichtsteuersoftware/Klasse_Preset.pdf} + \caption{Aufbau der Klasse \lstinlinemap{Preset} aus der Lichtsteuersoftware.} + \label{fig_Klasse_Preset_LS} + \vspace{-32pt} + \end{center} +\end{wrapfigure} + +Die Klasse \lstinlinemap{PresetRepository} mit den darin enthaltenen Presets ist eine Abbildung der Presets der Lichtsteuereinheit. +Ein Preset enthält für eine Gruppe eine Lichtszene. +Wird dieses aktiviert, wird die entsprechende Gruppe mit der dazugehörigen Lichtszene aktiviert. +Abbildung \ref{fig_Klasse_Preset_LS} zeigt den Aufbau der Klasse \lstinlinemap{Preset}.\par +Die Methode \lstinlinemap{updatePreset} überträgt die vom Benutzer eingestellte Lichtszene an die Lichtsteuereinheit. +Quellcode \ref{src_updatePreset} zeigt den Inhalt der Methode. +Zu Beginn der Methode wird der Preset der lokalen Lichtsteuereinheit geleert, damit keine alten Werte mehr enthalten sind (vgl. Zeile 2). +Um den Preset nun mit neuen Werten zu befüllen, muss unterschieden werden, ob es sich bei der Lichtszene um eine Lichtstimmung oder eine Komposition handelt (vgl. Zeile 3). +Bei einer Lichtstimmung werden für jede Lampe der Gruppe die Werte der ausgewählten Lichtstimmung in das Preset der Lichtsteuereinheit übertragen (vgl. Zeile 5 bis 11). +Handelt es sich um eine Komposition, so werden die in der Komposition für die Lampen hinterlegten Werte an den Preset gesendet (vgl. Zeile 15 bis 21). \breath + +\begin{lstlisting}[caption={Methode \lstinlinemap{updatePreset} der Klasse \lstinlinemap{Preset}.}, label=src_updatePreset] +if(lightingScene != null) { + this.lightController.clearPreset(this.id); + if(lightingScene.getLightingSceneType() == + LightingSceneType.LIGHTING_MOOD) { + group.getFixtureRepository() + .getFixtureMap() + .forEach((String name, Fixture fixture) -> { + this.setDmxValueForPreset( + fixture.getAddress(), + ((LightingMood)lightingScene) + .getDmxValues()); + }); + } else if (lightingScene.getLightingSceneType() == + LightingSceneType.COMPOSITION) { + group.getFixtureRepository() + .getFixtureMap() + .forEach((String name, Fixture fixture) -> { + this.setDmxValueForPreset( + fixture.getAddress(), + ((Composition)lightingScene) + .getDmxValuesForFixture(name)); + }); + } +} +\end{lstlisting} + +\subsection{Benutzerschnittstelle} +\label{sec_Benutzerschnittstelle} +Im Software-Entwicklungsprojekt wurde eine Nutzungsweise für ein Heimilluminationssystem ermittelt. +Die Benutzerschnittstelle ist auf Grundlage dieser Nutzungsweise entwickelt. +Abbildung \ref{fig_MainScreenKiwi} zeigt das Hauptfenster der Lichtsteuersoftware. +Entsprechend der ermittelten Nutzungsweise bildet die Gruppe das wichtigste Objekt im Kontext eines Heimilluminationssystems. +Die Liste aller Gruppen ist im linken Teil des Hauptfensters der Software lokalisiert. +Durch die Auswahl einer Gruppe werden weitere Elemente im Fenster geladen. +Somit besitzt die Liste der Gruppen eine Art Navigationscharakter. +Dies wird durch die Positionierung am linken Rand des Fensters unterstützt. +Der Benutzer wird in der Bedienung der Software unterstützt, da die Bedienabfolge (Gruppe auswählen $\rightarrow$ Lichtszene auswählen) der gewohnten Leserichtung (von Links nach Rechts) entspricht. +\footnote{Entspricht die gewohnte Leserichtung nicht von Links nach Rechts, so müsste die Anordnung entsprechend angepasst werden.} + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth]{./Medien/Kiwi_Main_Screne.png} + \caption{Hauptfenster der Lichtsteuersoftware \ac{kiwi}.} + \label{fig_MainScreenKiwi} + \end{center} +\end{figure} + +Unterhalb der Gruppenliste befindet sich der Bereich für die Lichtsteuereinheit. +Diesem Bereich kann der Benutzer die Information über den Verbindungsstaus zur Lichtsteuereinheit entnehmen und diesen mit Hilfe des Schalters auch ändern.\par +Auf der rechten Seite des Fensters befinden sich die beiden Bereiche für die Auswahl der Lichtstimmungen und der Kompositionen. +Die Listenelemente sind ähnlich zu denen aus der Gruppenliste aufgebaut. +Dies sorgt dafür, dass der Benutzer ein einheitliches Nutzungsgefühl erhält und gelerntes Nutzungsverhalten auch auf andere Bereiche der Software übertragen kann. +So befinden sich z.~B. auf den Listenelementen der Gruppenliste Icons mit einem Bleistift und einem Mülleimer. +Klickt der Benutzer diese Icons an, kann er die ausgewählte Gruppe bearbeiten oder löschen. +Diese Icons befinden sich auch auf den Listenelementen der anderen Listen. +Der Benutzer kann nun die korrekte Funktion dieser Icons vermuten, ohne diese vorher betätigt zu haben, was die Bedienung der Software vereinfacht.\par +Am oberen Fensterrand befindet sich die Menübar, über die der Benutzer alle Funktionen der Software erreichen kann. + +\begin{wrapfigure}{R}{0.35\textwidth} + \begin{center} + \vspace{-24pt} + \includegraphics[width=0.33\columnwidth] {./Medien/Kiwi_Create_Fixture.png} + \caption{Fenster zur Erstellung einer neuen Lampe} + \label{fig_CreateFixture} + \vspace{-32pt} + \end{center} +\end{wrapfigure} + +Entsprechend des Nutzungskontextes fügt der Benutzer nur zu Beginn und anschließend sehr selten und unregelmäßig Lampen dem System hinzu. +Somit muss diese Funktionalität nicht direkt aus dem Hauptbildschirm erreichbar sein und kann in die Menübar verlagert werden. +Abbildung \ref{fig_CreateFixture} zeigt das Fenster zur Erstellung einer neuen Lampe im System. +Dieses kann der Benutzer über das Menü \emph{Lampen} und den Menüeintrag \emph{Lampe hinzufügen} erreichen. +Damit der Benutzer beim Hinzufügen einer Lampe nicht das Fenster wechseln muss, um eine neue Gruppe für die entsprechende Lampe zu erstellen, ist der Button zur Erstellung neuer Gruppen mit im Fenster platziert. \breath + +Zum Erstellen einer neuen Lichtstimmung kann der Benutzer den Button im oberen Bereich der Lichtstimmungsliste nutzen, oder den Menüeintrag im Menü \emph{Lichtstimmungen} aufrufen. +Abbildung \ref{fig_CreateLightingMood} zeigt das Fenster zur Erstellung einer Lichtstimmung. + +\begin{figure}[H] + \begin{center} + \includegraphics[width=0.85\columnwidth]{./Medien/Kiwi_Create_LigtingMood.png} + \caption{Fenster zur Erstellung einer Lichtstimmung.} + \label{fig_CreateLightingMood} + \end{center} +\end{figure} + +Für die Erstellung einer Lichtstimmung muss der Benutzer die Gruppe auswählen, in der die Lichtstimmung erstellt werden soll. +Nutzt der Benutzer den Button im Hauptfenster, so wird die aktuell ausgewählte Gruppe vorausgewählt. +Jede Lichtstimmung benötigt einen Namen bzw. eine Bezeichnung. +Diese kann der Benutzer im Textfeld oben rechts eingeben. +Das Sternchen vor dem Textfeld gibt an, dass es sich hierbei um ein Pflichtfeld handelt. +Lässt der Benutzer das Feld leer, wird er mit einer Fehlermeldung darauf hingewiesen. +Die Fehlermeldung erscheint, sobald der Benutzer versucht, die Lichtstimmung hinzuzufügen. +Mit den Schiebereglern oder den Zahlenfeldern kann der Benutzer die gewünschten Werte der Lampe einstellen. +Für die Auswahl der Farbe steht diesem auch ein Farbauswahlfenster zur Verfügung, in dem er benutzerdefinierte Farben speichern kann. \breath + +Analog zur Erstellung einer Lichtstimmung kann der Benutzer eine neue Komposition über den Button der Kompositionsliste oder über den entsprechenden Menüeintrag erstellen. +Abbildung \ref{fig_CreateComposition} zeigt das Fenster zur Erstellung einer Komposition. + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth]{./Medien/Kiwi_Create_Composition.png} + \caption{Fenster zur Erstellung einer Komposition} + \label{fig_CreateComposition} + \end{center} +\end{figure} + +Für die Komposition muss ebenfalls eine Gruppe ausgewählt und ein Name vergeben werden. +Bei der Komposition wählt der Benutzer die einzelnen Lampen aus und weist diesen eine Lichtstimmung zu. +Dazu kann er entweder aus den vorhandenen Lichtstimmungen der Gruppe auswählen oder eine benutzerdefinierte Lichtstimmung für diese Komposition einstellen. +Wechselt der Benutzer zwischen den verschiedenen Lampen, werden die eingestellten Lichtstimmungen für die entsprechende Lampe zwischengespeichert. +\pagebreak + +\subsection{Integration des Netzwerkkommunikationsprotokolls} +\label{sec_Integration_des_Netzwerkkommunikationsprotokolls} + +\begin{wrapfigure}{R}{0.62\textwidth} + \begin{center} + \vspace{-24pt} + \includegraphics[width=0.6\columnwidth] {./Medien/Klassendiagramme/Lichtsteuersoftware/Klasse_ArtNetController.pdf} + \caption{Aufbau der Klasse \lstinlinemap{ArtNetController}} + \label{fig_KlasseArtNetController} + \vspace{-24pt} + \end{center} +\end{wrapfigure} + +Die Klasse \lstinlinemap{ArtNetController} steuert die Art-Net-Kom\-mu\-ni\-ka\-tion. +Sie stellt die Verbindung zu den Nodes her, versendet Art-Net-Pakete wie z.~B. ArtDmx zum Übertragen der \ac{dmx}-Werte und startet den \ac{udp}-Client um Art-Net-Pakete zu empfangen. +Abbildung \ref{fig_KlasseArtNetController} zeigt den Aufbau der Klasse \lstinlinemap{ArtNetController}.\breath + +Um sich mit den Nodes zu verbinden, sendet die Klasse ein ArtPoll-Paket per Broadcast. +Dies wird in der Methode \lstinlinemap{connectToNodes} durchgeführt. +Als Erstes wird in der Methode der \ac{udp}-Client, der Klasse \lstinlinemap{UdpListener} gestartet, damit die Antwort der Nodes empfangen werden kann. +Anschließend wird ein ArtPoll-Paket versendet. +Um ein ArtPoll-Paket zu versenden, wird ein Objekt vom Typ \lstinlinemap{ArtPoll} erstellt.\par +Für jeden Pakettypen gibt es eine entsprechend Klasse, welche die Attribute bzw. Felder des Paktes besitzt. +Jede dieser Klassen besitzt auch einen Konstruktor, dem ein Byte-Array übergeben werden kann, damit dieses direkt zum entsprechenden Pakettypen geparsed wird. +Zusätzlich besitzen alle Paketklassen auch die Methode \lstinlinemap{getUdpArray}, die ein Byte-Array zurück gibt, das dem Aufbau des entsprechenden Paketes entspricht. +Quellcode \ref{src_getUdpArray} zeigt beispielhaft die Methode \lstinlinemap{getUdpArray} der Klasse \lstinlinemap{ArtDmx}.\breath + +\begin{lstlisting}[caption={Methode \lstinlinemap{getUdpArray} der Klasse \lstinlinemap{ArtDmx}.}, label=src_getUdpArray] +byte[] udpArray = new byte[18 + this.length]; +byte[] opCodeArray = ByteBuffer.allocate(2) + .putShort(this.opCode) + .array(); +byte[] lengthArray = ByteBuffer.allocate(2) + .putShort(this.length) + .array(); +// id +for(int i = 0; i < 8; i++) { + udpArray[i] = (byte)this.id.charAt(i); +} +// op code +udpArray[8] = opCodeArray[1]; +udpArray[9] = opCodeArray[0]; +// protocoll version +udpArray[10] = this.protVerHi; +udpArray[11] = this.protVerLo; +// sequence +udpArray[12] = this.sequence; +// physical +udpArray[13] = this.physical; +// sub-net and universe +udpArray[14] = this.subUni; +// net +udpArray[15] = this.net; +// length +udpArray[16] = lengthArray[0]; +udpArray[17] = lengthArray[1]; +for(int i = 0; i < this.length; i++) { + udpArray[18 + i] = this.data[i]; +} +return udpArray; +\end{lstlisting} + +Die Methode \lstinlinemap{processArtDataReply} der Klasse \lstinlinemap{UdpListener} verarbeitet im Anschluss die Antworten der Nodes. +Diese prüft die IP-Adressen der eingegangenen Antworten mit denen der bekannten Nodes im Node-Repository. +Stimmen diese bei einer Antwort überein, wird der Verbindungsstatus des Nodes auf \glqq Verbunden\grqq \space gesetzt. +Sind alle Nodes verbunden, so gilt die Verbindung als hergestellt.\breath + +Bei der Aktivierung von Gruppen müssen \ac{dmx}-Werte mit Hilfe von Art-Net übertragen werden. +Damit die Anzahl der versendeten Pakete möglichst minimal gehalten werden kann, stellt der Art-Net-Controller zwei Methoden zur Verfügung. +Mit der Methode \lstinlinemap{setDmxValue} können dem Controller neue \ac{dmx}-Werte mitgeteilt werden. +Dieser speichert diese dann in seinem eigenen \ac{dmx}-Ausgabe-Array. +Erst mit dem Aufruf der Funktion \lstinlinemap{sendDmxValue} werden alle aktuell im Controller gespeicherten \ac{dmx}-Werte per Art-Net versendet. \breath + +Wird ein Preset an der Lichtsteuereinheit aktiviert, informiert diese die Software mit Hilfe eines ArtCommands. +Die Klasse \lstinlinemap{UdpListener} muss diesen empfangen und auswerten. +Abbildung \ref{fig_KlasseUdpListener} zeigt den Aufbau der Klasse \lstinlinemap{UdpListener}. +Die Klasse implementiert das Interface \lstinlinemap{Runnable} und wird von der Klasse \lstinlinemap{ArtNetController} in einem eigenen Thread ausgeführt. + +\begin{wrapfigure}{R}{0.52\textwidth} + \begin{center} + \vspace{-20pt} + \includegraphics[width=0.5\columnwidth] {./Medien/Klassendiagramme/Lichtsteuersoftware/Klasse_UdpListener.pdf} + \caption{Aufbau der Klasse \lstinlinemap{UdpListener}} + \label{fig_KlasseUdpListener} + \vspace{-36pt} + \end{center} +\end{wrapfigure} + +Die Methode \lstinlinemap{run} enthält eine While-Schleife, die als Abbruchkriterium das Attribut \lstinlinemap{running} besitzt. +Dieses Attribut ist vom Typ \lstinlinemap{AtomicBoolean} und kann somit threadsicher von außerhalb des Threads gesetzt werden. +Möchte der Benutzer die aktuelle Verbindung zu den Nodes aufheben, wird der Wert des Attributs auf \lstinlinemap{false} gesetzt und die Schleife bricht ab.\breath + +Um ein Paket zu empfangen, startet die \lstinlinemap{run}-Methode einen \ac{udp}-Socket mit einer Ablaufzeit, falls kein Paket kommt. +Die Ablaufzeit wird benötigt, damit in regelmäßigen Abständen das Abbruchkriterium der Schleife getestet werden kann. +Quellcode \ref{src_run} zeigt den Aufbau der Methode \lstinlinemap{run}. \breath + +\begin{lstlisting}[caption={Methode \lstinlinemap{run} der Klasse \lstinlinemap{UdpListener}.}, label=src_run] +try(DatagramSocket socket = new DatagramSocket(this.port)) { + socket.setSoTimeout(1000); + while(this.running.get()) { + try { + DatagramPacket incomingDatagram = new DatagramPacket(this.incomingData, this.incomingData.length); + socket.receive(incomingDatagram); + this.incomingData = incomingDatagram.getData(); + if(checkIfArtNetPakage(this.incomingData)) { + opCodeArray[0] = this.incomingData[9]; + opCodeArray[1] = this.incomingData[8]; + this.opCode = ByteBuffer.wrap(opCodeArray).getShort(); + [...] + // if else Anweisungen entsprechend des OP-Codes + } + } catch (SocketTimeoutException e) {} + } + socket.close(); +} catch (SocketException e) { + e.printStackTrace(System.err); +} catch (IOException e) { + e.printStackTrace(System.err); +} finally { + artNetController.getNodeRepository() + .getNodesMap() + .forEach((String name, ArtNetNode node) -> { + node.setConnectStatus(false); + }); +} +\end{lstlisting} + +Erhält der UDPListener ein ArtCommand-Paket, so wird die Methode \lstinlinemap{processArtCommand} aufgerufen. +Die Methode zerlegt den Befehlsstring entsprechend des Syntax-Diagramms in die verschiedenen Bestandteile (vgl. Abbildung \ref{fig_SyntaxDiagramm_ArtCommand}). +Für das Parsen des JSON-Objekts wird die Bibliothek GSON verwendet. +Quellcode \ref{src_processArtCommand} zeigt einen Ausschnitt der Methode \lstinlinemap{processArtCommand}. \breath + +\begin{lstlisting}[caption={Methode \lstinlinemap{processArtCommand} der Klasse \lstinlinemap{UdpListener}.}, label=src_processArtCommand] +[...] +PresetActivatedCommand presetActivatedCommand = this.gson.fromJson(commandJSON, PresetActivatedCommand.class); +presetRepository.getPreset( presetActivatedCommand.getPresetId()).activate(); +[...] +\end{lstlisting} + +Zum deserialisieren des JSON-Objektes wird der Befehl \lstinlinemap{fromJson} des \lstinlinemap{gson}-Objektes verwendet. +Diesem wird der JSON-String und die Klasse mit der dazugehörigen Struktur übergeben. + +\pagebreak +\subsection{Realisierung des Model-View-ViewModel-Ent\-wurfs\-musters} +\label{sec_Realisierung_des_Model_View_ViewModel_Entwurfsmuster} + +\begin{wrapfigure}{R}{0.35\textwidth} + \begin{center} + \vspace{-36pt} + \includegraphics[width=0.33\columnwidth] {./Medien/Klassendiagramme/Lichtsteuersoftware/MVVM.pdf} + \caption{Entwurfsmuster Model-View-ViewModel} + \label{fig_MVVM} + \vspace{-26pt} + \end{center} +\end{wrapfigure} + +Um die Objekte aus dem Paket \lstinlinemap{model} mit der Benutzeroberfläche zu verbinden, ist das Model-View-ViewModel-Entwurfsmuster im Einsatz. +Das Entwurfsmuster ist eine Alternative zum Entwurfsmuster Model-View-Controller. +Die Objekte der drei Schichten werden jeweils mit Hilfe von Bindings miteinander verbunden. +Anstelle von Bindings können auch Listener verwendet werden. +Abbildung \ref{fig_MVVM} stellt das Entwurfsmuster dar. +Das ViewModel verarbeitet die Eingaben der View und reicht sie ans Model weiter. +Sobald die Daten im Model verändert wurden, werden diese per Binding auch auf der Benutzeroberfläche angepasst. +Das ViewModel besitzt ebenfalls alle Eigenschaften der Benutzeroberfläche als Attribute. +Kann ein Listenelement z.~B. selektiert werden, so benötigt das ViewModel einen \lstinlinemap{boolean}-Parameter, der diesen Zustand abbildet.\breath + +Abbildung \ref{fig_MVVM_Struktur} stellt grundlegend dar, wie das Entwurfsmuster in der Software realisiert wurde. +Die Hauptapplikation \lstinlinemap{MainKiwi} besitzt die drei Handler-Objekte für Models, ViewModels und die View. +Die Handler-Objekte besitzen jeweils eine Referenz auf den nächstniedrigeren Handler, damit diese das Binding herstellen oder einen Listener erstellen können. +Die eigentlichen Objekte (Fixture, Group, FixtureVM etc.) der Schicht erhalten über diese Handler die entsprechenden Objekte der niedrigeren Schicht. + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth]{./Medien/Klassendiagramme/Lichtsteuersoftware/Klassendiagramm_MVMV.pdf} + \caption{MVVM-Struktur der Applikation} + \label{fig_MVVM_Struktur} + \end{center} +\end{figure} + +Um das Model unabhängig von der Benutzeroberfläche zu halten, wird anstelle der SimpleProperty-Klassen der JavaFX Bibliothek die Klasse \lstinlinemap{PropertyChangeSupport} der Java Beans Bibliothek verwendet. +Die Klasse ermöglicht es anderen Klassen, sich für Änderungen anzumelden. +Für das An- und Abmelden von Listenern benötigt die Model-Klasse die Methoden \lstinlinemap{addPropertyChangeListener} und \lstinlinemap{removePropertyChangeListener}, die durch die Klasse \lstinlinemap{PropertyItem} an alle Model-Klassen vererbt werden. +Ändern sich Werte im Model, können diese Änderungen wie in Quellcode \ref{src_setName} dargestellt, an die angemeldeten Listener mitgeteilt werden. \breath + +\begin{lstlisting}[caption={Methode \lstinlinemap{setName} der Klasse \lstinlinemap{Group}.}, label=src_setName] +public void setName(String name) { + this.propertySupport. firePropertyChange("name",this.name, name); + this.name = name; +} +\end{lstlisting} + +Die Methode \lstinlinemap{firePropertyChange} teilt allen angemeldeten Listenern mit, welches Attribut sich geändert hat, was der alte und der neue Wert ist. +Ein ViewModel kann sich dann, wie in Quellcode \ref{src_KonstGroupVM} dargestellt, an einer Klasse anmelden und auf Änderungen reagieren. \breath + +\begin{lstlisting}[caption={Auszug aus dem Konstruktor der Klasse \lstinlinemap{GroupVM}.}, label=src_KonstGroupVM] +this.groupListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("name")) { + groupName.setValue((String)event.getNewValue()); + } [...] + } +}; +group.addPropertyChangeListener(this.groupListener); +\end{lstlisting} + +Bei dem Attribut \lstinlinemap{groupName} handelt es sich um eine SimpleStringProperty. +Dieses kann an eine TextProperty eines JavaFX-Elements gebunden werden. +Quellcode \ref{src_KonstGroupListItem} zeigt das Binding des Gruppennamens an das Label des GruppenListItems.\breath + +\begin{lstlisting}[caption={Auszug aus dem Konstruktor der Klasse \lstinlinemap{GroupListItem}.}, label=src_KonstGroupListItem] +this.groupVM = groupVM; +this.groupRepositoryVM = viewModelHandler.getGroupRepositoryVM(); +this.groupId.bind(this.groupVM.groupIdProperty()); +this.groupName.bind(this.groupVM.groupNameProperty()); +this.groupState.bindBidirectional( this.groupVM.groupStateProperty());; +this.groupSelected.bind( this.groupVM.groupSelectedProperty()); +\end{lstlisting} + +Kann der Benutzer das JavaFX-Element beeinflussen, so kann diese Eigenschaft auch bidirektional verbunden werden (siehe Zeile 5). +Bei einer bidirektionalen Verbindung wird der in der View eingestellte Wert auch zurück ins ViewModel übertragen. +Dies macht besonders Sinn in den Eingabemasken zum Ändern von bestehenden Objekten, wie Gruppen oder Lichtszenen.\breath + +Zum Verbinden von ganzen Listen enthält das ViewModel eine ObservableList. +Diese ermöglicht es, die Liste direkt zu verbinden oder einen Listener für Änderungen an der Liste anzumelden. +Quellcode \ref{src_initGMPC} zeigt, wie der GroupMainPanelController über Änderungen an der Liste der Gruppen benachrichtigt wird. \breath + +\begin{lstlisting}[caption={Auszug aus der Methode \lstinlinemap{init} der Klasse \lstinlinemap{GroupMainPanelController}.}, label=src_initGMPC] +groupRepositoryVM.groupsListProperty() .addListener((ListChangeListener.Change<? extends GroupVM> change) -> { + while(change.next()) { + change.getAddedSubList().forEach(group -> { + this.groups.add(new GroupListItem(group, this.viewModelHandler)); + }); + + change.getRemoved().forEach(group -> { + int groupListIndex = -1; + for(int i = 0; i < this.groups.size(); i++) { + if(this.groups.get(i).getGroupName() .equals(group.getGroupName())) { + groupListIndex = i; + break; + } + } + if(groupListIndex != -1) { + this.groups.remove(groupListIndex); + } + }); + } +}); +\end{lstlisting} + +Werden neue Objekte durch die Benutzeroberfläche erzeugt oder geändert, so reicht die View diesen Vorgang an das ViewModel weiter, das die Objekte anschließend im Model erstellt oder bearbeitet. +Sind die Änderungen im Model durchgeführt, werden ViewModel und View über Listener und Bindings darüber informiert und aktualisiert. +Quellcode \ref{src_newGroup} zeigt beispielhaft die Methode \lstinlinemap{newGroup} der Klasse \lstinlinemap{GroupRepositoryVM}, welche von der View aufgerufen wird, wenn eine neue Gruppe erstellt werden soll.\breath + +\begin{lstlisting}[caption={Methode \lstinlinemap{newGroup} der Klasse \lstinlinemap{GroupRepositoryVM}.}, label=src_newGroup] +public void newGroup(String name) { + this.groupRepository.addGroup( new Group(name,KiwiModelHandler.getLightController())); +} +\end{lstlisting} \ No newline at end of file diff --git a/doc/projectDocumentation/Aufbau_der_lokalen_Lichtsteuereinheit.tex b/doc/projectDocumentation/Aufbau_der_lokalen_Lichtsteuereinheit.tex new file mode 100644 index 0000000000000000000000000000000000000000..de5f6fd5722decd97ccfe2f3b0bae1d345ab8bda --- /dev/null +++ b/doc/projectDocumentation/Aufbau_der_lokalen_Lichtsteuereinheit.tex @@ -0,0 +1,387 @@ +Die lokale Lichtsteuereinheit ermöglicht den Benutzern mit Tastern, Presets zu aktivieren oder zu deaktivieren, wodurch der Benutzer das Heimilluminationssystem auch ohne aktiv laufend Lichtsteuerungssoftware steuern kann. +Zusätzlich erzeugt die lokale Lichtsteuereinheit das \ac{dmx}-Steuersignal, das an die Lampen gesendet wird. +Sie bildet somit das Bindeglied zwischen der Lichtsteuersoftware und den Endgeräten.\par + +Das Kapitel \ref{sec_Hardwareaufbau_Lichtsteuerung} beschreibt den Aufbau der Hardwarekomponenten und gibt Hinweise darüber, was bei diesem zu beachten ist. +Kapitel \ref{sec_Datenstrukturen_Lichtsteuerung} stellt die Datenstrukturen des Mikrocontrollers dar und erläutert, wie die Daten der Presets im \ac{eeprom} gespeichert werden. +Abschließend beschreibt das Kapitel \ref{sec_Integration_des_Netzwerkkommunikationsprotokolls_Lichtsteuerung}, wie die Datenstruktur genutzt wird, um Art-Net-Pakete zu empfangen, auszuwerten und zu versenden.\par + +\subsection{Hardwareaufbau} +\label{sec_Hardwareaufbau_Lichtsteuerung} +Die Lichtsteuereinheit besteht aus dem Mikrocontroller Arduino Mega 2560, dem Arduino Ethernet Shield 2, sechs Schnellauswahltasten (bestehend aus mehreren Komponenten, die später im Text genauer beschrieben werden) und dem Chip \emph{MAX 485}.\par + +Der Arduino verarbeitet die Signale der Schnellauswahltaster, und sendet das entsprechende \ac{dmx}-Signal an die Endgeräte. +Für das Erzeugen des \ac{dmx}-Signals verwendet die Lichtsteuereinheit den Chip \emph{MAX 485}. +Der Arduino sendet das \ac{dmx}-Signal mit Hilfe der Spannungen 0\,V für ein LOW-Byte und 5\,V für ein HIGH-Byte. +Um eine durch das \ac{dmx}-Protokoll vorgegebene Spannung von mindestens $\pm1,5$\,V bis maximal $\pm5$\,V zu erhalten, wandelt der Chip \emph{MAX 485} die beiden Spannungen vom Arduino in $\pm2,5$\,V um. +Dieser symmetrische Spannungspegel dient zur Fehlererkennung im Protokoll. +Empfängt ein Endgerät 0\,V anstelle der $\pm2,5$\,V, so ist sofort erkennbar, dass eine Störung in der Leitung vorliegt. \par + +Ein Schnellauswahltaster besteht aus einem Drucktaster und einer RGB-LED. +Für den Betrieb der RGB-LED sind zusätzlich drei Widerstände mit einer Impedanz von $220\,\Omega$ in Verwendung. +Alle Drucktaster sind auf einem Pin mit dem Arduino verbunden und auf dem anderen mit Ground. Der Arduino steuert die Drucktaster mit dem Pin Mode +\lstinlinemap{INPUT_PULLUP} an. +Bei diesem Pin Mode liegt eine geringe Spannung am entsprechenden Pin an und ein interner Widerstand ist in Reihe geschaltet. +Ist der Pin mit Ground verbunden, fließt ein geringer Strom, wodurch das Eingangssignal auf HIGH steht.\par + +Das Ethernet Shield ist auf dem Arduino aufgesteckt und über die ICSP-Pins des Arduinos verbunden. +Beim Arduino Mega 2560 sind diese gleichgeschaltet mit den Digital Pins 50 bis 53, weswegen diese im weiteren Verlauf nicht für weitere Zwecke zu nutzen sind.\breath + +Abbildung \ref{fig_schematischer_Aufbau_Lichtsteuereinheit} zeigt schematisch den Aufbau der lokalen Lichtsteuereinheit. + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth]{./Medien/Lichtsteuereinheit_Aufbau.pdf} + \caption{Aufbau der lokalen Lichtsteuereinheit schematisch dargestellt.} + \label{fig_schematischer_Aufbau_Lichtsteuereinheit} + \end{center} +\end{figure} + +Alle Pinbelegungen der Hardwarekomponenten sind zentral in der Datei \lstinlinemap{config.h} verwaltet. Sie enthält alle allgemeinen, statischen Werte der Lichtsteuereinheit. +\footnote{Es existieren noch weitere Dateien mit statischen Werten, die aber spezifisch für einen Teil der Lichtsteuereinheit benötigt werden, z.~B. die Op-Codes des Art-Net-Protokolls.} +In Quellcode \ref{src_config} ist ein Ausschnitt der \lstinlinemap{config.h} abgebildet. In der Datei ist unter anderem die Anzahl der angeschlossenen Presets hinterlegt, damit global die Größe des damit verbundenen Arrays definiert ist.\breath + +\begin{lstlisting}[style = cpp, caption={Auszug aus der Konfigurationsdatei config.h.}, label=src_config] +// global values +#define MAX_DMX_CHANNEL 100 +#define NUMBER_OF_PRESETS 6 +#define NUMBER_OF_LED_COLORS 3 +#define EEPROM_START_ADRESS 0 + +// led pins +#define LED_1_PINOUT_R 46 +#define LED_1_PINOUT_G 44 +#define LED_1_PINOUT_B 48 +[...] + +// buttons pins +#define BUTTON_1_PININ 36 +#define BUTTON_2_PININ 34 +#define BUTTON_3_PININ 32 +#define BUTTON_4_PININ 30 +#define BUTTON_5_PININ 28 +#define BUTTON_6_PININ 26 + +// dmx pins +#define DMX_PINOUT 24 + +// preset state values +#define P_DEACTIV 0 +#define P_ACTIVE 1 +#define P_PART_ACTIVE 2 + +// common group id values +#define DEFAULT_GROUP_ID 0 + +[...] +\end{lstlisting} + +\begin{wrapfigure}{R}{0.68\textwidth} + \begin{center} + \vspace{-28pt} + \includegraphics[width=0.66\columnwidth, clip, trim=3cm 0 0 0] {./Medien/Aufbau_Lichsteuereinheit_real.pdf} + \caption{Foto des realen Aufbaus der Lichtsteuereinheit.} + \label{fig_realer_Aufbau_Lichtsteuereinheit} + \vspace{-24pt} + \end{center} +\end{wrapfigure} + +Abbildung \ref{fig_realer_Aufbau_Lichtsteuereinheit} zeigt den realen Aufbau der Lichtsteuereinheit. +Am unteren Ende des Breadboards befinden sich die sechs Drucktaster, welche mit Ground verbunden sind (1). +Rechts daneben befindet sich der Chip Max 485, mit dem das \ac{dmx}-Signal erzeugt wird (2). +Am oberen Ende des Breadboards befinden sich sechs RGB-LEDs, zur Anzeige des Presetstatus (3). +Darüber befindet sich der Arduino Mega 2560 mit dem Ethernet Shield (4). +Links in der Mitte des Breadboards befindet sich ein Modul zur Stromversorgung des Arduinos (5). \par + +\subsection{Datenstrukturen} +\label{sec_Datenstrukturen_Lichtsteuerung} + +Die Datenstruktur der Lichtsteuereinheit lässt sich in vier grobe Bereiche unterteilen. +Abbildung \ref{fig_Klassendiagramm_Lichtsteuereinheit} zeigt ein einfaches Klassendiagramm, ohne Attribute oder Methoden der Klassen. +Die gestrichelten Kästchen rahmen die vier Bereiche Hauptapplikation, Presets, \ac{dmx} und Art-Net ein. +Klassen mit gepunkteten Rahmen stellen dar, dass es sich um eine Datei mit statischen Werten oder um eine oder mehrere Strukturen handelt.\par + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth]{./Medien/Klassendiagramme/Lichtsteuereinheit/classDiagramLightControlUnit_simple.pdf} + \caption{Einfaches Klassendiagramm der Lichtsteuereinheit.} + \label{fig_Klassendiagramm_Lichtsteuereinheit} + \end{center} +\end{figure} + +Der Bereich Hauptapplikation enthält die Ino-Datei \lstinlinemap{lightControlUnit.ino}, die die Setup- und Loop-Methode des Arduinos beinhaltet. +In diesem Bereich ist auch die Datei \lstinlinemap{config.h} enthalten, die, wie bereits erwähnt, alle allgemeinen, statischen Werte enthält. +Die LightControlUnit erstellt und besitzt jeweils ein Objekt der Klassen \lstinlinemap{PresetRepository}, \lstinlinemap{DmxController} und \lstinlinemap{ArtNetController}.\breath + +\begin{wrapfigure}{R}{0.3\textwidth} + \begin{center} + \vspace{-36pt} + \includegraphics[width=0.28\columnwidth] {./Medien/Klassendiagramme/Lichtsteuereinheit/StructDmxChannel.pdf} + \caption{Aufbau der Struktur \lstinlinemap{DmxChannel}.} + \label{fig_Struktur_DmxChannel} + \vspace{-36pt} + \end{center} +\end{wrapfigure} + + + +Im Bereich Presets sind alle Klassen und Strukturen enthalten, die für die Steuerung und Speicherung der sechs Presets benötigt werden. +Die kleinste Einheit eines Presets ist die Struktur \lstinlinemap{DmxChannel}, die in Abbildung \ref{fig_Struktur_DmxChannel} genauer dargestellt ist. +Sie besteht aus dem \lstinlinemap{uint8_t}-Wert des \ac{dmx}-Kanals und einer \lstinlinemap{bool}, die angibt, ob dieser Kanal vom Preset genutzt wird. +Die nächstgrößere Einheit ist die Struktur \lstinlinemap{PresetStoredInformation}. + +\begin{wrapfigure}{R}{0.42\textwidth} + \begin{center} + \vspace{-22pt} + \includegraphics[width=0.4\columnwidth] {./Medien/Klassendiagramme/Lichtsteuereinheit/StructPresetStoredInfromation.pdf} + \caption{Aufbau der Struktur \lstinlinemap{PresetStoredInfromation}.} + \label{fig_Struktur_PresetStoredInfromation} + \vspace{-24pt} + \end{center} +\end{wrapfigure} + +Diese beinhaltet alle Informationen, die von einem Preset auf dem \ac{eeprom} abgespeichert werden müssen. +Abbildung \ref{fig_Struktur_PresetStoredInfromation} zeigt den Aufbau der Struktur. +Sie enthält ein Array von 100 \ac{dmx}-Kanälen, die Gruppen-Id und einen \lstinlinemap{uint8_t}-Wert für den Status des Presets. +Die drei Zustände inaktiv, aktiv und teilaktiv werden durch die Zahlen 0, 1 und 2 dargestellt. +Diese Werte sind global in der \lstinlinemap{config.h}-Datei definiert (vgl. Zeile 25-27 Quellcode \ref{src_config}).\par + +Die \ac{eeprom}-Bibliothek des Arduinos ermöglicht es, mit der Methode \lstinlinemap{put()} eine Struktur beliebiger Größe (aber kleiner als die Speicherkapazität des \acp{eeprom}) im \ac{eeprom} zu speichern.\par + +Die Struktur \lstinlinemap{PresetStoredInformation} belegt 202\,Bytes (100 Kanäle mit je 2\,Bytes plus 2\,Bytes für State und Gruppen-Id) an Speicherplatz. +Die Lichtsteuereinheit besitzt sechs Presets und benötigt somit eine Speicherkapazität von 1.212\,Bytes. +Der \ac{eeprom} des Arduino Mega besitzt eine Speicherkapazität von 4.096\,Bytes. Die benötigte Speicherkapazität ist somit nicht ausgeschöpft.\par + +\begin{wrapfigure}{L}{0.65\textwidth} + \begin{center} + \vspace{-36pt} + \includegraphics[width=0.63\columnwidth] {./Medien/Klassendiagramme/Lichtsteuereinheit/KlassePreset.pdf} + \caption{Aufbau der Klasse \lstinlinemap{Preset}.} + \label{fig_Klasse_Preset} + \vspace{-24pt} + \end{center} +\end{wrapfigure} + +Aufgrund dessen, dass die Klasse \lstinlinemap{Preset} von \linebreak +\lstinlinemap{PresetStoredInfromation} \linebreak +erbt, ist es möglich, das Preset-Objekt als Struktur zu casten und im \ac{eeprom} zu speichern. +Der Aufbau der Klasse \lstinlinemap{Preset} ist in Abbildung \ref{fig_Klasse_Preset} dargestellt. +Die Hauptfunktion der Klasse ist das Speichern und Laden der Information eines Presets. +Das Set \lstinlinemap{usedChannel} enthält die Nummern der Kanäle, die im Preset verwendet werden. +Die Methode \lstinlinemap{updateState} vergleicht dieses Set mit dem Set der aktiven Kanäle der \ac{dmx}-Ausgabe. +Enthält das Set der aktiven Kanäle eine oder mehrere Kanalnummern des Presets, so wird der State des Presets auf teilaktiv gesetzt. +Falls nicht, ist das Preset inaktiv.\par + +Die Klasse \lstinlinemap{PresetRepository} ist für die Verwaltung der Presets zuständig. +Diese aktiviert oder deaktiviert die Presets, übermittelt deren \ac{dmx}-Werte an den \ac{dmx}-Controller und wird vom Art-Net-Controller angesteuert, um Preset-Werte zu setzen oder den State des Presets zu aktualisieren. +Wird ein Preset aktiviert, prüft die Klasse, ob weitere Presets derselben Gruppe deaktiviert werden müssen oder ob andere Presets nun teilaktiv sind. +Abbildung \ref{fig_Klasse_PresetRepository} zeigt die Attribute und Methoden der Preset-Repository-Klasse. + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth] {./Medien/Klassendiagramme/Lichtsteuereinheit/KlassePresetRepository.pdf} + \caption{Aufbau der Klasse \lstinlinemap{PresetRepository}.} + \label{fig_Klasse_PresetRepository} + \end{center} +\end{figure} + +Der Bereich \ac{dmx} besteht nur aus der Klasse \lstinlinemap{DmxController}. +Diese besitzt ein Array an \ac{dmx}-Werten und ein Set mit den Nummern der aktiven Kanäle. + +\begin{wrapfigure}{R}{0.52\textwidth} + \begin{center} + \vspace{-32pt} + \includegraphics[width=0.5\columnwidth] {./Medien/Klassendiagramme/Lichtsteuereinheit/KlasseDmxController.pdf} + \caption{Aufbau der Klasse \lstinlinemap{DmxController}.} + \label{fig_Klasse_DmxController} + \vspace{-24pt} + \end{center} +\end{wrapfigure} + +Sie wird vom Preset-Repository oder vom Art-Net-Controller aufgerufen um \ac{dmx}-Werte zu setzen bzw. zu senden. +Um den State der Presets korrekt bestimmen zu können, muss beim Setzen von \ac{dmx}-Werten auch immer mit angegeben werden, ob der Kanal aktiv ist. +Dies wird durch einen zusätzlichen Parameter beim Methodenaufruf oder durch den Aufruf einer weiteren Funktion mitgeteilt. +Abbildung \ref{fig_Klasse_DmxController} zeigt den Aufbau der Klasse \lstinlinemap{DmxController}. \breath + +Der letzte Bereich (Art-Net) besteht aus der Klasse \lstinlinemap{ArtNetController} und den zwei .h-Dateien, die statische Werte und Strukturen für den Art-Net-Controller enthalten. +Der Art-Net-Controller nutzt die Bibliothek \lstinlinemap{EthernetUDP} des Arduinos, um einen \ac{udp}-Socket zu erstellen und auf dem Port 6454 nach Art-Net-Paketen zu lauschen. +Um die Pakete korrekt interpretieren oder versenden zu können, enthält die Datei \lstinlinemap{ArtNetPackageTypes.h} eine Struktur für jeden benötigten Pakettypen. +Die mit dem Paket \emph{ArtCommand} versendeten Befehle sind als JSON formatiert. +Damit dieser JSON-String erstellt und auch wieder ausgewertet werden kann, enthält die Datei \lstinlinemap{ArtCommands} für jeden möglichen Befehl den JSON-Aufbau als Struktur. + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth] {./Medien/Klassendiagramme/Lichtsteuereinheit/KlasseArtNetController.pdf} + \caption{Aufbau der Klasse \lstinlinemap{ArtNetController}.} + \label{fig_Klasse_ArtNetController} + \end{center} +\end{figure} + +\subsection{Integration des Netzwerkkommunikationsprotokolls} +\label{sec_Integration_des_Netzwerkkommunikationsprotokolls_Lichtsteuerung} + +Der Art-Net-Controller besitzt zwei Hauptfunktionen. +Zum einem lauscht dieser auf dem Port 6454 nach Art-Net-Paketen und zum anderen versendet dieser ArtCommand-Pakete, um mitzuteilen, dass ein Preset aktiviert oder deaktiviert wurde. +Bei der Initialisierung des Objektes wird ein \ac{udp}-Socket gestartet, mit dem der Port 6454 abgehört werden kann. +In der Methode \lstinlinemap{loop()} der Hauptapplikation wird die Methode \lstinlinemap{listenToArtNet} aufgerufen, welche prüft, ob Datenpakete am Port anliegen. +Der Ablauf dieser Methode wird in Abbildung \ref{fig_Ablaufdiagramm_ListenArtNet} dargestellt. +Sobald ein Paket am Port anliegt, überprüft die Methode, ob das Paket mindestens eine Länge von 14 Bytes besitzt. +Dies ist die minimale Größe eines Art-Net-Pakets (vgl. \cite[Seite. 17 f.]{Art-Net}). +Ist dieses Kriterium erfüllt, wird das Paket in ein Byte-Puffer-Array geladen und die IP-Adresse des Senders wird gespeichert, um eine anschließende Antwort versenden zu können. +Anschließend überprüft die Methode \lstinlinemap{checkArtNetHeader}, ob das Paket den Art-Net-Header enthält. +Entsprechen die ersten acht Bytes des Pakets dem Byte-Array \lstinlinemap{\{'A','r','t','-','N','e','t',0x00\}}, so ist dieses ein gültiges Art-Net-Paket. + +\begin{figure}[H] + \begin{center} + \includegraphics[width=0.85\columnwidth] {./Medien/AblaufdiagrammListenArtNet.pdf} + \caption{Ablaufdiagramm der Methode \lstinlinemap{listenToArtNet}.} + \label{fig_Ablaufdiagramm_ListenArtNet} + \end{center} +\end{figure} + +Ist die Prüfung erfolgreich, wird anhand des Op-Codes des Art-Net-Pakets entschieden, um welchen Pakettypen es sich handelt. +Der Op-Code befindet sich in den Bytes 8 und 9 des Pakets und wird mit Hilfe einer Switch-Anweisung ausgewertet. +Handelt es sich beim Op-Code um den Code OpPoll(0x2000), so wird als Antwort darauf ein ArtPollReply-Paket gesendet. +Dies übernimmt die Methode \lstinlinemap{sendArtPollReply}, welche in Quellcode \ref{src_sendArtPollReply} abgebildet ist. \breath + +\begin{lstlisting}[style=cpp, caption={Auszug aus der Methode sendArtPollReply.}, label=src_sendArtPollReply] +int packageSize = 236; +ArtPollReply artPollReply; +// set controller ip +for(int i = 0; i < 4; i++) +{ + artPollReply.IpAddress[i] = this->nodeIpAddress[i]; +} +char* longName = "KIWI (is an) Illumination Weeny Interface"; +[...] +// set mac address +for(int i = 0; i < 6; i++) +{ + artPollReply.Mac[i] = this->mac[i]; +} +uint8_t udpSendData[packageSize]; +this->parseFromArtPollReply(artPollReply, updSendData, packageSize); +IPAddress remoteIp = IPAddress(this->controllerIpAddress); +this->udp.beginPacket(remoteIp, UDP_PORT_ADRESS); +this->udp.write(updSendData, packageSize); +this->udp.endPacket(); +\end{lstlisting} + +In Zeile 2 des Quellcodes \ref{src_sendArtPollReply} wird eine neue Struktur vom Typen \lstinlinemap{ArtPollReply} erstellt, welche in der Datei \lstinlinemap{ArtNetPackageTypes.h} definiert ist. +Alle Felder in der Struktur besitzen bereits einen Standardwert, der nun mit den korrekten Werten überschrieben werden muss. +Die For-Schleife in Zeile 4 bis 7 setzt z.~B. die IP-Adresse des Controllers, von dem das ArtPoll-Paket empfangen wurde. +Sind alle Werte im Paket gesetzt, wird dieses mit Hilfe der Methode \lstinlinemap{parseFromArtPollReply} zu einem \lstinlinemap{uint8_t}-Array umgewandelt (siehe Zeile 16). +Zu jedem Pakettypen, der versendet wird, existiert eine \lstinlinemap{parseFrom}-Methode, die eine Struktur des Pakettypen erhält und diese entsprechend der Paketdefinition in ein \lstinlinemap{uint8_t}-Array umwandelt. +Manche Pakettypen besitzen Felder, die nicht zwingend mitübertragen werden müssen. +Damit die Methode unterscheiden kann, welche Felder mitgesendet werden sollen, erhält sie die gewünschte Anzahl der Bytes, die das Paket lang ist. +Mit dieser Anzahl und der Definition des Pakettypen kann ermittelt werden, welche Felder übertragen werden und welche nicht. +Quellcode \ref{src_parseFromArtPollReply} stellt eine gekürzte Form der Methode \lstinlinemap{parseFromArtPollReply} dar. \breath + +\begin{lstlisting}[style=cpp, caption={Auszug aus der Methode parseFromArtPollReply.}, label=src_parseFromArtPollReply] +if(length >= 207){ + // id + for(int i = 0; i<8; i++) { + udpSendData[i] = artPollReply.Id[i]; + } + // op code + udpSendData[8] = artPollReply.OpCode; + udpSendData[9] = artPollReply.OpCode >> 8; + // node ip + for(int i= 0; i < 4; i++) { + udpSendData[10+i] = artPollReply.IpAddress[i]; + } + [...] + // net address + udpSendData[18] = artPollReply.NetSwitch; + // sub net address + udpSendData[19] = artPollReply.SubSwitch; + [...] +} +if(length >= 208){ + // bind ip + for (int i = 0; i < 4; i++) { + udpSendData[207+i] = artPollReply.BindIp[i]; + } +} +if(length >= 212){[...]} +[...] +\end{lstlisting} + +Abhängig von der an die Methode übergebenen Länge des Pakets, werden weitere Felder des Pakets zum Byte-Array hinzugefügt (vgl. Zeile 1, 20 und 26 des Quellcodes \ref{src_parseFromArtPollReply}). +Für die Umwandlung von eingehenden Art-Net-Paketen in die entsprechende Struktur werden die \lstinlinemap{parseTo}-Methoden verwendet. +Diese sind im Kern identisch zu den \lstinlinemap{parseFrom}-Methoden aufgebaut, mit dem Unterschied, dass nun vom Byte-Array in die Struktur geschrieben, statt gelesen wird. \breath + +Das in der Auswertung und für den Versand nötigen Erstellung komplexeste Paket ist das Paket ArtCommand. +Dieses enthält einen String, welcher aus einem Befehlswort (command) und den Werten des Befehls (values) besteht. Die Werte werden durch ein JSON-Objekt dargestellt. \par +\pagebreak +Ein ArtCommand kann auch mehrere Befehle übertragen, welche durch das \&-Zeichen separiert werden. +Abbildung \ref{fig_SyntaxDiagramm_ArtCommand} zeigt ein Syntax-Diagramm eines ArtCommands. \par + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth, clip, trim=0 22cm 0 1cm] {./Medien/SyntaxdiagrammArtCommand.pdf} + \caption{Syntax-Diagramm des Befehlsstrings eines ArtCommands.} + \label{fig_SyntaxDiagramm_ArtCommand} + \end{center} +\end{figure} + +Quellcode \ref{src_processArtCommandLCU} zeigt die Verarbeitung eines eingehenden ArtCommands. +Der Befehlsstring wird zuerst an allen Stellen geteilt, an denen ein \&-Zeichen steht. +Dies wird mit Hilfe des Befehls \lstinlinemap{strtok} ermöglicht. +In Zeile 3 wird der Befehlsstring geladen und der Teilstring zurückgegeben. +Sofern dieser ungleich \lstinlinemap{NULL} ist, wird er innerhalb der While-Schleife weiter verarbeitet. +In Zeile 37 wird der nächste Teilstring geladen und die Schleife beginnt von vorne. +Wurde ein Teilstring erfolgreich geladen, wird er in den Befehl und die Werte aufgeteilt (vgl. Zeile 5 bis 16). +Die Bibliothek ArduinoJson von Benoît Blanchon wandelt mit dem Befehl \lstinlinemap{deserializeJson} den JSON-String in ein StaticJsonDocument um (siehe Zeile 17). +Anschließend kann mit Hilfe der JSON-Keys auf die Werte zugegriffen werden. +Die Strukturen und deren Keys der verschiedenen ArtCommands sind in der Datei \lstinlinemap{ArtCommands.h} enthalten. \breath + +\begin{lstlisting}[style=cpp, caption={Auszug aus der Methode processArtCommand.}, label=src_processArtCommandLCU] +ArtCommand artCommand; +artCommand = this->parseToArtCommand(updData, length); +char *commandString = strtok(artCommand.Data, "&"); +while (commandString != NULL) { + String command = String(commandString) + .substring(0, String(commandString) + .indexOf('=')); + int commandValuelength = (String(commandString) + .substring(String(commandString) + .indexOf('=')+1)) + .length() + 1; + char commandValue[commandValuelength]; + String(commandString) + .substring(String(commandString) + .indexOf('=')+1) + .toCharArray(commandValue, commandValuelength); + deserializeJson(doc, commandValue, commandValuelength); + + if(command.equals(ART_COM_AP)) { + this->presetRepository + ->activatePreset( + doc[activatePresetStructure().presetId]); + } + [...] + else if(command.equals(ART_COM_SP)){ + this->presetRepository + ->setPresetGroupId( + doc[setPresetStructure().presetId], + doc[setPresetStructure().groupId]); + this->presetRepository + ->setPresetChannelValue( + doc[setPresetStructure().presetId], + doc[setPresetStructure().channel], + doc[setPresetStructure().value]); + } + [...] + commandString = strtok(NULL, "&"); +} +\end{lstlisting} + +Damit die Lichtsteuersoftware nach dem Verbindungsaufbau weiß, welche Presets bereits aktiv sind, kann sie ein ArtDataRequest-Paket senden. +In diesem Paket ist ein Request-Code enthalten, der in Tabelle \ref{tab_DataRequest_Codes} beschrieben ist. +Der Bereich von 0x8000 bis 0xFFFF ist für die herstellerspezifische Nutzung vorgesehen. +Mit dem Request-Code 0x8000 fragt man den aktuellen Preset-Status an. +Die Lichtsteuereinheit antwortet anschließend mit einem ArtDataReply-Paket darauf. +In diesem Paket ist eine Payload enthalten, die sechs Bytes groß ist. +Jedes Byte gibt hierbei den Status eines Presets an. +Das Byte kann die drei Werte inaktiv(0), aktiv(1) oder teilaktiv(2) enthalten. \ No newline at end of file diff --git a/doc/projectDocumentation/Bachlor-Thesis.pdf b/doc/projectDocumentation/Bachlor-Thesis.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0c0c68efb3ac8926834ed2e960b2a071c4d6e99c Binary files /dev/null and b/doc/projectDocumentation/Bachlor-Thesis.pdf differ diff --git a/doc/projectDocumentation/Bachlor-Thesis.tex b/doc/projectDocumentation/Bachlor-Thesis.tex new file mode 100644 index 0000000000000000000000000000000000000000..255ab60131124dc759d48f2ce26a278fafef8a53 --- /dev/null +++ b/doc/projectDocumentation/Bachlor-Thesis.tex @@ -0,0 +1,79 @@ + +%% Eigenschaften setzen +\input{einstellungen} + +%% Dokument vorbereiten +\input{preambel} + +\begin{document} + + %% Titelseite automatisch erzeugen + %% Abstract muss noch geschrieben werden + \input{prefix} + + \section{Einleitung} + \label{sec_Einleitung} + \input{Einleitung} + \pagebreak + + \section{Lichtsteuerung im Heimbereich} + \label{sec_Lichtsteuerung_im_Heimbereich} + \input{Lichtsteuerung_im_Heimbereich} + \pagebreak + + \section[Netzwerkkommunikationsprotokoll des Heim\-ill\-uminationssystems]{\texorpdfstring{Netzwerkkommunikationsprotokoll\\ des Heimilluminationssystems}{Netzwerkkommunikationsprotokoll des Heimilluminationssystems}} + \label{sec_Netzwerkkommunikationsprotokoll_des_Heimilluminationssystems} + \input{Netzwerkkommunikationsprotokoll_des_Heimilluminationssystems} + \pagebreak + + + \section{Aufbau der lokalen Lichtsteuereinheit} + \label{sec_Aufbau_der_lokalen_Lichtsteuereinheit} + \input{Aufbau_der_lokalen_Lichtsteuereinheit} + \pagebreak + + \section{Aufbau der Lichtsteuersoftware} + \label{sec_Aufbau_der_Lichtsteuersoftware} + \input{Aufbau_der_Lichtsteuersoftware} + \pagebreak + + \section{Aktuelle Herausforderungen} + \label{sec_Aktuelle_Herausforderungen} + \input{Aktuelle_Herausforderungen} + \pagebreak + + \section{Fazit und Ausblick} + \label{sec_Fazit_und_Ausblick} + \input{Fazit_und_Ausblick} + \pagebreak + + \section*{Anhang} + \addcontentsline{toc}{section}{\protect\numberline{}Anhang} + \renewcommand{\thesubsection}{\Alph{subsection}} + \appendix + + \printbibliography[title={Literaturverzeichnis},heading=subbibnumbered] + + \subsection{Abbildungsverzeichnis} + \vspace{-48pt} + \listoffigures + + \subsection{Tabellenverzeichnis} + \vspace{-48pt} + \listoftables + + \subsection{Abkürzungsverzeichnis} + \begin{acronym}\itemsep-20pt + \input{./Abkürzungen.tex} + \end{acronym} + + + \subsection{Quellcodeverzeichnis} + \vspace{-48pt} + \lstlistoflistings + \clearpage + + \thispagestyle{withoutPageNumber} + \input{Eidesstattliche_Erklärung} + +\end{document} \ No newline at end of file diff --git "a/doc/projectDocumentation/Eidesstattliche_Erkl\303\244rung.tex" "b/doc/projectDocumentation/Eidesstattliche_Erkl\303\244rung.tex" new file mode 100644 index 0000000000000000000000000000000000000000..9a2bb117d6dc20e864c55f63b018a44f4ff61c64 --- /dev/null +++ "b/doc/projectDocumentation/Eidesstattliche_Erkl\303\244rung.tex" @@ -0,0 +1,30 @@ +%%%%%%%%%%%%%%%%%%% +\section*{Eidesstattliche Erklärung} +% +Ich versichere, dass ich die Arbeit selbständig verfasst und keinen als die angegebenen Quellen und Hilfsmittel benutzt sowie Zitate kenntlich gemacht habe. +% +\bigskip + +Die Regelungen der geltenden Prüfungsordnung zu Versäumnis, Rücktritt, Täuschung und Ordnungsverstoß habe ich zur Kenntnis genommen. +% +\bigskip + +Diese Arbeit hat in gleicher oder ähnlicher Form keiner Prüfungsbehörde vorgelegen. +% +\bigskip + +%Ich versichere, die von mir vorgelegte Arbeit selbstständig verfasst zu haben. +%Alle Stellen, die wörtlich oder sinngemäß aus veröffentlichten oder nicht veröffentlichten +%Arbeiten anderer entnommen sind, +%habe ich als entnommen kenntlich gemacht. +%Sämtliche Quellen und Hilfsmittel, die ich für die Arbeit benutzt habe, sind angegeben. +%Die Arbeit hat mit gleichem Inhalt bzw. in wesentlichen Teilen noch keiner anderen Prüfungsbehörde vorgelegen. +% + +\vspace{3cm} +Heiligenhaus, den +\underline{\hspace*{3cm}} +\hfill +\begin{tabular}[t]{@{}l@{}}\hline +\hspace*{2.5cm}Unterschrift\hspace*{2.5cm} +\end{tabular} diff --git a/doc/projectDocumentation/Einleitung.tex b/doc/projectDocumentation/Einleitung.tex new file mode 100644 index 0000000000000000000000000000000000000000..e34e2bb9fdf66cbc3edac40e269aa25ef2392616 --- /dev/null +++ b/doc/projectDocumentation/Einleitung.tex @@ -0,0 +1,55 @@ +In der Vergangenheit entwickelte der Autor bereits im Rahmen des +Software-Ent\-wick\-lungs\-pro\-jekts und des Moduls \emph{Algorithmen und Datenstrukturen} eine Lichtsteuersoftware und eine Lichtsteuereinheit, die über +\ac{usb} mit der Software verbunden ist. Die Lichtsteuereinheit steuert +angeschlossene Lampen über das Protokoll \ac{dmx}-512 (vgl. \cite{ALDS} und \cite{SWEP}).\par +Die folgende Ausarbeitung stellt dar, wie die Lichtsteuersoftware mit der +Lichtsteuereinheit anstelle über \ac{usb} über ein lokales Netzwerk +kommuniziert. + +\subsection{Motivation} +\label{sec_Motivation} +Die \ac{ifa} ist eine Messe, bei der Hersteller ihre neuesten Produkte und +Konzepte, unter anderem in den Bereichen Home-Entertainment, Multimedia und +Haushaltselektronik, vorstellen. Der Begriff \glqq Smart~Home\grqq\space hat +hierbei in den letzten Jahren immer mehr an Präsenz dazugewonnen. Alle Geräte sind +untereinander vernetzt, um Prozesse und Abläufe im Alltag zu optimieren. Ein +Teilbereich dieser Thematik ist die Lichtsteuerung. Die Lampe im Wohnzimmer kann +nun mit der Handy-\ac{app} eingeschaltet werden und leuchtet in der zum Film +passenden Farbe. Nachteilig an vielen Produkten im Bereich der Lichtsteuerung +ist die Bindung an den Hersteller und die singuläre Art der Steuerung. Viele +Produkte verschiedener Hersteller sind ohne weiteres nicht miteinander kompatibel, da die Kommunikationsprotokolle meist proprietär und die Spezifikationen dieser nicht immer öffentlich zugänglich sind. +Zudem ermöglichen viele \acp{app} nur das Steuern einzelner Lampen, so dass diese nicht in Kombination oder Gruppen gesteuert werden können.\breath + +Das Software-Entwicklungsprojekt des Autors beschreibt, zusammen mit der +Ausarbeitung im Modul \emph{Algorithmen und Datenstrukturen}, einen Ansatz, mit dem eine Heimbeleuchtung mit Hilfe des Steuerprotokolls \ac{dmx}-512 ermöglicht wird und somit vom Hersteller unabhängig ist. Im Rahmen dieser Arbeiten wurde mit Hilfe des menschzentrierten Gestaltungsprozesses eine Nutzungsweise eines sogenannten Heimilluminationssystems ermittelt. +Auf Grundlage der ermittelten Nutzungsweise wurde eine Lichtsteuersoftware und eine Lichtsteuereinheit entwickelt. Zusammen ermöglichen diese einem Benutzer eine gruppenbasierte (Gruppe von Lampen) Lichtsteuerung von \ac{dmx}-fähigen Endgeräten.\breath + +In der bisherigen Systemarchitektur kommuniziert die Lichtsteuersoftware mit der +Lichtsteuereinheit über \ac{usb}. Somit muss sich die Lichtsteuereinheit in der +Nähe des Computers befinden, auf dem die Steuersoftware ausgeführt wird, um eine +Verbindung herzustellen. Das verwendete Kommunikationsprotokoll über \ac{usb} +ist proprietär, wodurch die Nutzung von anderer Hard- oder Software erschwert +wird. Auch ist es in der bisherigen Systemarchitektur nicht möglich, mehrere +Lichtsteuereinheiten mit der Software zu verbinden.\par +Eine netzwerkbasierte Kommunikation mit Hilfe eines bereits etablierten +Protokolls zur Übertragung von \ac{dmx}-Werten ermöglicht eine Lichtsteuerung +mit mehreren, ortsunabhängigen Lichtsteuereinheiten, die sowohl mit Hard- als auch +Softwareprodukten weiterer Hersteller kombiniert werden kann. + +\subsection{Aufgabenstellung und Zielsetzung} +\label{sec_Aufgabenstellung_und_Zielsetzung} +In dieser Arbeit soll das zuvor verwendete \ac{usb}-Kommunikationsprotokoll zwischen der Lichtsteuersoftware und der Lichtsteuereinheit durch ein netzwerkbasiertes Kommunikationsprotokoll ersetzt werden. Im Zuge dieser Änderungen werden Anpassungen an der Lichtsteuersoftware und Lichtsteuereinheit durchgeführt.\par +Im Software-Entwicklungsprojekt hat der Autor den Softwarekern (Programmlogik mit einer Kommandozeilen-Eingabe) separat von der Benutzerschnittstelle entwickelt. In dieser Arbeit soll mit dem Model-View-ViewModel-Entwurfsmuster eine Verbindung zwischen dem Softwarekern und der Benutzerschnittstelle erstellt werden.\par +Genau wie im Software-Entwicklungsprojekt ist die Zielgruppe dieses Systems die der Hobby- und Amateurbastler. Benutzer müssen das System um weitere Endgeräte und Systemeigenschaften erweitern können. Somit sollten möglichst offene Standards gewählt werden, die Hobby- und Amateurbastlern leicht nutzen können. \breath + +Ziel dieser Arbeit ist eine Lichtsteuersoftware für den Heimbereich, die über ein standardisiertes Netzwerkprotokoll mit der Lichtsteuereinheit kommunizieren kann und eine Benutzerschnittstelle besitzt, die nach den Design- und Interaktionsprinzipien des Curriculum \texttt{CPUX-DS} und der Norm \texttt{DIN EN ISO 9241-110} gestaltet wurde.\par +Unter Beachtung des Umfangs der Arbeit wird angenommen, dass nur ein Typ von Endgerät verwendet wird. Dies setzt den Schwerpunkt der Arbeit auf die Kommunikation zwischen der Lichtsteuersoftware und den Lichtsteuereinheiten, schränkt die Funktionalität der Software aber nicht in großem Maße ein. + +\subsection{Vorgehensweise und Aufbau der Arbeit} +\label{sec_Vorgehensweise_und_Aufbau_der_Arbeit} +Einleitend stellt die Arbeit in Kapitel \ref{sec_Lichtsteuerung_im_Heimbereich} die Architektur eines Heimilluminationssystems dar, damit die folgenden Themen korrekt verstanden und eingeordnet werden können. Hierbei werden das Prinzip des Steuerprotokolls \ac{dmx}-512 grundlegend erläutert und die Vorteile der Verwendung einer netzwerkbasierte Steuerung in Bezug auf das aktuelle Heimilluminationssystem begründet.\par +Weiterführend werden in Kapitel \ref{sec_Netzwerkkommunikationsprotokoll_des_Heimilluminationssystems} die Anforderungen an ein Kommunikationsprotokoll zwischen Lichtsteuersoftware und den Lichtsteuereinheiten dargestellt. Diese sind auf Grundlage der im menschzentrierten Gestaltungsprozess erarbeiteten Nutzungsanforderungen entwickelt. Anschließend werden die Protokolle \emph{Art-Net}, \emph{sACN} bzw. \emph{ANSI E1.31-2018} und MA-Net/ ETCNet dargestellt und mit den Anforderungen verglichen. Abgeschlossen wird das Kapitel mit der Evaluation und der damit verbundenen Auswahl eines Protokolls.\par +Kapitel \ref{sec_Aufbau_der_lokalen_Lichtsteuereinheit} dokumentiert die Struktur der lokalen Steuereinheit mit netzwerkbasiertem Kommunikationsprotokoll. Im Kapitel ist sowohl der Aufbau der Hardware dokumentiert, als auch die Darstellung und Erläuterung der verwendeten Datenstrukturen. Ebenfalls wird erläutert, wie das Netzwerkprotokoll in die Lichtsteuereinheit integriert ist.\par +Ergänzend dazu beschreibt Kapitel \ref{sec_Aufbau_der_Lichtsteuersoftware} die Strukturen der Lichtsteuersoftware. Das Kapitel erläutert die Zusammenhänge der Softwarearchitektur und der Datenstrukturen und stellt die verschiedenen Aspekte der Benutzerschnittstelle dar. Auch zeigt das Kapitel, wie die netzwerkbasierte Kommunikation in der Software integriert ist und wie der Softwarekern mit der Benutzerschnittstelle mit Hilfe des Model-View-ViewModel-Entwurfsmusters verbunden ist.\par +Die Herausforderungen, die bei hoher Netzwerkbelastung der Lichtsteuereinheit entstehen und bei Animationen von Grafikelementen sowie bei Aktualisierungen von Listen der Benutzeroberfläche, werden in Kapitel \ref{sec_Aktuelle_Herausforderungen} beschrieben.\par +Abschließend stellt Kapitel \ref{sec_Fazit_und_Ausblick} das Fazit zum Projekt dar und gibt einen Ausblick für weitere Optimierungen in der Zukunft. \ No newline at end of file diff --git a/doc/projectDocumentation/Fazit_und_Ausblick.tex b/doc/projectDocumentation/Fazit_und_Ausblick.tex new file mode 100644 index 0000000000000000000000000000000000000000..774b473f19052053ddd8d4abd6ed6aa101bf595a --- /dev/null +++ b/doc/projectDocumentation/Fazit_und_Ausblick.tex @@ -0,0 +1,27 @@ +Zusammenfassend lässt sich das Ergebnis dieser Arbeit als erfolgreich bezeichnen. +Im Rahmen der Arbeit wurde ein etabliertes und standardisiertes Netzwerkprotokoll ermittelt, mit dem Lampen in einem Heimilluminationssystem gesteuert werden können. +Das ermittelte Protokoll Art-Net ist in die lokale Lichtsteuereinheit und die Lichtsteuersoftware integriert. +Der Softwarekern der Lichtsteuereinheit ist mit der Benutzeroberfläche mit Hilfe des Model-View-ViewModel-Entwurfsmusters verbunden.\breath + +Beim Dauerbetrieb der Lichtsteuereinheit wurden Performance-Engpässe beobachtet, die in Kapitel \ref{sec_Leistungsenpass_Lichtsteuereinheit} beschrieben sind. +Auch sind manche Animationen und Listenaktualisierungen in der Benutzeroberfläche noch fehlerhaft (siehe Kapitel \ref{sec_Grafikanimationen_Listenaktualisierungen}).\breath + +Unabhängig von diesen Herausforderungen kann die Lichtsteuersoftware mit einem handelsüblichen Art-Net-Interface betrieben und zum Steuern des Heimilluminationssystems genutzt werden. +Sämtlicher Quellcode zum entwickelten Heimilluminationssystem steht unter der MIT-Lizenz und ist unter dem folgenden Link öffentlich zugänglich: +\begin{center} + \url{https://gitlab.cvh-server.de/sboettger/kiwi-home-light-control-system} +\end{center} + +In der Zukunft könnten folgende Aspekte am System noch verbessert werden: +\begin{itemize} + \item Stabile Paketverarbeitung der Lichtsteuereinheit + \item Verbesserte Grafikanimation von JavaFX-Elementen + \item Korrekte Aktualisierung von Listen auf der Benutzeroberfläche + \item Speichern und Laden der aktuellen Konfiguration der Lichtsteuersoftware + \item Verbesserte Usability der Benutzeroberfläche + \begin{itemize} + \item Duplizieren von Gruppen + \item Hinweisfelder für zusätzliche Beschreibungen von Funktionen + \item Erstellen von Lichtszenen auf Grundlage der aktuell eingestellten Beleuchtung + \end{itemize} +\end{itemize} \ No newline at end of file diff --git a/doc/projectDocumentation/Lichtsteuerung_im_Heimbereich.tex b/doc/projectDocumentation/Lichtsteuerung_im_Heimbereich.tex new file mode 100644 index 0000000000000000000000000000000000000000..51c56b277671ac8e88f5452db954d500b80f7738 --- /dev/null +++ b/doc/projectDocumentation/Lichtsteuerung_im_Heimbereich.tex @@ -0,0 +1,210 @@ +Das Thema dieser Arbeit liegt im Kontext der Beleuchtung im Heimbereich. +Damit die Inhalte zur Lichtsteuereinheit und der Lichtsteuersoftware besser eingeordnet und verstanden werden können, wird im folgenden Kapitel \ref{sec_Architektur_des_Heimilluminationssystems} die grundlegende Architektur eines Heimilluminationssystems erläutert. +Bestandteil der Architektur ist das Steuerprotokoll \ac{dmx}-512, welches in Kapitel \ref{sec_DMX-512_als_Steuerprotokoll} detaillierter erklärt wird. +Aufbauend auf den Titel der Arbeit, stellt Kapitel \ref{sec_Vorteile_einer_netzwerkbasierten_Kommunikation} die Vorteile einer netzwerkbasierten Kommunikation innerhalb eines Heimilluminationssystems dar. + +\subsection{Architektur des Heimilluminationssystems} +\label{sec_Architektur_des_Heimilluminationssystems} +Beleuchtungssysteme existieren in den verschiedensten Bereichen. +Eine sehr große Sparte ist zum Beispiel die Beleuchtung bei Veranstaltungen, wie Konzerten, Musicals und weiteren Events. +Diese Systeme arbeiten häufig mit sehr vielen verschiedenen Endgeräten, die eine Menge an steuerbaren Eigenschaften (Farbe, Helligkeit, Ausrichtung der Lampe, Fokus, Zoom etc.) besitzen. +Diese Endgeräte werden vielseitig eingesetzt und bei der Steuerung werden verschiedene Typen von Endgeräten miteinander kombiniert, um die passende Beleuchtung für die Veranstaltung zu erhalten.\par +Dem gegenüber stehen Beleuchtungssysteme in Industrien und Einrichtungen, wie zum Beispiel Fabrikhallen oder Schulen. +Diese Systeme steuern zentral die Lichtquellen im Gebäude und besitzen häufig Funktionen, wie zeitgesteuertes Ein- und Ausschalten von Lampen in einem bestimmten Bereich. +Die Endgeräte dieser Systeme sind meist recht simpel und besitzen nur eine Helligkeitsregelung. +Einzelne Lampen werden als Gruppe zusammengeschlossen, um diese gemeinsam zu steuern. +So werden in einer Schule zum Beispiel alle Lampen in der Mensa ab 15 Uhr ausgeschaltet. +Die Lampen in den Klassenräumen ab 18 Uhr und ab 20 Uhr leuchten nur noch einzelne Lampen in den Fluren, um die Notbeleuchtung zu gewährleisten.\breath + +Die Beleuchtung im Heimbereich (vor allem im Kontext von \glqq Smart Home\grqq) nutzt Elemente aus beiden genannten Systemen. +Das Software-Entwicklungsprojekt des Autors beschreibt einen Nutzungskontext und eine Nutzungsweise für ein Beleuchtungssystem im Heimbereich, die durch den menschzentrierten Gestaltungsprozess erarbeitet wurden. +In diesem Nutzungskontext wird beschrieben, dass Lampen im Heimbereich häufig mehrere Funktionen besitzen. +Es müssen die Farbe, Helligkeit und eventuell auch Effekte, wie Blinken eingestellt werden können. +Die Steuerung dieser Lampen erfolgt gruppenweise. +Die meisten Gruppen von Lampen entsprechen realen Abgrenzungen, wie Räumen, Etagen oder sonstigen Bereichen. +Die Gruppen werden unabhängig voneinander gesteuert, so dass die Steuerung des Lichts im Wohnzimmer nicht das Licht in der Küche beeinflusst. +Innerhalb einer Gruppe werden Lampen zum einen identisch angesteuert (alle Lampen erhalten die selben Eigenschaftswerte für Farbe, Helligkeit und Effekt) und zum anderen aber auch individuell (alle Lampen erhalten eigene Eigenschaftswerte für Farbe, Helligkeit und Effekt).\par +Der letzte Aspekt des Nutzungskontexts ist die dezentrale Steuerung. +Das Licht muss dort gesteuert werden können, wo der Nutzer sich aufhält. +Somit reicht eine zentrale Steuerkonsole oder Steuersoftware nicht aus. +Der Benutzer benötigt die Möglichkeit, am aktuellen Standort eine zuvor eingestellte Konfiguration der Lampen abzurufen. +Mit Grundlage dieses Nutzungskontexts und den daraus entsprechenden Nutzungserfordernissen entsteht das sogenannte \emph{Heimilluminationssystem}. +Abbildung \ref{fig_Systemarchitektur} zeigt die Systemarchitektur des Heimilluminationssystems. + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth, clip, trim=0 70pt 0 80pt]{./Medien/Systemübersicht.pdf} + \caption{Systemarchitektur eines Heimilluminationssystems} + \label{fig_Systemarchitektur} + \end{center} +\end{figure} + +Das Heimilluminationssystem ist in drei ineinander verschachtelte Bereiche aufgeteilt. +Der innerste Bereich ist die \emph{Applikation}. +Bei der Applikation handelt es sich um eine Lichtsteuersoftware, mit der die Werte für die verschiedenen Lampen eingestellt und gespeichert werden können. +Beim Speichern der Werte gibt es zwei Möglichkeiten:\par +\begin{table}[H] + \begin{tabular}{lp{11,4cm}} + \textbf{Lichtstimmung} & Bei der Lichtstimmung werden allen Lampen einer Gruppe die selben Eigenschaftswerte zugewiesen. Sie kann genutzt werden, um einen Raum in einer einheitlichen Farbe und Helligkeit zu beleuchten.\\ + \\ + \textbf{Komposition} & Bei einer Komposition werden jeder Lampe einer Gruppe individuelle Eigenschaftswerte zugewiesen. Sie kann genutzt werden, um einen Raum präzise zu beleuchten. + \end{tabular} +\end{table} + +Der nächste Bereich ist die \emph{Lichtsteuerung}. +Diese umfasst die Lichtsteuersoftware und die Lichtsteuereinheiten. +Die Lichtsteuersoftware kommuniziert mit den Lichtsteuereinheiten über ein festgelegtes Kommunikationsprotokoll. +Eine Lichtsteuereinheit hat zwei Funktionen. +Zum einem übermittelt sie mit Hilfe eines Steuerprotokolls die von der Lichtsteuersoftware festgelegten Eigenschaftswerte an die Lampen. +Zum anderen stellt sie dem Benutzer Schnellauswahltasten zur Verfügung, mit denen dieser im Vorhinein ausgewählte Lichtstimmungen oder Kompositionen einer Gruppe aktivieren oder deaktivieren kann. +Die Kombination aus Gruppe und Lichtstimmung oder Komposition heißt \emph{Preset}.\par +Der letzte Bereich ist das Heimilluminationssystem selbst. +Es umfasst die gesamte Lichtsteuerung und alle damit verbundenen Endgeräte. +Im Rahmen dieser Ausarbeitung wird nur ein Typ von Endgerät verwendet. +Hierbei beschränkt sich die Funktion des Endgerätes auf die drei Farbwerte rot, grün und blau, den Helligkeitswert und die Blinkrate. + +\subsection{\acs{dmx}-512 als Steuerprotokoll} +\label{sec_DMX-512_als_Steuerprotokoll} + +Das Steuerprotokoll \ac{dmx}-512 (abgekürzt auch nur \ac{dmx} genannt) wird durch die Norm \texttt{DIN 56930-2} definiert (vgl. \cite{DIN_56930-2}). +Das Protokoll dient \textit{\glqq zur Verbindung von Lichtsteuerungen und Dimmern oder anderer angeschlossener Peripherie bei professioneller Anwendung in Veranstaltungs- und Produktionsstätten, z. B. in Theatern, Mehrzweckhallen, Studios und Diskotheken\grqq}(\cite[S.1 Abschnitt 1]{DIN_56930-2}). +Das Protokoll überträgt bis zu 512 sogenannter Kanäle, die zusammen als \ac{dmx}-Universum oder \ac{dmx}-Frame bezeichnet werden. +Jeder dieser Kanäle enthält einen 8-Bit-Wert. +Den angeschlossenen Endgeräten werden Kanalbereiche zugewiesen, um über diese Kanäle die Funktionen der Endgeräte zu steuern. +Tabelle \ref{tab_Beispiel_DMX_Kanalbelegung} zeigt einen Ausschnitt einer beispielhaften Belegung eines \ac{dmx}-Universums.\breath + +Vorteile des \ac{dmx}-Protokolls sind der simple Aufbau, die daraus resultierende Geräte- und Funktionsunabhängigkeit und die große Vielfalt an Produkten, die \ac{dmx} unterstützen. +Ein Kanal im Protokoll hat keine festgelegte Funktion, da die Funktionszuordnung des Kanals erst durch das Endgerät definiert wird. +Somit ist das Protokoll nicht nur auf die Steuerung von Lampen beschränkt, sondern kann auch für weitere Endgeräte genutzt werden. +Die Steuerung eines Rollladens oder einer Markise sind mögliche Anwendungsfälle. +Auch können zwei oder mehr Kanäle zusammen genutzt werden um eine höhere Auflösung als 8-Bit zu erreichen. +Nicht \ac{dmx}-fähige Endgeräte können leicht mit Hilfe eines kleinen Mikrocontrollers auf \ac{dmx} umgerüstet werden. +Dies lädt viele Hobby- und Amateurbastler dazu ein, das Protokoll für kleine Heimprojekte zu verwenden.\breath + +Alternative Steuerprotokolle im Bereich von \glqq Smart Home\grqq \space sind zum Beispiel \emph{ZigBee} von der ZigBee Alliance und \emph{Matter} von der \ac{csa}. +Diese Protokolle unterstützen die Ansteuerung von zahlreichen Smart-Home-Geräten. +Allerdings haben diese Protokolle bezogen auf das Ziel dieser Ausarbeitung einige Nachteile gegenüber \ac{dmx}-512.\par + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + C{1.5cm} + >{\raggedright}m{4cm} + >{\raggedright}m{4cm} + >{\raggedright}m{4cm} + } + + \toprule + \rowcolor[gray]{.9} + \textbf{\acs{dmx}-Kanal}& + \textbf{LED-Scheinwerfer}& + \textbf{LED Moving Head}& + \textbf{4-Kanal Dimmer} + \tabularnewline\bottomrule + 1&Intensität rot&& + \tabularnewline\midrule + 2&Intensität grün&& + \tabularnewline\midrule + 3&Intensität blau&& + \tabularnewline\midrule + 4&Intensität gesamt&& + \tabularnewline\midrule + 5&Blinkrate&& + \tabularnewline\midrule + 6&&Intensität rot& + \tabularnewline\midrule + 7&&Intensität grün& + \tabularnewline\midrule + 8&&Intensität blau& + \tabularnewline\midrule + 9&&Intensität gesamt& + \tabularnewline\midrule + 10&&Pan& + \tabularnewline\midrule + 11&&Tilt& + \tabularnewline\midrule + 12&&&Intensität Kanal 1 + \tabularnewline\midrule + 13&&&Intensität Kanal 2 + \tabularnewline\midrule + 14&&&Intensität Kanal 3 + \tabularnewline\midrule + 15&&&Intensität Kanal 4 + \tabularnewline\bottomrule + + \end{tabular} + \caption{Beispielhafte Kanalbelegung eines \ac{dmx}-Universums} + \label{tab_Beispiel_DMX_Kanalbelegung} + \end{center} +\end{table} + +Der Aufbau von Matter und ZigBee ist recht komplex und beinhaltet viele Mechanismen und Methoden, die es für Hobby- und Amateurbastler erschweren das Protokoll selbstständig im Heimnetz umzusetzen. +Beide Protokolle verfügen über Verschlüsselungsprinzipien und Authentifizierungsprozesse, um eine sichere Kommunikation mit vertrauenswürdigen Endgeräten zu erreichen (vgl. \cite[Kapitel~4]{ZigBee} und \cite[Kapitel~2.7]{Matter-Core}). +Allerdings werden für diese Prozesse teilweise Zertifikate benötigt, die nur von den Urhebern des Protokolls (z. B. der \ac{csa}) ausgestellt werden können (vgl. \cite[Kapitel 2.6]{Matter-Core}). +Da das \ac{dmx}-Protokoll als kabelgebundene Kette zwischen den Endgeräten aufgebaut wird, werden hierbei keine weiteren Sicherheitsprozesse benötigt.\par +Häufig geben die Protokolle auch nur den Rahmen der Kommunikation vor, aber definieren nicht genauer in welcher Weise die eigentlichen Nutzdaten übertragen werden. +Diese Struktur ist somit weiterhin herstellerabhängig und muss auch nicht öffentlich zugänglich sein (vgl. \cite[Kapitel~1.1.3]{ZigBee}). +Eine Ausnahme bildet hier Matter. +Matter definiert mit sogenannten Device-Typen und Clustern, welche Daten für welche Art von Endgerät, wie übertragen werden. +Dies ist allerdings gleichermaßen auch wieder ein Nachteil, da somit nur vom Protokoll fest definierte Gerätetypen gesteuert werden können (vgl. \cite[Kapitel 3, S. 29]{Matter-Device}). +Durch die kanalbasierte Steuerung ermöglicht es \ac{dmx}, vollkommen geräte- und funktionsunabhängig zu sein. \breath + +Für diese Arbeit wird, wie in Kapitel \ref{sec_Aufgabenstellung_und_Zielsetzung} beschrieben, nur ein Typ von Endgerät verwendet. +Es handelt sich dabei um das Gerät \emph{Stairville xBrick Full-Colour Fluter 16x3W LED}. +Diese Lampe kann mit 5 \ac{dmx}-Kanälen gesteuert werden. +Die Belegung der Kanäle ist Tabelle \ref{tab_DMX_Kanalbelegung_XBrick} zu entnehmen. + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + C{2.5cm} + >{\raggedright}m{0.5cm} + >{\raggedright}m{5cm} + } + + \multicolumn{3}{c}{\textbf{\ac{dmx}-Belegung xBrick LED Fluter}}\\ + \toprule + \rowcolor[gray]{.9} + \acs{dmx}-Kanal&\space& + Funktion + \tabularnewline\bottomrule + 1&&Intensität rot + \tabularnewline\midrule + 2&&Intensität grün + \tabularnewline\midrule + 3&&Intensität blau + \tabularnewline\midrule + 4&&Intensität gesamt + \tabularnewline\midrule + 5&&Blinkrate + \tabularnewline\bottomrule + + \end{tabular} + \caption{\ac{dmx}-Kanalbelegung der Stairville xBrick Full-Colour Fluter} + \label{tab_DMX_Kanalbelegung_XBrick} + \end{center} +\end{table} + +\subsection{Vorteile einer netzwerkbasierten Kommunikation} +\label{sec_Vorteile_einer_netzwerkbasierten_Kommunikation} +Beim ursprünglichen Heimilluminationssystem wurde die Lichtsteuersoftware mit Hilfe eines proprietären Kommunikationsprotokolls über \ac{usb} mit der Lichtsteuersoftware verbunden. +Durch diese Verbindung entstehen folgende Nachteile:\par +\begin{itemize} + \item Die Lichtsteuereinheit muss sich in der Nähe des Computers befinden + \item Proprietäre Protokolle erschweren die Nutzung unterschiedlicher Hard- und Software + \item Es ist nicht möglich, mehrere Lichtsteuereinheiten mit der Software zu verbinden + \begin{itemize} + \item Dies liegt zum einen am Protokoll, aber auch an der begrenzten Anzahl der USB-Anschlüsse eines Computers + \end{itemize} +\end{itemize} + +Mit der Umstellung auf ein netzwerkbasiertes Protokoll für die Kommunikation kann die Entfernung zwischen dem Computer mit der Lichtsteuersoftware und der Lichtsteuereinheit erhöht werden. +Solange die Geräte Teilnehmer des selben \ac{lan} sind, ist deren geografische Entfernung zueinander irrelevant. +Zudem ermöglicht die Topologie eines \acp{lan} das Verbinden von (fast) beliebig vielen Lichtsteuereinheiten. +\footnote{Im privatem Umfeld ist ein /24-Netz üblich, was bis zu 256 Teilnehmer in einem Netz ermöglicht.} +Die Verwendung eines bereits etablierten Standardprotokolls ermöglicht die Nutzung von weiterer Hard- und Software.\breath + +Um die Sicherheit in einem \ac{lan} zu gewährleisten, helfen in diesem Fall mehrere Aspekte. Ein Teilnehmer eines \acp{lan} muss entweder mit einem Kabel angeschlossen sein, oder erhält den Zugriff über \ac{wlan}. Im Falle des Kabelanschlusses ist die Sicherheitsmaßname der physikalische Zugang zum Netzwerk. +Ist dieser nicht gegeben, so kann keine Verbindung hergestellt werden. +Im Falle einer WLAN-Verbindung kann durch die Nutzung einer geeigneten Authentifizierungsmethode sichergestellt werden, dass keine unbefugten Geräte ins Netzwerk gelangen.\par +Zusammenfassend lässt sich sagen, dass die Nutzung eines Netzwerks zur Kommunikation zwischen der Lichtsteuersoftware und Lichtsteuereinheit die genanten Nachteile der \ac{usb}-Kommunikation ausgleicht und eine sichere und sinnvolle Lösung ist. \ No newline at end of file diff --git a/doc/projectDocumentation/Netzwerkkommunikationsprotokoll_des_Heimilluminationssystems.tex b/doc/projectDocumentation/Netzwerkkommunikationsprotokoll_des_Heimilluminationssystems.tex new file mode 100644 index 0000000000000000000000000000000000000000..531ae46c0b425631ab3298f1329c8d75bccb300f --- /dev/null +++ b/doc/projectDocumentation/Netzwerkkommunikationsprotokoll_des_Heimilluminationssystems.tex @@ -0,0 +1,843 @@ +Kapitel \ref{sec_Vorteile_einer_netzwerkbasierten_Kommunikation} erläutert, welche Vorteile eine netzwerkbasierte Kommunikation besitzt. +In diesem Kapitel werden verschiedene Netzwerkprotokolle evaluiert und die Auswahl des Protokolls Art-Net wird erläutert. +Die für die Evaluation der Protokolle benötigten Anforderungen werden in Kapitel \ref{sec_Anforderungen_des_Kommunikationsprotokolls} dargestellt. +In den Kapiteln \ref{sec_Art-Net}, \ref{sec_sACN_ANSI} und \ref{sec_MA-Net_ETCNet} werden die zur Auswahl stehenden Protokolle vorgestellt, damit Kapitel \ref{sec_Evaluation_und_Auswahl_des_Protokolls} fundiert die Evaluation der Protokolle darstellen kann. + +\subsection{Anforderungen des Kommunikationsprotokolls} +\label{sec_Anforderungen_des_Kommunikationsprotokolls} +Die Anforderungen an das Heimilluminationssystem sind mit Hilfe einer Satzschablone formuliert, die auch als User-Story bekannt ist. +Der Aufbau dieser Schablone ist im CPUX-UR Curriculum des UXQB e. V. definiert:\par +\begin{center} + \textit{\glqq Der Benutzer muss am System eine \textbf{<Information oder Ressource>} erkennen/auswählen/eingeben können unter \textbf{<Bedingung (optional)>}.\grqq\\\cite[S.~68]{CPUX-UR}} +\end{center} +Der \glqq Benutzer\grqq \space steht in dieser Satzschablone stellvertretend für eine Benutzergruppe. +Bei der Analyse des Nutzungskontextes ergeben sich folgende Benutzergruppen: +\begin{table}[H] + \begin{center} + \begin{tabular}{ + m{3.2cm} + m{11cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Benutzergruppe}&\textbf{Menschzentrierte Qualitätsziele}\tabularnewline \midrule + Heimanwender & + \begin{itemize}[left=0pt, itemsep=0pt] + \item Steuerung der Beleuchtung im Innen- und Außenbereich + \item Erstellen von Lichtstimmungen + \item Erhalten von Informationen zum aktuellen Beleuchtungszustand + \end{itemize} \tabularnewline \midrule + + Installateur & + \begin{itemize}[left=0pt, itemsep=0pt] + \item Konfiguration der Steuerung für die vorhandenen Endgeräte + \end{itemize} \tabularnewline \midrule + + Zuschauer & + \begin{itemize}[left=0pt, itemsep=0pt] + \item Anschauen einer schönen Beleuchtung + \end{itemize} \tabularnewline \bottomrule + \end{tabular} + \caption{Übersicht der Benutzergruppen und deren menschzentrierte Qualitätsziele} + \label{tab_Benutzergruppen_Qualitätsziele} + \end{center} +\end{table} + +Die menschzentrierten Qualitätsziele zeigen die Ziele der Benutzergruppen auf, die durch das System erfüllt werden sollen. +Jede dieser Benutzergruppen hat Erfordernisse, um ihre menschzentrierten Qualitätsziele zu erfüllen. +\footnote{Für die Beschreibung von Erfordernissen gibt es ebenfalls eine Satzschablone, die allerdings leicht von der Beschreibung der Anforderungen abweicht.} +Aus den ermittelten Erfordernissen werden anschließend die Anforderungen abgeleitet. +Für das Dokumentieren der Anforderungen, kann die oben dargestellte Satzschablone genutzt werden. +Folgende Anforderungen des Heimilluminationssystems betreffen die Kommunikation zwischen der Lichtsteuersoftware und der Lichtsteuereinheit bzw. haben Auswirkungen auf diese:\par + +\begin{itemize}[wide, labelindent=0pt, itemsep=-5pt] + \item[] \textbf{Gruppe} + \item Der Heimanwender muss an der Lichtsteuersoftware eine Gruppe löschen können. + \item Der Heimanwender muss an der Lichtsteuersoftware eine Gruppe aktivieren und deaktivieren können. + \item Der Heimanwender muss an der Lichtsteuersoftware erkennen können, ob eine Gruppe aktiv, inaktiv oder teilaktiv ist.\\ + + \item[] \textbf{Lichtsteuereinheit} + \item Der Heimanwender muss an der Lichtsteuersoftware die Verbindung zur Lichtsteuereinheit herstellen können. + \item Der Heimanwender muss an der Lichtsteuersoftware den Status der Verbindung (verbunden, nicht verbunden, Verbindung wird hergestellt) zur Lichtsteuereinheit erkennen können. + \item Der Heimanwender muss an der Lichtsteuersoftware die Schnellauswahltasten der Lichtsteuereinheit konfigurieren können (einen Preset zuweisen). + \item Der Heimanwender muss an der Lichtsteuereinheit Schnellauswahltasten aktivieren und deaktivieren können. + \item Der Heimanwender muss an der Lichtsteuereinheit erkennen, welche Schnellauswahltasten aktiv, inaktiv oder teilaktiv sind.\\ + + \item[] \textbf{Lichtstimmung} + \item Der Heimanwender muss an der Lichtsteuersoftware eine Lichtstimmung löschen können. + \item Der Heimanwender muss an der Lichtsteuersoftware eine Lichtstimmung aktivieren und deaktivieren können. + \item Der Heimanwender muss an der Lichtsteuersoftware erkennen können, ob eine Lichtstimmung aktiv oder inaktiv ist.\\ + + \item[] \textbf{Komposition} + \item Der Heimanwender muss an der Lichtsteuersoftware eine Komposition löschen können. + \item Der Heimanwender muss an der Lichtsteuersoftware eine Komposition aktivieren und deaktivieren können. + \item Der Heimanwender muss an der Lichtsteuersoftware erkennen können, ob eine Komposition aktiv oder inaktiv ist.\\ + + \item[] \textbf{Lampe} + \item Der Heimanwender muss an der Lichtsteuersoftware eine Lampe einer Gruppe zuweisen können. + \item Der Heimanwender muss an der Lichtsteuersoftware eine Lampe aus einer Gruppe entfernen können. +\end{itemize} + +Für die Anforderungen an das Kommunikationsprotokoll gibt es keine konkreten Benutzer. +Um dennoch die Satzschablone für die Formulierung von Anforderungen nutzen zu können, wird die \emph{Lichtsteuersoftware} und \emph{Lichtsteuereinheit} als \glqq Benutzer\grqq \space verwendet. +Es folgen nun die konkreten Anforderungen an das Kommunikationsprotokoll.\par + +\begin{itemize}[wide, labelindent=0pt, itemsep=-5pt] + \item[] \textbf{Preset} + \item Die Lichtsteuersoftware muss ein Preset (Gruppen-Id und die \ac{dmx}-Werte der in der Gruppe befindlichen Lampen) setzen können. + \item Die Lichtsteuersoftware muss ein Preset der Lichtsteuereinheit löschen können (somit ist die Schnellauswahltaste funktionslos). + \item Die Lichtsteuersoftware muss ein Preset der Lichtsteuereinheit aktivieren und deaktivieren können. + \item Die Lichtsteuereinheit muss der Lichtsteuersoftware mitteilen können, dass ein Preset aktiviert oder deaktiviert wurde. + \item Die Lichtsteuersoftware muss bei der Lichtsteuereinheit den aktuellen Status aller Schnellauswahltasten (aktiv, inaktiv oder teilaktiv) abfragen können.\\ + + \item[] \textbf{Gruppe} + \item Die Lichtsteuersoftware muss eine Zustandsänderung einer Gruppe der Lichtsteuereinheit mitteilen können.\\ + + \item[] \textbf{\ac{dmx}-Signale} + \item Die Lichtsteuersoftware muss einen \ac{dmx}-Frame an die Lichtsteuereinheit übertragen können (damit dieser an die Lampen übertragen wird). +\end{itemize} + +Zusammengefasst ergeben sich für die Evaluation der Protokolle die folgenden drei Anforderungen:\par + +\begin{enumerate} + \item Das Protokoll muss das Übertragen von \ac{dmx}-Werten ermöglichen + \item Das Protokoll muss eine bidirektionale Kommunikation ermöglichen + \item Das Protokoll muss das Übertragen von zusätzlichen Informationen (Aktivieren/Deaktivieren von Gruppen/Presets etc.) ermöglichen +\end{enumerate} + +\subsection{Art-Net} +\label{sec_Art-Net} +Art-Net ist eines der verbreitetsten Protokolle im Bereich der Veranstaltungstechnik zur Übertragung von \ac{dmx}-Werten über das Netzwerk.\par +\begin{center} + \glqq Art-Net is an Ethernet protocol based on the TCP/IP protocol suite. Its purpose is to allow transfer of large amounts of DMX512 data over a wide area using standard networking technology. Art-Net was invented by Wayne Howell, the founder of Artistic Licence.\grqq \space \cite[Seite. 6]{Art-Net} +\end{center} +Die erste Version des Protokolls wurde 1998 vorgestellt und konnte bis zu 40 \ac{dmx}-Universen per Broadcast-Verfahren übertragen. +Die aktuellste Version ist Art-Net 4 und wurde mit dem PLASA Award for Innovation ausgezeichnet. +Art-Net 4 bietet ein breites Spektrum an Funktionen. +Es unterstützt bis zu 30.000 \ac{dmx}-Universen, besitzt Verfahren zur automatischen Entdeckung von Art-Net-fähigen Geräten im Netzwerk und ermöglicht die Übertragung von Medien (Film und Foto) und des sogenannten Time-Codes. +\footnote{eine Zeitinformation zur Synchronisierung von verschiedenen Geräten.} (vgl. \cite{Art-Net-Web})\breath + +Art-Net 4 nutzt das Transportprotokoll \ac{udp} um die Nutzdaten im Netzwerk zu versenden. +Die versendeten Nutzdaten werden im folgenden als \emph{Art-Net-Paket} oder auch kurz als Paket bezeichnet. +\ac{udp} ist ein verbindungsloses Protokoll, welches keine Prüfung über das erfolgreiche Zustellen der versendeten Daten durchführt. +Vorteilhaft an \ac{udp} ist die hohe Übertragungsrate, wodurch eine schnelle Steuerung der Endgeräte ermöglicht wird. \breath + +Diese Arbeit beschränkt sich auf die folgenden drei Aspekte des Protokolls: +\begin{itemize} + \item Verbindungsaufbau + \item Übertragen von \ac{dmx}-Werten + \item Übertragen von zusätzlichen Informationen +\end{itemize} +In der Spezifikation des Art-Net Protokolls werden unter anderem die Begriffe \emph{Node} und \emph{Controller} verwendet, die im folgenden erklärt werden: + +\begin{table}[H] + \begin{tabular}{lp{12.5cm}} + \textbf{Node} & Ein Gerät, welches \ac{dmx}-Daten von oder in das Art-Net-Protokoll übersetzt, wird als Node bezeichnet.\\ + \\ + \textbf{Controller} & Ein Gerät zur zentralen Steuerung oder Überwachung (Lichtsteuerkonsole) ist ein Controller. + Der Begriff wird auch generalisiert verwendet für alle Geräte, die Steuerungsdaten über Art-Net versenden. + \end{tabular} + \caption{Definition der Begriffe Node und Controller. Sinnhaft übersetzt aus der Spezifikation (vgl. \cite[Seite.~9~f.]{Art-Net})} + \label{key} +\end{table} + +Abbildung \ref{fig_Art-Net_Netzwerk} zeigt beispielhaft den Aufbau eines Art-Net-Netzwerks. +Das Art-Net-Protokoll ermöglicht das parallele Nutzen von mehreren Controllern. +In dieser Arbeit wird dies nicht benötigt, aber berücksichtigt.\par + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth, clip, trim=1cm 0 1cm 0 ]{./Medien/Art-Net_Netzwerkaufbau.pdf} + \caption{Beispielhafter Aufbau eines Art-Net Netzwerkes} + \label{fig_Art-Net_Netzwerk} + \end{center} +\end{figure} + +Jeder Node besitzt eine einmalige IP-Adresse, über die der Node eindeutig identifiziert werden kann. +Zusätzlich besitzt jeder Node noch die drei Eigenschaften \emph{Net}, \emph{Sub-Net} und \emph{Universe}. +Die Kombination aus diesen drei Werten heißt \emph{Port-Address} und referenziert ein \ac{dmx}-Universum eindeutig. +Die Port-Address besteht aus 15 Bits und wird in zwei Bytes übertragen. +Tabelle \ref{tab_Port-Address} stellt den Aufbau der Port-Address dar. + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{2.5cm}| + p{1.5cm}| + p{2.5cm}| + p{2cm}| + p{2cm} + } + & + Bit 15& + Bit 14-8& + Bit 7-4& + Bit 3-0 + \tabularnewline \midrule + Port-Address& + 0& + Net& + Sub-Net& + Universe + \end{tabular} + \caption{Aufbau der Port-Address} + \label{tab_Port-Address} + \end{center} +\end{table} + + +\subsubsection{Verbindungsausbau zu einem Node} +Für den Verbindungsaufbau stellt Art-Net zwei Typen von Paketen zur Verfügung. +Zum einen das Paket \emph{ArtPoll} und zum anderen das Paket \emph{ArtPollReply}. +Das Paket ArtPoll wird vom Controller per Broadcast im Netz versendet. +Alle Art-Net-fähigen Endgeräte antworten anschließend mit einem ArtPollReply darauf. +Mit diesem Vorgehen können neue Art-Net-fähige Geräte im Netz erkannt werden. +Das ArtPoll Paket wird in regelmäßigen Abständen versendet um auch den Verbindungsabbruch eines Gerätes zu erkennen.\par +Tabelle \ref{tab_Aufbau_ArtPoll} zeigt eine gekürzte Version des Aufbaus des Art-Net-Pakets ArtPoll. +Die Spalte \emph{Größe} gibt hierbei den Datentypen an. +Das Protokoll nutzt für alle Informationen einen unsigned Integer mit 8, 16 oder 32 Bit. +Besteht ein Feld aus einem Array, so wird die Größe des Array in eckigen Klammern angeben. +Im wesentlichen besteht das Paket ArtPoll aus der \emph{ID} (ein String zur Identifikation des Protokolls), dem \emph{OPCode} zur Identifizierung des Pakettypen und der Versionsnummer (\emph{ProtVerHi} und \emph{ProtVerLo}).\par + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{0.8cm} + p{1.8cm} + p{1.1cm} + p{10cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Feld}& + \textbf{Name}& + \textbf{Größe}& + \textbf{Beschreibung} + \tabularnewline \midrule + 1 & + ID& + Int8[8]& + Ein Array von acht Character, wobei der letzte Eintrag 0x00 entspricht. + Feldwert = 'A' 'r' 't' '-' 'N' 'e' 't' 0x00 + \tabularnewline \midrule + + 2 & + OpCode& + Int16& + Gibt den Nachrichtentyp an (siehe Tabelle \ref{tab_OpCodes}). Aufbau nach Little-Endian-Prinzip. + In diesem Fall \emph{OpPoll}. + \tabularnewline \midrule + + 3 & + ProtVerHi& + Int8& + Höherwertiges Byte der Art-Net-Protokoll-Re\-vi\-sions\-nummer. + \tabularnewline \midrule + + 4 & + ProtVerLo& + Int8& + Niederwertiges Byte der Art-Net-Protokoll-Re\-vi\-sions\-nummer. + Aktueller Wert ist 14. + \tabularnewline \bottomrule + \end{tabular} + \caption{Gekürzter Aufbau des ArtPoll-Pakets (vgl. \cite[Seite. 17 f.]{Art-Net}).} + \label{tab_Aufbau_ArtPoll} + \end{center} +\end{table} + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{3cm} + p{1.2cm} + p{9.5cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Name}& + \textbf{Wert}& + \textbf{Definition} + \tabularnewline \midrule + OpPoll & + 0x2000& + Dies ist ein ArtPoll Paket. + Es sind keine weiteren Daten in diesem \ac{udp}-Paket enthalten. + \tabularnewline \midrule + + OpPollReply & + 0x2100& + Dies ist ein ArtPollReply Paket. + Es enthält Statusinformationen des Gerätes. + \tabularnewline \midrule + + OpCommand & + 0x2400& + Dies ist ein ArtCommand Paket. + Es enthält Textbasierte Befehle.Statusinformationen des Gerätes. + \tabularnewline \midrule + + OpDataRequest & + 0x2700& + Dies ist ein ArtDataRequest Paket. + Es wir benutzt um Daten von einem Node anzufragen. + \tabularnewline \midrule + + OpDataReply & + 0x2800& + Dies ist ein ArtDataReply Paket. + Es wir benutzt um Angefragte Daten zum Controller zu senden. + \tabularnewline \midrule + + OpDmx & + 0x5000& + Dies ist ein ArtDmx Paket. + Es enthält die \ac{dmx}-Werte eines \ac{dmx}-Frames. + \tabularnewline \bottomrule + \end{tabular} + \caption{Ein Auszug der OpCodes des Art-Net-Protokolls (vgl. \cite[Seite. 19-21]{Art-Net}).} + \label{tab_OpCodes} + \end{center} +\end{table} + +Tabelle \ref{tab_OpCodes} zeigt die für diese Arbeit relevanten OpCodes des Art-Net Protokolls. +Mit diesen Codes wird der Typ des Art-Net-Pakets angegeben.\par + + +Erhält ein Node ein ArtPoll-Paket, antwortet es mit einem ArtPollReply-Paket. +Ein gekürzter Aufbau des ArtPollReply-Pakets ist Tabelle \ref{tab_Aufbau_ArtPollReply} zu entnehmen.\par + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{0.8cm} + p{2cm} + p{1.1cm} + p{9.8cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Feld}& + \textbf{Name}& + \textbf{Größe}& + \textbf{Beschreibung} + \tabularnewline \midrule + 2& + OpCode& + Int16& + Gibt den Nachrichtentyp an (siehe Tabelle \ref{tab_OpCodes}). Aufbau nach Little-Endian-Prinzip. + In diesem Fall \emph{OpPollReply}. + \tabularnewline \midrule + + 3& + IP Address& + Int8[4]& + Ein Array mit den vier Zahlen der IPv4-Adresse des Nodes. Aufbau nach Big-Endian-Prinzip. + \tabularnewline \midrule + + 7& + NetSwitch& + Int8& + Das erste Byte der Port-Address (siehe Tabelle \ref{tab_Port-Address}). + \tabularnewline \midrule + + 8& + SubSwitch& + Int8& + Bit 7-4 der Port-Address (siehe Tabelle \ref{tab_Port-Address}). + \tabularnewline \midrule + + 20& + PortTypes& + Int8[4]& + Dieses Array gibt an, wie die vier möglichen Ports genutzt werden. + Für jeden Port wird ein Byte mit dem folgendem Aufbau zurückgegeben.\breath + \begin{tabular}{ + p{0.6cm} + p{8.5cm}} + Bit&Beschreibung + \tabularnewline \midrule + 7& Bit ist gesetzt, wenn der Port Daten aus dem Art-Net-Netzwerk ausgibt. + \tabularnewline \midrule + 6& Bit ist gesetzt, wenn der Port Daten aus dem Art-Net-Netzwerk empfängt. + \tabularnewline \midrule + 5-0& + 000000 = DMX512\par + 000101 = Art-Net + \end{tabular}\breath + + Ungenutzte Ports werden durch ein 0er-Byte gekennzeichnet. + \tabularnewline \midrule + + 23 & + SwIn& + Int8[4]& + Gibt das Universe (Bit 7-4 der Port-Address) für die vier möglichen Eingangsports des Nodes an (siehe Tabelle \ref{tab_Port-Address}). + \tabularnewline \midrule + + 24 & + SwOut& + Int8[4]& + Bit 7-4 der Port-Address für die vier möglichen Ausgangsports des Nodes (siehe Tabelle \ref{tab_Port-Address}). + \tabularnewline \bottomrule + \end{tabular} + \caption{Gekürzter Aufbau des ArtPollReply-Pakets (vgl. \cite[Seite. 24-32]{Art-Net}).} + \label{tab_Aufbau_ArtPollReply} + \end{center} +\end{table} +\vspace{-18pt} +Das ArtPollReply-Paket enthält die Information, welche \ac{dmx}-Universen über dieses Node versendet werden. +Jedes Node kann maximal vier \emph{Ports} mit einem ArtPollReply rückmelden. +\footnote{Besitzt ein Node mehr als vier Ports, so müssen diese mit Hilfe des BindIndex in mehreren ArtPollReply-Paketen gemeldet werden.} +Ein Port stellt einen Signalein- und/oder Ausgang des Nodes dar. +Feld 20 des Pakets definiert die Signalrichtung und das Protokoll. +Jedem Port wird ein \ac{dmx}-Universum zugeordnet (siehe Feld 23 und 24). Erhält der Controller das ArtPollReply-Paket eines Nodes, so gilt dieser als verbunden. \par + +\subsubsection{Übertragen von \acs{dmx}-Werten} +Zum Übertragen der \ac{dmx}-Werte wird das Paket \emph{ArtDmx} verwendet. +Ein gekürzter Aufbau ist Tabelle \ref{tab_Aufbau_ArtDmx} zu entnehmen.\par +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{0.8cm} + p{1.7cm} + p{1.2cm} + p{10cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Feld}& + \textbf{Name}& + \textbf{Größe}& + \textbf{Beschreibung} + \tabularnewline \midrule + 2 & + OpCode& + Int16& + Gibt den Nachrichtentyp an (siehe Tabelle \ref{tab_OpCodes}). Aufbau nach Little-Endian-Prinzip. + In diesem Fall \emph{OpDmx}. + \tabularnewline \midrule + + 7 & + SubUni& + Int8& + Zweites Byte der PortAdress (siehe Tabelle \ref{tab_Port-Address}). + \tabularnewline \midrule + + 8 & + Net& + Int8& + Erste Byte der PortAdress (siehe Tabelle \ref{tab_Port-Address}). + \tabularnewline \midrule + + 9 & + LengthHi& + Int8& + Anzahl der übertragenen \ac{dmx}-Kanäle (2-512).\par + Höherwertiges Byte + \tabularnewline \midrule + + 10 & + Length& + Int8& + Anzahl der übertragenen \ac{dmx}-Kanäle (2-512).\par + Niederwertiges Byte + \tabularnewline \midrule + + 11 & + Data& + Int8\par + [Length]& + Ein Array mit variabler Länge, welches die Werte der \ac{dmx}-Kanäle enthält. + \tabularnewline \bottomrule + \end{tabular} + \caption{Gekürzter Aufbau des ArtDmx-Pakets (vgl. \cite[Seite. 60 f.]{Art-Net}).} + \label{tab_Aufbau_ArtDmx} + \end{center} +\end{table} + +Im ArtDmx-Paket wird die PortAdress für das entsprechende \ac{dmx}-Universum angegeben (Feld 7 und 8), die Anzahl an übertragenen \ac{dmx}-Kanälen (Feld 9 und 10) und die \ac{dmx}-Werte selber.\par + + +\subsubsection{Übertragen von zusätzlichen Informationen} +Für diese Arbeit müssen der Lichtsteuereinheit (Node) zusätzliche Informationen mitgeteilt und Statusdaten abgefragt werden. +Für diesen Zweck gibt es die Pakete \emph{ArtDataRequest}, \emph{ArtDataReply} und \emph{ArtCommand}. +Tabelle \ref{tab_Aufbau_ArtDataRequest} zeigt den gekürzten Aufbau des ArtDataRequest-Pakets.\par +Im Paket ArtDataRequest wird mit Hilfe der Felder 9 und 10 ein DataRequest-Code übertragen. +Dieser gibt an, was vom Controller angefragt wird. +Für diese Arbeit ist der Code-Bereich von 0x8000 bis 0xffff relevant, da dieser Bereich für die herstellerspezifische Nutzung freigegeben ist. +Somit kann in diesem Bereich ein Code zum Anfragen der Statusinformationen definiert werden. +Tabelle \ref{tab_DataRequest_Codes} gibt einen Überblick über die möglichen DataRequest-Codes.\par + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{0.8cm} + p{1.7cm} + p{1.2cm} + p{10cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Feld}& + \textbf{Name}& + \textbf{Größe}& + \textbf{Beschreibung} + \tabularnewline \midrule + 2 & + OpCode& + Int16& + Gibt den Nachrichtentyp an (siehe Tabelle \ref{tab_OpCodes}). Aufbau nach Little-Endian-Prinzip. + In diesem Fall \emph{OpDataRequest}. + \tabularnewline \midrule + + 9 & + RequestHi& + Int8& + \makecell[l]{Kennzahl welche Daten angefragt werden\\(siehe Tabelle~\ref{tab_DataRequest_Codes}). + Höherwertiges Byte.} + \tabularnewline \midrule + + 10 & + RequestLo& + Int8& + \makecell[l]{Kennzahl welche Daten angefragt werden\\(siehe Tabelle \ref{tab_DataRequest_Codes}). + Niederwertiges Byte.} + \tabularnewline \bottomrule + \end{tabular} + \caption{Gekürzter Aufbau des ArtDataRequest-Pakets (vgl. \cite[Seite. 44 f.]{Art-Net}).} + \label{tab_Aufbau_ArtDataRequest} + \end{center} +\end{table} + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{3cm} + p{1.2cm} + p{9.5cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Name}& + \textbf{Wert}& + \textbf{Definition} + \tabularnewline \midrule + DrPoll & + 0x0000& + Mit diesem Code wird angefragt, ob eine Datenabfrage möglich ist. + \tabularnewline \midrule + + DrUrlProduct & + 0x0001& + URL zur Produktseite des Nodes. + \tabularnewline \midrule + + DrUrlUserGuide & + 0x0002& + URL zur Benutzeranleitung des Nodes. + \tabularnewline \midrule + + DrUrlSupport & + 0x0003& + URL zur Hilfeseite des Nodes. + \tabularnewline \midrule + + DrManSpec & + 0x8000-0xffff& + Hersteller spezifische Nutzung. + \tabularnewline \bottomrule + \end{tabular} + \caption{Codes zum Anfragen von Daten (vgl. \cite[Seite. 45]{Art-Net}).} + \label{tab_DataRequest_Codes} + \end{center} +\end{table} + +Erhält ein Node nun eine Datenanfrage, so antwortet es mit einem ArtDataReply-Paket darauf. +Tabelle \ref{tab_Aufbau_ArtDataReply} zeigt den gekürzten Aufbau eines ArtDataReply-Pakets. +Feld 9 und 10 des Pakets geben erneut den DataRequest-Code an, damit die Daten korrekt zugeordnet werden können. +Feld 11 und 12 geben die Länge des Datenarrays in Feld 13 an.\par + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{0.8cm} + p{1.7cm} + p{1.2cm} + p{10cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Feld}& + \textbf{Name}& + \textbf{Größe}& + \textbf{Beschreibung} + \tabularnewline \midrule + 2 & + OpCode& + Int16& + Gibt den Nachrichtentyp an (siehe Tabelle \ref{tab_OpCodes}). Aufbau nach Little-Endian-Prinzip. + In diesem Fall \emph{OpDataReply}. + \tabularnewline \midrule + + 9 & + RequestHi& + Int8& + \makecell[l]{Kennzahl welche Daten angefragt wurden\\(siehe Tabelle \ref{tab_DataRequest_Codes}). + Höherwertiges Byte.} + \tabularnewline \midrule + + 10 & + RequestLo& + Int8& + \makecell[l]{Kennzahl welche Daten angefragt wurden\\(siehe Tabelle \ref{tab_DataRequest_Codes}). + Niederwertiges Byte.} + \tabularnewline \midrule + + 11 & + PayLenHi& + Int8& + Gibt die Länge des Array der Nutzdaten (Feld 13) an.\par + Höherwertiges Byte. + \tabularnewline \midrule + + 12 & + PayLenLo& + Int8& + Gibt die Länge des Array der Nutzdaten (Feld 13) an.\par + Niederwertiges Byte. + \tabularnewline \midrule + + 13 & + PayLoad& + Int8\par + [Length]& + Datenarray der angefragten Daten. + \tabularnewline \bottomrule + + \end{tabular} + \caption{Gekürzter Aufbau des ArtDataReply-Pakets (vgl. \cite[Seite. 46 f.]{Art-Net}).} + \label{tab_Aufbau_ArtDataReply} + \end{center} +\end{table} + +Um Befehle, wie das Setzen von Presets oder das Aktivieren von Gruppen, übertragen zu können, wird das Paket ArtCommand verwendet. +Mit diesem Paket wird ein textbasierter Befehl übertragen, der bis zu 512 Zeichen lang sein kann. +Die Spezifikation empfiehlt den String nach dem folgendem Schema aufzubauen:\par +\begin{center} + Befehl=Data\& +\end{center} +Das \&-Zeichen dient als Trennzeichen zwischen mehreren Befehlen in einem String. +Tabelle \ref{tab_Aufbau_ArtCommand} zeigt einen gekürzten Aufbau des Pakets.\par + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{0.8cm} + p{1.7cm} + p{1.2cm} + p{10cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Feld}& + \textbf{Name}& + \textbf{Größe}& + \textbf{Beschreibung} + \tabularnewline \midrule + 2 & + OpCode& + Int16& + Gibt den Nachrichtentyp an (siehe Tabelle \ref{tab_OpCodes}). Aufbau nach Little-Endian-Prinzip. + In diesem Fall \emph{OpCommand}. + \tabularnewline \midrule + + 7 & + LengthHi& + Int8& + Anzahl der übertragenen Bytes.\par + Höherwertiges Byte + \tabularnewline \midrule + + 8 & + LengthLo& + Int8& + Anzahl der übertragenen Bytes.\par + Niederwertiges Byte + \tabularnewline \midrule + + 11 & + Data& + Int8\par + [Length]& + ASCII basierter Befehls-String. + \tabularnewline \bottomrule + \end{tabular} + \caption{Gekürzter Aufbau des ArtCommand-Pakets (vgl. \cite[Seite. 52 f.]{Art-Net}).} + \label{tab_Aufbau_ArtCommand} + \end{center} +\end{table} + +\subsection{\acs{sacn} bzw. ANSI E1.31-2016.} +\label{sec_sACN_ANSI} + +Das Protokoll \ac{sacn} wurde 2009 von der \ac{esta} in der Norm ANSI E1.31 definiert und stellt einen Standard dar, um \ac{dmx}-Daten über ein Netzwerk zu übertragen. +Das Protokoll basiert auf dem Standard \ac{acn}, der in der Norm ANSI E.1.17 definiert ist. +\ac{acn} nutzt \ac{udp} zur Netzwerkkommunikation (vgl. \cite[Seite 1]{ANSI_E.1.31-2018}), wodurch nicht sichergestellt ist, dass ein Datenpaket ankommt. +\ac{sacn} selbst stellt auch keine weiteren Methoden für eine Verbindungsprüfung zur Verfügung. +Insgesamt werden mit \ac{sacn} drei Arten von Paketen übertragen:\par +\begin{itemize} + \item Data Packet + \item Universe Discovery Packet + \item Synchronization Packet +\end{itemize} + +Für diese Arbeit ist nur das \emph{Data Packet} relevant. +Mit dem Data Packet können \ac{dmx}-Daten versendet werden. +Hierbei wird die Nummer des jeweilige Universums und der damit verbundene \ac{dmx}-Frame versendet. +Tabelle \ref{tab_Aufbau_Data_Packet} zeigt den Aufbau eines Data Packets. +Die Spalte Größe gibt an, wie viele Bytes das Feld in Anspruch nimmt. +Alle Daten in diesem Paket werden nach dem Big-Endian-Prinzip versendet.\par + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{0.8cm} + p{3.2cm} + p{1.2cm} + p{8.5cm}} + \toprule + \rowcolor[gray]{.9} + \textbf{Pos.}& + \textbf{Name}& + \textbf{Größe}& + \textbf{Beschreibung} + \tabularnewline \midrule + 113-\par + 114 & + Universe& + 2& + Nummer des \ac{dmx}-Universums + \tabularnewline \midrule + + 123-\par + 124 & + Property value\par + count& + 2& + Anzahl der versendeten \ac{dmx}-Kanäle + \tabularnewline \midrule + + 125-\par + 637 & + Property values& + 1-513& + \ac{dmx}-Werte + \tabularnewline \bottomrule + \end{tabular} + \caption{Gekürzter Aufbau des Data Packet (vgl. \cite[Seite. 6 f.]{ANSI_E.1.31-2018}).} + \label{tab_Aufbau_Data_Packet} + \end{center} +\end{table} + +Eine Methode, um weitere Informationen wie Befehle und Preset-Daten zu versenden, bietet \ac{sacn} nicht. +Es ist jedoch möglich, weitere Daten und Informationen über \ac{dmx}-Kanäle in einem zweiten Universum zu versenden. +Dies ist allerdings vom Protokoll so nicht vorgesehen und kann zu Problemen führen, wenn diese Kanäle von anderen Geräten für \ac{dmx} genutzt werden.\par + +\subsection{MA-Net} +\label{sec_MA-Net_ETCNet} +Ein weiteres verbreitetes Netzwerkprotokoll zur Übertragung von \ac{dmx}-Daten ist von der Firma MA Lighting Technology GmbH. +Das sogenannte \emph{MA-Net3} ist die neuste Version des Kommunikationsprotokolls, welches alle Geräte (Lichtsteuerkonsolen, Nodes, Medienserver, Netzwerk-Switche) der Firma für die Kommunikation nutzen. +Mit diesem Protokoll, können sowohl \ac{dmx}-Daten, als auch weitere Nutzdaten übertragen werden. +Abbildung \ref{fig_MA-Net-Systemarchitektur} zeigt eine beispielhaften Systemarchitektur von Steuergeräten und Lichtsteuereinheiten, welche mit MA-Net3 verbunden sind. +MA-Net3 ermöglicht die gleichzeitige Nutzung von mehreren Controllern und Nodes, die über Switche miteinander kommunizieren. +Aktuell sind die Spezifikationen des Protokolls nicht öffentlich zugänglich.\par + + +\begin{figure}[H] + \begin{center} + \includegraphics[width=\columnwidth]{./Medien/MA-Net_Beispiel.pdf} + \caption[Beispielhafte Systemarchitektur des MA-Net3.] + {Beispielaufbau einer MA-Net-Systemarchitektur.\footnotemark} + \label{fig_MA-Net-Systemarchitektur} + \end{center} +\end{figure} +\footnotetext{Bildquelle: \url{https://www.malighting.com/de/ma-network-solutions}} + +Ein ähnliches Protokoll ist das ETCNet der Firma Electronic Theatre Controls, Inc. +Auch zu diesem Protokoll sind die Spezifikationen nicht öffentlich zugänglich. \par + +\subsection{Evaluation und Auswahl des Protokolls} +\label{sec_Evaluation_und_Auswahl_des_Protokolls} +Für die Evaluation der Protokolle beschreibt Kapitel \ref{sec_Anforderungen_des_Kommunikationsprotokolls} die fachlichen Anforderungen an das Protokoll. +Das Protokoll muss \ac{dmx}-Daten übertragen können, die Kommunikation muss bidirektional sein und es müssen zusätzliche Informationen wie das Setzen von Presets übertragen werden können. +Hinzu kommt die Anforderung, dass die Protokoll\-spezifikation öffentlich zugänglich sein muss, damit das Protokoll auf eigener Hard- und Software genutzt werden kann. +Ebenfalls fließt in die Bewertung mit ein, ob es bereits Bibliotheken der entsprechenden Protokolle für den Arduino (Mikrocontroller für die Lichtsteuereinheit) und Java (Programmiersprache der Lichtsteuersoftware) gibt. \breath + +Tabelle \ref{tab_Nutzwertanalyse} stellt das Ergebnis der durchgeführte Nutzwertanalyse dar. \par + +\begin{table}[H] + \begin{center} + \begin{tabular}{ + p{4.5cm} + C{3cm} + C{3cm} + C{3cm}} + \toprule + \rowcolor[gray]{.9} + Anforderungen&Art-Net&\ac{sacn}&MA-Net3 + \tabularnewline \midrule + + Übermittlung von \ac{dmx}-Daten& + {\Large \ding{51}}& + {\Large \ding{51}}& + {\Large \ding{51}} + \tabularnewline \midrule + + Bidirektionale Kommunikation& + {\Large \ding{51}}& + {\Large \ding{55}}& + {\Large \ding{51}} + \tabularnewline \midrule + + Übertragung von weiteren Informationen& + {\Large \ding{51}}& + {\Large (\ding{51})}& + {\Large \ding{51}} + \tabularnewline \midrule + + Öffentlich zugängliche Protokollspezifikation& + {\Large \ding{51}}& + {\Large \ding{51}}& + {\Large \ding{55}} + \tabularnewline \midrule + + Bibliotheken für den Arduino& + {\Large \ding{51}}& + {\Large \ding{51}}& + {\Large (\ding{51})} + \tabularnewline \midrule + + Bibliotheken für Java& + {\Large \ding{51}}& + {\Large \ding{51}}& + {\Large \ding{55}} + \tabularnewline \bottomrule[1.5pt] + + Ergebnis& + 6 / 6& + 4,5 / 6& + 3,5 / 6 + \tabularnewline + \multicolumn{4}{l}{\ding{51} : erfüllt \hspace{1cm} (\ding{51}) : teilweise erfüllt \hspace{1cm} \ding{55} : nicht erfüllt} + \end{tabular} + \caption{Nutzwertanalyse der drei Protokolle Art-Net, \ac{sacn} und MA-Net3.} + \label{tab_Nutzwertanalyse} + \end{center} +\end{table} + +Alle drei Protokolle besitzen Methoden, um \ac{dmx}-Daten in ausreichender Menge und Geschwindigkeit zu übertragen. +Eine bidirektionale Verbindung ist bei Art-Net und MA-Net3 möglich. +Bei \ac{sacn} ist keine bidirektionale Verbindung vorgesehen. +Auch beim Übertragen von zusätzlichen Informationen stellt, \ac{sacn} im Gegensatz zu Art-Net und MA-Net3 keine konkrete Methode zur Verfügung. +Es ist zwar möglich, weitere Daten in Form von \ac{dmx}-Kanalwerten in weiteren Universen zu übertragen, dies wäre aber recht aufwändig und nicht im Sinne des Protokolls. +Der größte Nachteil von MA-Net3 besteht darin, dass die Spezifikationen des Protokolls nicht öffentlich zugänglich sind. +Dies macht eine private Nutzung des Protokolls mit eigener Hard- und Software so gut wie unmöglich. +Für die beiden Protokolle Art-Net und \ac{sacn} existieren bereits Bibliotheken, um diese Protokolle auf dem Arduino und in Java nutzen zu können. +Für MA-Net3 gibt es vereinzelt auch Bibliotheken, mit denen der Arduino mit den MA-Net3 interagieren kann. Da die Spezifikation des Protokolls nicht öffentlich ist, basieren diese Bibliotheken häufig nur auf dem analysierten Netzwerkverkehr eines aktiven Systems. +Somit bieten diese Bibliotheken keine Garantie, dass das Protokoll tatsächlich korrekt genutzt bzw. imitiert wird. \breath + +Zusammenfassend erfüllt Art-Net sechs von sechs Kriterien, \ac{sacn} vier Kriterien, eins nur teilweise und MA-Net3 erfüllt drei Kriterien und eins nur teilweise. +Die Nutzwertanalyse zeigt somit, dass Art-Net das optimale Protokoll für diesen Anwendungsfall ist. +Es erfüllt alle fachlichen Anforderungen aus Kapitel \ref{sec_Anforderungen_des_Kommunikationsprotokolls}, ist ein weitverbreiteter Standard, dessen Spezifikationen öffentlich zugänglich sind und es existieren bereits Bibliotheken, um das Protokoll auf dem Arduino und in Java zu nutzen. \ No newline at end of file diff --git a/doc/projectDocumentation/einstellungen.tex b/doc/projectDocumentation/einstellungen.tex new file mode 100644 index 0000000000000000000000000000000000000000..586fb8f679699cb547b469f7d05ebcf2b0688bfe --- /dev/null +++ b/doc/projectDocumentation/einstellungen.tex @@ -0,0 +1,156 @@ + + \ifx\inPreamble\undefined \else + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Art der Arbeit %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% ist noch im Entwurfsstadium -> fügt Wasserzeichen ein +\setbool{isEntwurf}{false} + +% soll ein Abstract gezeigt werden +\setbool{showAbstract}{true} + +% ist es eine normale Hausarbeit oder eine Abschlussarbeit +\setbool{isAbschlussarbeit}{true} + +% falls es eine Abschlussarbeit ist, Art der Arbeit auswählen +% Bachelor-Arbeit oder Master-Arbeit +\newcommand{\artDerArbeit}{Bachelor-Arbeit} + +% Abschluss, falls es eine Abschlussarbeit ist +% bspw. Bachelor of Engineering oder Master of Science +\newcommand{\abschlussgrad}{Bachelor of Engineering} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Titel der Arbeit %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\titel}{Netzwerkbasierte Lichtsteuerung\\ + von DMX-fähigen Endgeräten\\ + im Heimbereich} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Angaben über den Autor %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Vollständiger Name +\newcommand{\autor}{Sebastian Böttger} + +% Matrikelnummer +\setbool{showMatrikelnummer}{true} +\newcommand{\matrikelnummer}{--- --- ---} + +% offizielle Bezeichnung des Studiengangs +\newcommand{\studiengang}{Technische Informatik KIA} +% Schwerpunkt des Studiengangs - falls nicht vorhanden, leer lassen +\newcommand{\fachsemester}{8} +\newcommand{\schwerpunkt}{} + +% Der Fachbereich, in dem die Arbeit verfasst wird +\newcommand{\fachbereich}{Fachbereich Elektrotechnik und Informatik} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Angaben über die Arbeit %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Abgabedatum +\newcommand{\abgabedatum}{02. April 2024} +\newcommand{\abgabeort}{Heiligenhaus} + +% Prüfer +\setbool{hasZweitenPruefer}{true} +\newcommand{\prueferEins}{Prof.~Dr.-Ing.~Christian~Weidauer} +\newcommand{\prueferZwei}{Prof.~Dr.~rer.~nat.~Peter~Gerwinski} % wenn nicht vorhanden, leer lassen + +% Arbeit am CVH? +\setbool{isCVH}{true} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Literatur %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% soll für Quellen [Abc123] statt [1] verwendet werden? +\setbool{useAlphaStyle}{true} + +% Name der Literatur-Datei +\newcommand{\bibFile}{Literatur.bib} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Optionale Einstellungen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Layout (Optional) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Einseitiger oder doppelseitiger Druck? +\setbool{doppelseitig}{false} + +% Anklickbare Links im PDF-Dokument mit Rahmen markieren? +\setbool{linksUmrahmen}{false} + +% Seitenumbruch zwischen den Verzeichnissen deaktivieren? +\setbool{verzeichnisseZusammenfassen}{false} + +% Verzeichnisse im Inhaltsverzeichnis erwähnen? +\setbool{verzeichnisseImInhaltsverzeichnis}{true} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Seitenränder %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Wie breit ist der Teil, an dem die einzelnen Blätter +% mit einander verklebt/anderweitig verbunden werden? +\setlength{\bindekorrektur}{3.5cm} + +% Wie viel Rand außen neben dem Text (einseitig: wie viel Rand rechts neben dem Text) +% Innerer bzw. linker Rand wird daraus automatisch berechnet +\setlength{\randAussen}{2.0cm} % 1.88 - 2.5cm (einseitig), 2.5 - 3.4cm (doppelseitig) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Sprachen (Optional) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Sprache, in der das Dokument geschrieben ist. +% Eine Liste der möglichen Sprachen finden sich in der Dokumentation zum LaTeX-Paket 'babel' +\newcommand{\hauptsprache}{ngerman} + +% weitere Sprachen, auf die kurzfristig mit \selectlanguage{language} gewechselt wird. +% (wenn es mehrere sind, werden diese mit Kommata getrennt) +\newcommand{\weitereSprachen}{ngerman, english, french} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Farben (Optional) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Farbe für Design-Elemente verwenden +\setbool{useColor}{true} + +% Farbmodell +% z.B. cmyk, rgb oder gray +\newcommand{\colormodel}{rgb} +% Falls das Tool eurer Druckerei Schwarz-Weiß-Seiten trotz \setbool{color}{false} +% _fälschlicherweise_ als Farbseiten erkennt (das kann ziemlich teuer werden!), +% könnt ihr hier das Farbmodell der Vorlage umstellen. +% +% So gab es schon einmal den Fall, dass eine Thesis-Druckerei die S/W-Seiten +% erst korrekt erkannt hat, wenn das (eigentlich für das Drucken ungeeignete) +% RGB-Modell verwendet wurde... +% +% Bilder und eingebundene PDFs werden durch diese Einstellung nicht geändert! +% +% Ein paar Beispiele für sinnvolle Werte: +% {cmyk} - CMYK (Cyan, Magenta, Yellow, Key) ist _das Farbmodell_ für alles was gedruckt wird. +% Jede professionelle Druckerei kann damit umgehen! +% => der Standard bei Drucksachen und daher auch in dieser Vorlage +% +% {rgb} - RGB (Red, Green, Blue) ist ein Farbmodell für Bildschirme etc. +% Im Gegensatz zum Druck mit Pigmenten (=subtraktive Farbmischung) wird +% hier mit Licht gearbeitet (Additive Farbmischung). RGB ist daher nicht +% für den Druck geeignet und wird vor dem Druckvorgang in ein anderes +% Farbmodell (z.B. CMYK) umgewandelt. +% => eigentlich falsch, wird in Einzelfällen aber von Druckereien angefordert +% +% {gray} - Wer möchte, kann auch das Farbmodell "gray" verwenden. Dann werden alle +% Farben direkt in Graustufen umgerechnet. +% In diesem Fall wird zusätzlich \setbool{useColor}{false} empfohlen. +% So wird die Darstellung von Quelltexten an die nun fehlenden Farben angepasst. +% +% Weblinks zum Thema: +% https://de.wikipedia.org/wiki/CMYK-Farbmodell +% https://de.wikipedia.org/wiki/RGB-Farbraum +% https://www.ctan.org/pkg/xcolor + +\fi \ No newline at end of file diff --git a/doc/projectDocumentation/preambel.tex b/doc/projectDocumentation/preambel.tex new file mode 100644 index 0000000000000000000000000000000000000000..41218840b32dc1caa73adcdeb536042d808308ff --- /dev/null +++ b/doc/projectDocumentation/preambel.tex @@ -0,0 +1,683 @@ +% Flag setzen: wird sind in der Präambel +\def\inPreamble{} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Encoding %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% UTF8 Codierte .tex-Dateien +\RequirePackage[utf8]{inputenc} + +% Benutzung der europäischen Schriftkodierung +% z.B. zur richtigen Darstellung von Umlauten +\RequirePackage[T1]{fontenc} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Werkzeuge %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\RequirePackage{etoolbox} % Einfacheres Programmieren in LaTeX +\RequirePackage{calculator} % Rechnen (auch mit Längen) +\RequirePackage{xfp} % Genaueres Rechnen (aber nicht mit Längen) +\RequirePackage{pbox} % \pbox (Parbox flexibler Breite) + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Variablen zur Anpassung der Arbeit %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newbool{isEntwurf} +\newbool{isAbschlussarbeit} +\newbool{showAbstract} +\newbool{showMatrikelnummer} +\newbool{hasZweitenPruefer} +\newbool{isCVH} +\newbool{useAlphaStyle} +\newbool{doppelseitig} +\newbool{linksUmrahmen} +\newbool{verzeichnisseZusammenfassen} +\newbool{verzeichnisseImInhaltsverzeichnis} +\newbool{useColor} + +\newlength{\bindekorrektur} +\newlength{\randAussen} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Einstellungen anwenden %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\input{einstellungen} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Document-Class %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\ifbool{doppelseitig}{ + \def\onetwoside{twoside} +}{ + \def\onetwoside{oneside} +} + +\documentclass[ + \onetwoside, % twoside: zweiseitig, oneside: einseitig + titlepage, % Titelseite steht für sich allein + 12pt, % Schriftgröße + a4paper, % A4-Papier +]{scrartcl} +\usepackage[onehalfspacing]{setspace} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Sprachen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\RequirePackage[ + main=\hauptsprache, % Umsetzung der deutschen Sprache nach neuer Rechtschreibung + \hauptsprache, % muss hier nochmal erwähnt werden, damit \autoref das auch mitbekommt + \weitereSprachen % Sprachen, die nur Abschnittsweise (z.B. für Zitate) verwendet werden +]{babel} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Schriftarten, Schriftsatz %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\RequirePackage{lmodern} % Schriftart lmodern nutzen +\RequirePackage{microtype} % Besserer Schriftsatz +\usepackage{pifont} % Zusätzliche Zeichen + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Zitate, Anführungszeichen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\RequirePackage[ + autostyle, % Zitierstil an die aktuelle Sprache anpassen + german=quotes, % wenn Deutsch -> „Anführungszeichen“ benutzen +]{csquotes} % wird auch von biblatex verwendet + +% Umdefiniert um Doppelklammerung bei \textquote+\cite zu verhindern +\renewcommand{\mkcitation}[1]{\,#1} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Abkürzungsverzeichnis %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\usepackage[withpage, printonlyused]{acronym} + +%printonlyused, + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Seitengröße festlegen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage[ + layout=a4paper, % Papierformat + headheight=1.2cm, % durch Kopfzeile festgelegt + top=2.5cm, % Abstand Text <-> oberer Seitenrand + left=\bindekorrektur, % Abstand Text <-> linker Seitenrand + right=\randAussen, % Abstand Text <-> rechter Seitenrand + bottom=2.0cm % Abstand Text <-> unterer Seitenrand +]{geometry} + +% Maßeinheit setzen +\setlength{\unitlength}{1cm} + +% Einrückung von Paragraphen entfernen +\setlength{\parindent}{0pt} +\newcommand{\breath}{\bigbreak} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Literaturverwaltung %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\ifbool{useAlphaStyle}{ % wenn gewünscht ... + \def\bibStyle{style=alphabetic,} % ... in der Form [Xil13] statt [1] referenzieren +}{ + \def\bibStyle{} +} + +\RequirePackage[backend=bibtex, % Daten von Bibtex holen + \bibStyle + sorting=nyt % Name,Year,Title +]{biblatex} +\addbibresource{\bibFile} +%\bibliographystyle{unsrt} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Andere Listen für den Anhang %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%\makeatletter +%\renewcommand\listoftables{% +% \@starttoc{lot}% +%} +%\makeatother +% +%\makeatletter +%\renewcommand\listoffigures{% +% \@starttoc{lot}% +%} +%\makeatother + +\usepackage{makecell} + +\addto\captionsngerman{\renewcommand{\listfigurename}{}} +\addto\captionsngerman{\renewcommand{\listtablename}{}} +\addto\captionsngerman{\renewcommand{\lstlistlistingname}{}} + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Verschiedene nützliche Packages %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{setspace} +\usepackage{enumerate} +\usepackage{enumitem} +\usepackage{booktabs} +\usepackage{lipsum} + +\newcommand{\tabitem}{~~\llap{\textbullet}~~} +\usepackage{array} +%\newcommand{\minipagetrue}{\@minipagetrue} +\newcolumntype{P}[1]{>{\raggedright\arraybackslash}p{#1}} +\renewcommand\arraystretch{1.0} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Wasserzeichen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\ifbool{isEntwurf}{ + \usepackage{draftwatermark} + \SetWatermarkText{\textbf{ENTWURF}} + \SetWatermarkScale{0.8} + \SetWatermarkColor[gray]{0.95} +}{} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Farben %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage[ + \colormodel, % Konvertiere alle Farben in das angegebene Farbmodell + table, % Lade das colortbl package (Farben in Tabellen) + showerrors, % Nicht definierte Farbe verwendet -> Fehler erzeugen +]{xcolor} + +\definecolor{BO} {cmyk}{0.00 1.00 0.88 0.11} % BO-Rot +\definecolor{BO-CVH} {cmyk}{0.00 0.88 0.85 0.07} % CVH-Rot +\definecolor{pureK} {cmyk}{0.00 0.00 0.00 1.00} % K + +\definecolor{AccentStrong} {cmyk}{1.000,0.870,0.000,0.000} % Hellblau +\definecolor{AccentMiddle} {cmyk}{1.000,0.000,0.080,0.170} % Bläuliches Grün +\definecolor{AccentWeak} {cmyk}{0.295,0.142,0.000,0.310} % Bläuliches Grau + +% Farbschema +\ifbool{useColor}{ % wenn Farbe + \colorlet{top} {BO-CVH} + \colorlet{middle} {BO-CVH!80} + \colorlet{bottom} {BO-CVH} + \colorlet{textBlack} {black} +}{ % wenn Graustufen + \colorlet{top} {pureK} + \colorlet{middle} {pureK!50} + \colorlet{bottom} {pureK} + \colorlet{textBlack} {pureK} +} + +% Spezialisierter Anwendungszweck +\colorlet{pagenumber} {bottom!50!textBlack} +\colorlet{headrule} {top} +\colorlet{footnoteRule} {middle} +\colorlet{footrule} {bottom} + +\colorlet{captionLabel} {pureK!80} +\colorlet{subcaptionLabel} {pureK!70} + +\colorlet{captionText} {pureK!70} +\colorlet{subcaptionText} {pureK!60} + +\colorlet{listingBackground}{pureK!5} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Fußnotengestaltung %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\renewcommand{\footnoterule}{ + \color{footnoteRule}{ + \vspace*{-3pt} + \hrule height 0.1em width 0.4\columnwidth + \vspace*{2.6pt} + } +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Kopfzeilen und Seitenzahl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\def\customHeadrule{ + \renewcommand{\headrulewidth}{1.0mm} + \renewcommand{\headrule}{ + \begingroup + \color{headrule} + \hrule height \headrulewidth + \endgroup + } +} + +\def\customFootrule{ + \renewcommand{\footrulewidth}{1.5mm} + \renewcommand{\footrule}{% + \begingroup + \color{footrule} + \hrule height \footrulewidth + \vspace{0.5em} + \endgroup + } +} + +\def\renewMarks{ + \renewcommand{\sectionmark}[1]{% + \markboth{% + ##1%~(\thesection)% + }{} + } + \renewcommand{\subsectionmark}[1]{% + \markright{% + ##1 + } + } +} + +\def\seitenNummer{ + \color{pagenumber}\sffamily\bfseries{Seite \thepage} +} + +% Schönere Kopfzeilen +\usepackage{fancyhdr} + +\ifbool{doppelseitig}{ + \def\rightodd{RO} + \def\lefteven{LE} + \def\rightoddlefteven{RO,LE} + \def\leftoddrighteven{LO,RE} +}{ + \def\rightodd{R} + \def\lefteven{R} + \def\rightoddlefteven{R} + \def\leftoddrighteven{L} +} + +\def\vertikalZentrieren{% + \vspace{-\footrulewidth}% + \vspace{-1.275em}% +} + +\pagestyle{fancy} +\renewMarks +\fancyhf{} +\fancyhead[\leftoddrighteven]{ + \nouppercase{ + \sffamily + \textbf{\leftmark} + \\ + \rightmark + } +} +\fancyhead[\rightoddlefteven]{ + \ifbool{isCVH}{ + \includegraphics[height=2em]{\bologopdf} + }{ + \includegraphics[height=2em,clip,trim=216 0 0 0]{\bologopdf} + } + \hspace{-0.9em} +} +\fancyfoot[\lefteven]{\vertikalZentrieren\hspace{1em}\colorbox{white}{\seitenNummer}} +\fancyfoot[\rightodd]{\vertikalZentrieren\colorbox{white}{\seitenNummer}\hspace{1em}} +\customHeadrule +\customFootrule + +\fancypagestyle{plain}{% + \renewMarks + \fancyhf{} % clear + \fancyhead[\rightoddlefteven]{ + \ifbool{isCVH}{ + \includegraphics[height=2em]{\bologopdf} + }{ + \includegraphics[height=2em,clip,trim=216 0 0 0]{\bologopdf} + } + \hspace{-0.9em} + } + \fancyfoot[\lefteven]{\vertikalZentrieren\hspace{1em}\colorbox{white}{\seitenNummer}} + \fancyfoot[\rightodd]{\vertikalZentrieren\colorbox{white}{\seitenNummer}\hspace{1em}} + + \customHeadrule + \customFootrule +} + +\fancypagestyle{withoutPageNumber}{% + \renewMarks + \fancyhf{} % clear + \fancyhead[\rightoddlefteven]{ + \ifbool{isCVH}{ + \includegraphics[height=2em]{\bologopdf} + }{ + \includegraphics[height=2em,clip,trim=216 0 0 0]{\bologopdf} + } + \hspace{-0.9em} + } + %\fancyfoot[\lefteven]{\vertikalZentrieren\hspace{1em}\colorbox{white}{\seitenNummer}} + %\fancyfoot[\rightodd]{\vertikalZentrieren\colorbox{white}{\seitenNummer}\hspace{1em}} + + \customHeadrule + \customFootrule +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Format der Überschriften %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage[% +% nobottomtitles*, % Überschriften am unteren Seitenrand vermeiden +]{titlesec} + +\def\titleformatBase{\sffamily\bfseries} +\def\titleformatSection{\LARGE} +\def\titleformatSubsection{\Large} +\def\titleformatSubsubsection{\large} +\def\titleformatParagraph{\normalsize} + +\def\titlepartSection +{\titleformatSection\ifbool{weAreInTheAppendix}{\Alph{section}}{\arabic{section}}} + +\def\titlepartSubsection +{\titleformatSubsection\ifbool{weAreInTheAppendix}{\Alph{subsection}}{\arabic{subsection}}} + +%\def\titlepartSubsection{\titleformatSubsection\arabic{subsection}} + +\def\titlepartSubsubsection{\titleformatSubsubsection\arabic{subsubsection}} +\newbool{weAreInTheAppendix} +\setbool{weAreInTheAppendix}{false} +\appto{\appendix}{\setbool{weAreInTheAppendix}{true}} +\def\titleNumberExtraDistance{.5cm} + +\titleformat{\section}[block] +{\titleformatBase} +{\color{middle}\titlepartSection\hphantom{.\titlepartSection}} +{\titleNumberExtraDistance} +{\titleformatSection} + +\titleformat{\subsection}[block] +{\titleformatBase} +{\ifbool{weAreInTheAppendix}{\color{textBlack!50}\titlepartSubsection} + {\color{middle}\titlepartSection.\color{textBlack!50}\titlepartSubsection}} +{\titleNumberExtraDistance} +{\titleformatSubsection} + +\titleformat{\subsubsection}[block] +{\titleformatBase} +{\color{middle}\titlepartSection.\color{textBlack!50}\titlepartSubsection.\color{textBlack}\titlepartSubsubsection} +{\titleNumberExtraDistance} +{\titleformatSubsubsection} + +\titleformat{\paragraph}[runin] +{\titleformatBase} +{\titleformatParagraph\theparagraph} +{0em} +{\titleformatParagraph}% +[] + +% command left before after +\titlespacing*{\section} {0pt} {1em} {1em} +\titlespacing*{\subsection} {0em} {1em} {1em} +\titlespacing*{\subsubsection} {0em} {1em} {1em} +\titlespacing*{\paragraph} {0em} {1em} {1em} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Grafiken %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage{graphicx} % um Bilder einbinden zu können +\usepackage{pdfpages} % Ganzseitig externe PDFs einbinden (z.B. für Aufgabenstellung) +\usepackage{tikz} % Zeichnen per Code +\usepackage{subfigure} +\usepackage{wrapfig} +%Bilder bleiben im Kapitel +\usepackage[section]{placeins} +%Bilder bleiben genau an der stelle wo sie eingefügt werden sollen. +\usepackage{float} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Tabellen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\usepackage{array} +\usepackage{multirow} +\newcolumntype{C}[1]{>{\centering\arraybackslash}m{#1}} +\usepackage{diagbox} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% SI-Einheiten und Zahlendarstellung %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage{siunitx} +\sisetup{ + detect-all, % Font an die Einstellungen des umgebenden Textes anpassen + detect-inline-family = math, %TODO math/text prüfen + detect-inline-weight = math, %TODO math/text prüfen + detect-display-math = true, % Font an Mathematik-Umgebungen anpassen + scientific-notation = engineering, % Wissenschaftliche Notation, Exponent als Vielfaches von drei + tight-spacing = true, % Whitespace reduzieren + output-product = \cdot,% Multiplikationszeichen + exponent-product = \,\cdot,% Multiplikationszeichen Exponent + binary-units = true, + output-decimal-marker = {,}, % Dezimaltrenner + per-mode = fraction,% symbol, fraction, reciprocal,reciprocal-positive-first, + % per-symbol = {/}, + separate-uncertainty, % Unsicherheit wird separat mit \pm ausgegeben + list-final-separator = { und }, + list-pair-separator = { und }, + range-phrase = { bis } +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Quellcode %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage{listings} + +% Nutze das Wort Quellcode anstelle von Listing +\renewcommand{\lstlistingname}{Quellcode} + +%% Fixing highlighting error +\newcommand{\lstinlinemap}[1]{\lstinline{#1}} + +\ifbool{useColor}{ + \def\listingBasicstyle {\color{black}\ttfamily\small} + \def\listingKeywordstyle {\color{AccentStrong}\bfseries} + \def\listingStringstyle {\color{AccentMiddle}\slshape} + \def\listingCommentstyle {\color{AccentWeak}\fontseries{l}\selectfont} + \def\listingEmphstyle {\color{AccentStrong}\bfseries} + \def\listingRulecolor {\color{AccentWeak}} + \def\listingNumbercolor {\color{AccentWeak!60}} +}{ + \def\listingBasicstyle {\color{pureK}\ttfamily\small} + \def\listingKeywordstyle {\color{pureK}\bfseries} + \def\listingStringstyle {\color{pureK}\slshape} + \def\listingCommentstyle {\color{pureK}\fontseries{l}\selectfont} + \def\listingEmphstyle {\color{pureK}\bfseries\underbar} + \def\listingRulecolor {\color{pureK!50}} + \def\listingNumbercolor {\color{pureK!26}} +} + +\lstset{ + language=C++, + basicstyle = \listingBasicstyle, % Basisformat + keywordstyle= \listingKeywordstyle, % Schlüsselwörter + stringstyle = \listingStringstyle, % Strings + commentstyle= \listingCommentstyle, % Kommentare + emphstyle = \listingEmphstyle, % Hervorhebungen + % + % extendedchars=true, %Erweiterte Zeichensätze in Listings benutzen (aber nur Single-Byte!) + morekeywords={define, uint8_t}, + breaklines=true, % Zeilen werden Umgebrochen + breakatwhitespace=true, % erlaube Zeilenumbrüche nur an Whitespace + breakindent=0em, + breakautoindent=true, % bei Zeilenumbruch automatisch einrücken + % + prebreak=, + postbreak=\mbox{$\hookrightarrow$\hspace{-0.34em}\hphantom{m}}, + % + showstringspaces=true, % Leerzeichen in Strings zeigen + showspaces=false, % Leerzeichen anzeigen? + showtabs=false, % Tabs anzeigen? + tabsize=3, % Zeichenbreite eines Tabs + % + keepspaces=false, % Erlaubt die Unterdrückung von Leerzeichen zugunsten eines besseren Spalten-Layouts + columns=fixed, % Zeichenbreite + % + captionpos=b, % Position der Beschriftung + xleftmargin=2.2em, % Abstand zum Rand + xrightmargin=0.35em, % + framexleftmargin=0em, % Abstand im Rahmen + framexrightmargin=0pt, % + framexbottommargin=2pt, % + framextopmargin=0pt, % + frame=tblr, % Rahmen anzeigen + frameround=tftf, % t: abgerundete Ecke, f: eckige Ecke + backgroundcolor=\color{listingBackground}, % Hintergrundfarbe + rulecolor=\listingRulecolor,% Farbe der Umrandung + % + numbers=left, + numberstyle=\scriptsize\ttfamily\listingNumbercolor, %Stil der Zeilennummern + stepnumber=1, +} + +\lstdefinestyle{cpp}{ + language=C++, + basicstyle = \listingBasicstyle, % Basisformat + keywordstyle= \listingKeywordstyle, % Schlüsselwörter + stringstyle = \listingStringstyle, % Strings + commentstyle= \listingCommentstyle, % Kommentare + emphstyle = \listingEmphstyle, % Hervorhebungen + morekeywords={define, uint8_t}, + % + % extendedchars=true, %Erweiterte Zeichensätze in Listings benutzen (aber nur Single-Byte!) + breaklines=true, % Zeilen werden Umgebrochen + breakatwhitespace=true, % erlaube Zeilenumbrüche nur an Whitespace + breakindent=0em, + breakautoindent=true, % bei Zeilenumbruch automatisch einrücken + % + prebreak=, + postbreak=\mbox{$\hookrightarrow$\hspace{-0.34em}\hphantom{m}}, + % + showstringspaces=true, % Leerzeichen in Strings zeigen + showspaces=false, % Leerzeichen anzeigen? + showtabs=false, % Tabs anzeigen? + tabsize=3, % Zeichenbreite eines Tabs + % + keepspaces=false, % Erlaubt die Unterdrückung von Leerzeichen zugunsten eines besseren Spalten-Layouts + columns=fixed, % Zeichenbreite + % + captionpos=b, % Position der Beschriftung + xleftmargin=2.2em, % Abstand zum Rand + xrightmargin=0.35em, % + framexleftmargin=0em, % Abstand im Rahmen + framexrightmargin=0pt, % + framexbottommargin=2pt, % + framextopmargin=0pt, % + frame=tblr, % Rahmen anzeigen + frameround=tftf, % t: abgerundete Ecke, f: eckige Ecke + backgroundcolor=\color{listingBackground}, % Hintergrundfarbe + rulecolor=\listingRulecolor,% Farbe der Umrandung + % + numbers=left, + numberstyle=\scriptsize\ttfamily\listingNumbercolor, %Stil der Zeilennummern + stepnumber=1, +} + +\lstdefinestyle{java}{ + language=Java, + basicstyle = \listingBasicstyle, % Basisformat + keywordstyle= \listingKeywordstyle, % Schlüsselwörter + stringstyle = \listingStringstyle, % Strings + commentstyle= \listingCommentstyle, % Kommentare + emphstyle = \listingEmphstyle, % Hervorhebungen + morekeywords={define}, + % + % extendedchars=true, %Erweiterte Zeichensätze in Listings benutzen (aber nur Single-Byte!) + breaklines=true, % Zeilen werden Umgebrochen + breakatwhitespace=true, % erlaube Zeilenumbrüche nur an Whitespace + breakindent=0em, + breakautoindent=true, % bei Zeilenumbruch automatisch einrücken + % + prebreak=, + postbreak=\mbox{$\hookrightarrow$\hspace{-0.34em}\hphantom{m}}, + % + showstringspaces=true, % Leerzeichen in Strings zeigen + showspaces=false, % Leerzeichen anzeigen? + showtabs=false, % Tabs anzeigen? + tabsize=3, % Zeichenbreite eines Tabs + % + keepspaces=false, % Erlaubt die Unterdrückung von Leerzeichen zugunsten eines besseren Spalten-Layouts + columns=fixed, % Zeichenbreite + % + captionpos=b, % Position der Beschriftung + xleftmargin=2.2em, % Abstand zum Rand + xrightmargin=0.35em, % + framexleftmargin=0em, % Abstand im Rahmen + framexrightmargin=0pt, % + framexbottommargin=2pt, % + framextopmargin=0pt, % + frame=tblr, % Rahmen anzeigen + frameround=tftf, % t: abgerundete Ecke, f: eckige Ecke + backgroundcolor=\color{listingBackground}, % Hintergrundfarbe + rulecolor=\listingRulecolor,% Farbe der Umrandung + % + numbers=left, + numberstyle=\scriptsize\ttfamily\listingNumbercolor, %Stil der Zeilennummern + stepnumber=1, +} + + +\lstset{literate= % Deutsche Umlaute und ß in Listings erlauben + {Ö}{{\"O}}{1} + {Ä}{{\"A}}{1} + {Ü}{{\"U}}{1} + {ß}{{\ss}}{1} + %{ẞ}{{\MakeUppercase{\ss}}}{1} % KNOWNISSUE: der aktuell verwendete font enthält das zeichen leider nicht, also lieber erstmal weglassen ;-) + {ü}{{\"u}}{1} + {ä}{{\"a}}{1} + {ö}{{\"o}}{1} +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Format der Float-Beschriftungen %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage{caption} + +%Farbiger Text geht mit labelfont={bf,it,color=red} +% Mehr Infos zu CaptionStyle http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/caption/caption-eng.pdf +\DeclareCaptionStyle{myCaptionStyle}{% + format=plain, % Basis-Format + labelsep=quad, % Abstand Typ/Nummer <-> Beschriftung + % indention=-7em, % + margin=0.5em, % Zusatzabstand Links + singlelinecheck=false, % + labelfont={sf,small,bf,color=captionLabel}, % Font Typ/Nummer + textfont={sf,small, color=captionText}, % Font Beschriftung +} + +\DeclareCaptionStyle{mySubCaptionStyle}{% + format=plain, % Basis-Format + labelsep=space, % Abstand Typ/Nummer <-> Beschriftung + % indention=-7em, % + margin=0.5em, % Zusatzabstand links + singlelinecheck=false, % + labelfont={sf,small,bf, color=subcaptionLabel}, % Font Typ/Nummer + textfont={sf,small, color=subcaptionText}, % Font Beschriftung +} + +\captionsetup[table]{style=myCaptionStyle} +\captionsetup[figure]{style=myCaptionStyle} +\captionsetup[lstlisting]{style=myCaptionStyle} + +\captionsetup[subfigure]{style=mySubCaptionStyle} +\captionsetup[subtable]{style=mySubCaptionStyle} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% PDF-Meta-Informationen und Links im Dokument %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\usepackage[bookmarksnumbered,hyperfootnotes=false]{hyperref} + +\ifbool{linksUmrahmen}{ + % nichts +}{ + \hypersetup{hidelinks} % Link-Markierung verstecken +} + +\hypersetup{ + colorlinks=false, + citecolor=AccentStrong, + linkcolor=AccentMiddle, + urlcolor=AccentWeak} \ No newline at end of file diff --git a/doc/projectDocumentation/prefix.tex b/doc/projectDocumentation/prefix.tex new file mode 100644 index 0000000000000000000000000000000000000000..b435d9eee9b5c5994faa6fb45ddd824fd30d3b74 --- /dev/null +++ b/doc/projectDocumentation/prefix.tex @@ -0,0 +1,44 @@ +%%% verschiedene Definitionen +\ifbool{useColor}{ + \newcommand{\bologopdf}{Medien/BO-Logo_CVH_quer.pdf} +}{ + \newcommand{\bologopdf}{Medien/BO-Logo_CVH_quer_grey.pdf} +} + + +% Titelseite +\input{titelseite} +\clearpage + +% Text soll bei doppelseitigen Arbeiten links beginnen +\ifbool{doppelseitig}{ + \ifthenelse{\isodd{\thepage}}{ + % nichts + }{ + \clearpage + } +}{} + +% Zu Beginn römisch nummerieren +\pagenumbering{Roman} +\setcounter{page}{2} + +%Abstract +\ifbool{showAbstract}{ +\section*{Abstract} + \input{Abstract} + \clearpage +}{} + +% Inhaltsverzeichnis +\newpage +{ +\thispagestyle{plain} +\tableofcontents +\clearpage +} + + +% Ab hier arabisch nummerieren +\pagenumbering{arabic} +%\setcounter{page}{4} \ No newline at end of file diff --git a/doc/projectDocumentation/titelseite.tex b/doc/projectDocumentation/titelseite.tex new file mode 100644 index 0000000000000000000000000000000000000000..1148b99378667e08a9c706fc7d009d5954880793 --- /dev/null +++ b/doc/projectDocumentation/titelseite.tex @@ -0,0 +1,58 @@ +\thispagestyle{empty} + +\parbox[t]{5cm}{\raggedright\sffamily\fachbereich} + +\begin{picture}(0.0,0.0) +\put(8.71,-1.15){ + \ifbool{isCVH}{ + \includegraphics[scale=0.5]{\bologopdf} + }{ + \includegraphics[scale=0.5,clip,trim=216 0 0 0]{\bologopdf} + } +} +\end{picture} + +\vfill + +\begin{center} + \sffamily + {\Huge{\textbf{\titel}}\par} + \bigskip\bigskip + von\par + \smallskip + \Large\textbf{\autor}\par + \smallskip + \ifbool{showMatrikelnummer}{ + \large{Matrikelnummer: \matrikelnummer}\par + }{} + \ifbool{isAbschlussarbeit}{ + \bigskip\bigskip\bigskip + \artDerArbeit\ im Studiengang\\ + \studiengang\\ + zur Erlangung des akademischen Grades\\ + \abschlussgrad + }{ + \bigskip\bigskip\bigskip + \fachsemester. Fachsemester im Studiengang\\ + \studiengang\\ + } + + +\end{center} + +\vfill +\vfill + +\begin{tabular}{ll} + \sffamily + \textbf{Eingereicht am:} & \abgabeort, den \abgabedatum\\ + \\ + \ifbool{hasZweitenPruefer}{ + + \textbf{1.~Prüfer:} & \prueferEins \\ + \textbf{2.~Prüfer:} & \prueferZwei + }{ + \textbf{Prüfer:} & \prueferEins \\ + } + +\end{tabular} \ No newline at end of file diff --git a/src/lightControlSoftware/ressourcen/images/Kiwi.png b/src/lightControlSoftware/ressourcen/images/Kiwi.png new file mode 100644 index 0000000000000000000000000000000000000000..ec84cd3b69508c8fa2e8912541eb79aea3ff3073 Binary files /dev/null and b/src/lightControlSoftware/ressourcen/images/Kiwi.png differ diff --git a/src/lightControlSoftware/src/view/test/TestUI.java b/src/lightControlSoftware/src/view/test/TestUI.java deleted file mode 100644 index 067c6b821302eaa1ca83d89fe366463c768da202..0000000000000000000000000000000000000000 --- a/src/lightControlSoftware/src/view/test/TestUI.java +++ /dev/null @@ -1,89 +0,0 @@ -package view.test; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -import javafx.application.Application; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.Scene; -import javafx.scene.control.Button; -import javafx.scene.control.ComboBox; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Pane; -import javafx.stage.Stage; - -public class TestUI extends Application{ - - protected final PropertyChangeSupport propertySupport = new PropertyChangeSupport(this); - private PropertyChangeListener fixtureListener; - public void addPropertyChangeListener(PropertyChangeListener listener) { - propertySupport.addPropertyChangeListener(listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - propertySupport.removePropertyChangeListener(listener); - } - - public void printText(String text) { - System.out.println(text); - } - - public TestUI() { - this.fixtureListener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent event) { - if(event.getPropertyName().equals("Test")) { - if((boolean) event.getNewValue()) { - printText("True"); - } else { - printText("False"); - } - } - } - }; - } - - - public static void main(String[] args) { - launch(args); - - } - - @Override - public void start(Stage stage) throws Exception { - - ObservableList<String> options = FXCollections.observableArrayList( - "Option 1", - "Option 2", - "Option 3" - ); - ComboBox<String> comboBox = new ComboBox<>(options); - comboBox.setOnAction(event -> { - propertySupport.firePropertyChange("Test", true, false); - }); - - Button buttonAnmelden = new Button("Anmelden"); - buttonAnmelden.setOnAction(event -> { - this.addPropertyChangeListener(fixtureListener); - }); - - Button buttonAbmelden = new Button("Abmelden"); - buttonAbmelden.setOnAction(event -> { - this.removePropertyChangeListener(fixtureListener); - }); - - - Pane root = new Pane(); - HBox hBox = new HBox(comboBox, buttonAnmelden, buttonAbmelden); - root.getChildren().add(hBox); - Scene scene = new Scene(root); - stage.setMinWidth(800); - stage.setMinHeight(625); - stage.setScene(scene); - stage.show(); - - } - -} diff --git a/src/playground/TestingTypeSize.cpp b/src/playground/TestingTypeSize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6baa056accf17b7dfcfe2f2a57af26a79018cb73 --- /dev/null +++ b/src/playground/TestingTypeSize.cpp @@ -0,0 +1,6 @@ +#include <iostream> + +int main() +{ + std::cout << "Hello World" << std::endl; +} \ No newline at end of file diff --git a/src/playground/eepromTest/config.h b/src/playground/eepromTest/config.h new file mode 100644 index 0000000000000000000000000000000000000000..1d9449bffa07d6d184075ffb456fcc3c450da573 --- /dev/null +++ b/src/playground/eepromTest/config.h @@ -0,0 +1,63 @@ +// gloabl values +#define MAX_DMX_CHANNEL 100 +#define NUMBER_OF_PRESETS 6 +#define NUMBER_OF_LED_COLORS 3 +#define EEPROM_START_ADRESS 0 + + +// LED pins +#define LED_1_PINOUT_R 48 +#define LED_1_PINOUT_G 46 +#define LED_1_PINOUT_B 44 + +#define LED_2_PINOUT_R 42 +#define LED_2_PINOUT_G 40 +#define LED_2_PINOUT_B 38 + +#define LED_3_PINOUT_R 49 +#define LED_3_PINOUT_G 47 +#define LED_3_PINOUT_B 45 + +#define LED_4_PINOUT_R 43 +#define LED_4_PINOUT_G 41 +#define LED_4_PINOUT_B 39 + +#define LED_5_PINOUT_R 37 +#define LED_5_PINOUT_G 35 +#define LED_5_PINOUT_B 32 + +#define LED_6_PINOUT_R 31 +#define LED_6_PINOUT_G 29 +#define LED_6_PINOUT_B 27 + +// buttons pins +#define BUTTON_1_PININ 36 +#define BUTTON_2_PININ 34 +#define BUTTON_3_PININ 32 +#define BUTTON_4_PININ 30 +#define BUTTON_5_PININ 28 +#define BUTTON_6_PININ 26 + +// dmx pins +#define DMX_PINOUT 24 + +// preset state values +#define P_DEAKTIV 0 +#define P_ACTIVE 1 +#define P_PART_ACTIVE 2 + +// common group id values +#define DEFAULT_GROUP_ID 0 + +// Ethernet communication +#define MAC_ADDRESS_PART_01 0xA8; +#define MAC_ADDRESS_PART_02 0x61; +#define MAC_ADDRESS_PART_03 0x0A; +#define MAC_ADDRESS_PART_04 0xAE; +#define MAC_ADDRESS_PART_05 0xE0; +#define MAC_ADDRESS_PART_06 0x13; + +#define IP_ADDRESS_PART_01 192; +#define IP_ADDRESS_PART_02 168; +#define IP_ADDRESS_PART_03 178; +#define IP_ADDRESS_PART_04 109; \ No newline at end of file diff --git a/src/playground/eepromTest/eepromTest.ino b/src/playground/eepromTest/eepromTest.ino new file mode 100644 index 0000000000000000000000000000000000000000..4e6005eeef037ebe060bf771c823f945f14fea15 --- /dev/null +++ b/src/playground/eepromTest/eepromTest.ino @@ -0,0 +1,107 @@ +#include <Arduino.h> +#include <EEPROM.h> +#include "config.h" +#include <ArduinoSTL.h> +#include "set.h" + +Set test; + +// structs + +struct channel +{ + bool isActive; + uint8_t value; +}; + +struct storeDate +{ + uint8_t state; + channel channels[2]; +}; + +// varables +int buttons[] = {BUTTON_1_PININ, BUTTON_2_PININ, BUTTON_3_PININ, BUTTON_4_PININ, BUTTON_5_PININ, BUTTON_6_PININ}; +storeDate saveData; +storeDate loadData; +channel saveChannel; + + + +// setup functions +void setupButtons() +{ + for(int i = 0; i < NUMBER_OF_PRESETS; i++){ + pinMode(buttons[i], INPUT_PULLUP); + } +} + +// check functinos +void checkButtonIsPressed() +{ + for(int i = 0; i < NUMBER_OF_PRESETS; i++) { + if(digitalRead(buttons[i]) == LOW) { + switch(i) + { + case 0: + Serial.println("EEPROM leeren."); + for(int i = 0; i<10; i++) { + EEPROM.update(i, 0x00); + } + break; + case 1: + saveChannel = {false, 0}; + saveData.state = 0; + saveData.channels[0] = saveChannel; + saveChannel = {false, 0}; + saveData.channels[1] = saveChannel; + Serial.println("Das Strukt mit 0er Daten wird in den EEPROM geschrieben."); + Serial.println("S:" + String(saveData.state) + " C1-U:" + String(saveData.channels[0].isActive) + " C1-V:" + String(saveData.channels[0].value)); + Serial.println("S:" + String(saveData.state) + " C2-U:" + String(saveData.channels[1].isActive) + " C2-V:" + String(saveData.channels[1].value)); + //EEPROM.put(0, saveData); + break; + case 2: + saveChannel = {true, 250}; + saveData.state = 1; + saveData.channels[0] = saveChannel; + saveChannel = {false, 30}; + saveData.channels[1] = saveChannel; + Serial.println("Das Strukt mit gefüllten Daten wird in den EEPROM geschrieben."); + Serial.println("S:" + String(saveData.state) + " C1-U:" + String(saveData.channels[0].isActive) + " C1-V:" + String(saveData.channels[0].value)); + Serial.println("S:" + String(saveData.state) + " C2-U:" + String(saveData.channels[1].isActive) + " C2-V:" + String(saveData.channels[1].value)); + EEPROM.put(0, saveData); + break; + case 3: + Serial.println("Die ersten 10 Bytes werden aus den EEPROM geladen."); + for(int i = 0; i<10; i++) { + Serial.println("Byte " + String(i) + " V: " + String(EEPROM.read(i))); + } + break; + case 4: + loadData; + Serial.println("Das Strukt wird aus den EEPROM geladen."); + EEPROM.get(0, loadData); + Serial.println("S:" + String(loadData.state) + " C1-U:" + String(loadData.channels[0].isActive) + " C1-V:" + String(loadData.channels[0].value)); + Serial.println("S:" + String(loadData.state) + " C2-U:" + String(loadData.channels[1].isActive) + " C2-V:" + String(loadData.channels[1].value)); + break; + case 5: + Serial.println("Inhalts des save structs:"); + Serial.println("S:" + String(saveData.state) + " C1-U:" + String(saveData.channels[0].isActive) + " C1-V:" + String(saveData.channels[0].value)); + Serial.println("S:" + String(saveData.state) + " C2-U:" + String(saveData.channels[1].isActive) + " C2-V:" + String(saveData.channels[1].value)); + break; + } + while(digitalRead(buttons[i]) == LOW){} + } + } +} + +void setup() +{ + Serial.begin(9600); + setupButtons(); +} + +void loop() +{ + checkButtonIsPressed(); +} diff --git a/src/playground/oldLightControllFile.ino b/src/playground/oldLightControllFile.ino new file mode 100644 index 0000000000000000000000000000000000000000..c55ea93775944a7becaea0535f1a54d79250a7a1 --- /dev/null +++ b/src/playground/oldLightControllFile.ino @@ -0,0 +1,254 @@ +#include <ArduinoSTL.h> +#include <DmxSimple.h> +#include "Preset.h" +#include <SET.h> + +#define MAX_DMX_CHANNEL 100 +#define MAX_LAMP_CHANNEL 5 +#define PIN_DMX_OUT 26 +#define NUMBER_OF_PRESETS 6 +#define BUFFER_SIZE 5 + +int lampPins[] = {33,31,35,37,32,30}; +int buttonPins[] = {29,27,25,23,22,24}; +char serialBuffer[BUFFER_SIZE]; +std::vector<Preset> presets; +std::vector<byte> dmxOut(MAX_DMX_CHANNEL); + + +// dmx functions +void sendDmx() { + for(int i = 0; i < MAX_DMX_CHANNEL; i++){ + DmxSimple.write(i+1, dmxOut[i]); + } +} + +void updateDmx(std::vector<byte>& values, int reset) { + for(int i = 0; i < MAX_DMX_CHANNEL; i++){ + if(values[i]) { + if(!reset) { + dmxOut[i] = values[i]; + } else { + dmxOut[i] = 0; + } + } + } +} + +// buttons functions +void checkButtons() { + for(int i = 0; i < NUMBER_OF_PRESETS; i++) { + if(digitalRead(buttonPins[i]) == LOW) { + if(presets[i].getPresetStatus() == Preset::OFF) { + activatePreset(i); + } else { + deactivateGroup(presets[i].getGroupId()); + } + while(digitalRead(buttonPins[i]) == LOW) {} + } + } +} + +// preset functions +void loadPresets() { + for(int i = 0; i < NUMBER_OF_PRESETS; i++){ + presets[i].loadDmxArray(); + } +} + +void activatePreset(int presetNr) { + deactivateOtherGroupPresets(presetNr); + presets[presetNr].setPresetStatus(Preset::ACTIVE); + std::vector<byte> values = presets[presetNr].getDmxArray(); + updateDmx(values, 0); + char buff[] = {'P','A',presetNr,0,0}; + Serial.write(buff, BUFFER_SIZE); +} + +void deactivatePreset(int presetNr) { + presets[presetNr].setPresetStatus(Preset::OFF); + std::vector<byte> values = presets[presetNr].getDmxArray(); + updateDmx(values, 1); + char buff[] = {'P','D',presetNr,0,0}; + Serial.write(buff, BUFFER_SIZE); +} + +void clearPreset(int presetNr) { + deactivatePreset(presetNr); + std::vector<byte> dmxData(MAX_DMX_CHANNEL); + presets[presetNr].setDmxArray(dmxData); +} + +void setPreset(int presetNr, int channelNr, int value){ + std::vector<byte> dmxData(MAX_DMX_CHANNEL); + dmxData = presets[presetNr].getDmxArray(); + dmxData[channelNr - 1] = value; + presets[presetNr].setDmxArray(dmxData); +} + +// group functions +void activateGroup(byte groupId) { + for(int i = 0; i < NUMBER_OF_PRESETS; i++) { + if(presets[i].getPresetStatus() == Preset::OFF && presets[i].getGroupId() == groupId) { + presets[i].setPresetStatus(Preset::ACTIVE); + } + } +} + +void deactivateGroup(byte groupId) { + for(int i = 0; i < NUMBER_OF_PRESETS; i++) { + if(presets[i].getPresetStatus() == Preset::ACTIVE && presets[i].getGroupId() == groupId) { + deactivatePreset(i); + } + } +} + +void deactivateOtherGroupPresets(int presetId) { + byte groupId = presets[presetId].getGroupId(); + for(int i = 0; i < NUMBER_OF_PRESETS; i++) { + if(i != presetId && presets[i].getPresetStatus() == Preset::ACTIVE && presets[i].getGroupId() == groupId) { + deactivatePreset(i); + } + } +} + +// communication functions +void serialEvent() { + if(Serial.available()) { + Serial.readBytes(serialBuffer, BUFFER_SIZE); + + String command = ""; + command += serialBuffer[0]; + command += serialBuffer[1]; + int presetNr = serialBuffer[2]; + int channelNr = serialBuffer[3]; + byte value = (byte)serialBuffer[4]; + + if(command == "AP") { + activatePreset(presetNr); + } else if (command == "DP") { + deactivatePreset(presetNr); + } else if (command == "CP") { + clearPreset(presetNr); + } else if (command == "SP") { + setPreset(presetNr, channelNr, value); + } else if (command == "SC") { + dmxOut[channelNr-1] = value; + } else if (command == "SG") { + presets[presetNr].setGroupId((byte)channelNr); + } else if (command == "AG") { + activateGroup(channelNr); + } else if (command == "DG") { + deactivateGroup(channelNr); + } else if (command == "RS") { + sendStatus(); + } + } +} + +void sendStatus() { + for(int i = 0; i < NUMBER_OF_PRESETS; i++) { + if(presets[i].getPresetStatus() == Preset::ACTIVE) { + Serial.println("PA00" + String(i) + "000000"); + } + } +} + +// setup functions +void setupButtons() { + for(int i = 0; i < NUMBER_OF_PRESETS; i++){ + pinMode(buttonPins[i], INPUT_PULLUP); + } +} + +void setupLamps() { + for(int i = 0; i < NUMBER_OF_PRESETS; i++){ + pinMode(lampPins[i], OUTPUT); + } +} + +void setupPresets() { + for(int i = 0; i < NUMBER_OF_PRESETS; i++){ + Preset* presetPtr = new Preset(lampPins[i], i*(MAX_DMX_CHANNEL+2), MAX_DMX_CHANNEL); + presets.push_back(*presetPtr); + presets[i].loadDmxArray(); + presets[i].loadGroupId(); + presets[i].loadPresetStatus(); + if(presets[i].getPresetStatus() == Preset::ACTIVE) { + activatePreset(i); + } + } + + +} + +void setupData() { + std::vector<byte> scene1(MAX_DMX_CHANNEL); + scene1[0] = 255; + scene1[1] = 255; + scene1[2] = 255; + scene1[3] = 255; + scene1[4] = 255; + scene1[5] = 255; + scene1[6] = 255; + scene1[7] = 255; + scene1[8] = 255; + scene1[9] = 255; + scene1[10] = 255; + scene1[11] = 255; + presets[0].setDmxArray(scene1); + presets[0].setGroupId(1); + + std::vector<byte> scene2(MAX_DMX_CHANNEL); + scene2[0] = 255; + scene2[3] = 255; + presets[1].setDmxArray(scene2); + presets[1].setGroupId(2); + + std::vector<byte> scene3(MAX_DMX_CHANNEL); + scene3[1] = 255; + scene3[4] = 255; + presets[2].setDmxArray(scene3); + presets[2].setGroupId(2); + + std::vector<byte> scene4(MAX_DMX_CHANNEL); + scene4[8] = 255; + scene4[11] = 255; + presets[3].setDmxArray(scene4); + presets[3].setGroupId(3); + + std::vector<byte> scene5(MAX_DMX_CHANNEL); + scene5[6] = 255; + scene5[8] = 255; + scene5[9] = 255; + scene5[11] = 255; + presets[4].setDmxArray(scene5); + presets[4].setGroupId(3); + + std::vector<byte> scene6(MAX_DMX_CHANNEL); + scene6[12] = 255; + presets[5].setDmxArray(scene6); + +} + +void setup() { + Serial.begin(9600); + + setupButtons(); + setupLamps(); + setupPresets(); + //setupData(); + + // setup DMXSimple + DmxSimple.usePin(PIN_DMX_OUT); + DmxSimple.maxChannel(MAX_DMX_CHANNEL); +} + +// main programm +void loop() { + // send dmx data + sendDmx(); + + // check buttons + checkButtons(); +} diff --git a/src/playground/output/TestingTypeSize.exe b/src/playground/output/TestingTypeSize.exe new file mode 100644 index 0000000000000000000000000000000000000000..a10c0c619a9cf8fbfa7d900657b14d3c7356653f Binary files /dev/null and b/src/playground/output/TestingTypeSize.exe differ diff --git a/src/playground/setTest/setTest.ino b/src/playground/setTest/setTest.ino new file mode 100644 index 0000000000000000000000000000000000000000..33ff3260801f470d83d510b7ae5505b5df3f8dee --- /dev/null +++ b/src/playground/setTest/setTest.ino @@ -0,0 +1,17 @@ +#include "set.h" +Set test = Set(true); + +void setup() { + Serial.begin(9600); + + Serial.println("Dert Wert 255 wird hinzugefügt"); + test.add(255); + Serial.println("Dert Wert 255 wird ausgegeben"); + Serial.println("Dert wert 255 ist enthalten: " + String(test.has(255))); + +} + +void loop() { + // put your main code here, to run repeatedly: + +} diff --git a/src/playground/testProgramm/config.h b/src/playground/testProgramm/config.h new file mode 100644 index 0000000000000000000000000000000000000000..1d9449bffa07d6d184075ffb456fcc3c450da573 --- /dev/null +++ b/src/playground/testProgramm/config.h @@ -0,0 +1,63 @@ +// gloabl values +#define MAX_DMX_CHANNEL 100 +#define NUMBER_OF_PRESETS 6 +#define NUMBER_OF_LED_COLORS 3 +#define EEPROM_START_ADRESS 0 + + +// LED pins +#define LED_1_PINOUT_R 48 +#define LED_1_PINOUT_G 46 +#define LED_1_PINOUT_B 44 + +#define LED_2_PINOUT_R 42 +#define LED_2_PINOUT_G 40 +#define LED_2_PINOUT_B 38 + +#define LED_3_PINOUT_R 49 +#define LED_3_PINOUT_G 47 +#define LED_3_PINOUT_B 45 + +#define LED_4_PINOUT_R 43 +#define LED_4_PINOUT_G 41 +#define LED_4_PINOUT_B 39 + +#define LED_5_PINOUT_R 37 +#define LED_5_PINOUT_G 35 +#define LED_5_PINOUT_B 32 + +#define LED_6_PINOUT_R 31 +#define LED_6_PINOUT_G 29 +#define LED_6_PINOUT_B 27 + +// buttons pins +#define BUTTON_1_PININ 36 +#define BUTTON_2_PININ 34 +#define BUTTON_3_PININ 32 +#define BUTTON_4_PININ 30 +#define BUTTON_5_PININ 28 +#define BUTTON_6_PININ 26 + +// dmx pins +#define DMX_PINOUT 24 + +// preset state values +#define P_DEAKTIV 0 +#define P_ACTIVE 1 +#define P_PART_ACTIVE 2 + +// common group id values +#define DEFAULT_GROUP_ID 0 + +// Ethernet communication +#define MAC_ADDRESS_PART_01 0xA8; +#define MAC_ADDRESS_PART_02 0x61; +#define MAC_ADDRESS_PART_03 0x0A; +#define MAC_ADDRESS_PART_04 0xAE; +#define MAC_ADDRESS_PART_05 0xE0; +#define MAC_ADDRESS_PART_06 0x13; + +#define IP_ADDRESS_PART_01 192; +#define IP_ADDRESS_PART_02 168; +#define IP_ADDRESS_PART_03 178; +#define IP_ADDRESS_PART_04 109; \ No newline at end of file diff --git a/src/playground/testProgramm/structTest.cpp b/src/playground/testProgramm/structTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bafab07969f89b39ff200982e7d4313360a7ab59 --- /dev/null +++ b/src/playground/testProgramm/structTest.cpp @@ -0,0 +1,18 @@ +#include <iostream> +#include <typeinfo> + +using namespace std; + +struct ArtCommands +{ + uint8_t test; + uint8_t test2; +}; + +int main() { + ArtCommands testValue; + testValue.test = 120; + testValue.test2 = 60; + cout << typeid(ArtCommands).name(); + return 0; +} \ No newline at end of file diff --git a/src/playground/testProgramm/testProgramm.ino b/src/playground/testProgramm/testProgramm.ino new file mode 100644 index 0000000000000000000000000000000000000000..a4eded805886491613e27a1996082fbbd10a513f --- /dev/null +++ b/src/playground/testProgramm/testProgramm.ino @@ -0,0 +1,22 @@ +#include "config.h" +#include <Arduino.h> + +void setup() { + Serial.begin(9600); + pinMode(LED_1_PINOUT_R, OUTPUT); + pinMode(LED_1_PINOUT_G, OUTPUT); + pinMode(LED_1_PINOUT_B, OUTPUT); + + pinMode(BUTTON_1_PININ, INPUT_PULLUP); +} + +void loop() { + if(digitalRead(BUTTON_1_PININ) == LOW) + { + digitalWrite(LED_1_PINOUT_R, HIGH); + } + else + { + digitalWrite(LED_1_PINOUT_R, LOW); + } +} \ No newline at end of file diff --git a/src/playground/testSendingUDP_ART-NET.ps1 b/src/playground/testSendingUDP_ART-NET.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..3fe933187c46e828cdb5c384fbbc2e7bc82a4f00 --- /dev/null +++ b/src/playground/testSendingUDP_ART-NET.ps1 @@ -0,0 +1,186 @@ + $ip = "192.168.0.101" + $broadcast = "192.168.0.255" + +function sendArtPoll +{ + + $client = new-object net.sockets.udpclient(0) + + $send = [text.encoding]::ascii.getbytes("Art-Net") + $send += 0x00 #Byte 8 der Id + $send += 0x00 #OpCode + $send += 0x20 #OpCode + $send += 0x00 #Protokoll Version + $send += 0x10 #Protokoll Version + $send += 0x00 #Flag + $send += 0x00 #DiafPrioty + $send += 0x00 #Targeet Port + $send += 0x00 #Targeet Port + $send += 0x00 #Targeet Port + $send += 0x00 #Targeet Port + $send += 0x00 #EstMan + $send += 0x00 #EstMan + $send += 0x00 #Oem + $send += 0x00 #Oem + + [void] $client.send($send, $send.length, $broadcast, "6454") + $client.close() +} + + +function sendArtCommand +{ + param + ( + [String]$message + ) + + $client = new-object net.sockets.udpclient(0) + + $send = [text.encoding]::ascii.getbytes("Art-Net") + $send += 0x00 #Byte 8 der Id + $send += 0x00 #OpCode + $send += 0x24 #OpCode + $send += 0x00 #Protokoll Version + $send += 0x10 #Protokoll Version + $send += 0x00 #EstMan + $send += 0x00 #EstMan + $send += 0x00 #Länge + $send += [byte]$message.Length #Länge + $send += [text.encoding]::ascii.getbytes($message) + + + [void] $client.send($send, $send.length, $ip, "6454") + $client.close() +} + +function sendArtRequestData +{ + param + ( + [byte]$requestCodeHigh, + [byte]$requestCodeLow + ) + + $client = new-object net.sockets.udpclient(0) + + $send = [text.encoding]::ascii.getbytes("Art-Net") + $send += 0x00 #Byte 8 der Id + $send += 0x00 #OpCode + $send += 0x27 #OpCode + $send += 0x00 #Protokoll Version + $send += 0x10 #Protokoll Version + $send += 0x00 #EstMan + $send += 0x00 #EstMan + $send += 0x00 #Oem + $send += 0x00 #Oem + $send += $requestCodeHigh #Reqestcode Hi + $send += $requestCodeLow #Reqestcode Low + + for($i = 0; $i -le 22; $i++) + { + $send += 0x00 + } + + + [void] $client.send($send, $send.length, $ip, "6454") + $client.close() +} + +function sendArtDmx +{ + $client = new-object net.sockets.udpclient(0) + + $send = [text.encoding]::ascii.getbytes("Art-Net") + $send += 0x00 #Byte 8 der Id + $send += 0x00 #OpCode + $send += 0x50 #OpCode + $send += 0x00 #Protokoll Version + $send += 0x10 #Protokoll Version + $send += 0x00 #Sequenz + $send += 0x00 #Physikalischer Input + $send += 0x00 #SubUni + $send += 0x00 #Net + $send += 0x00 #Length Hi + $send += 0x0A #Length Lo + + $send += 0xFF #Dmx Channel 1 + $send += 0xFF #Dmx Channel 2 + $send += 0xFF #Dmx Channel 3 + $send += 0xFF #Dmx Channel 4 + $send += 0x00 #Dmx Channel 5 + $send += 0xFF #Dmx Channel 6 + $send += 0xFF #Dmx Channel 7 + $send += 0xFF #Dmx Channel 8 + $send += 0xFF #Dmx Channel 9 + $send += 0x00 #Dmx Channel 10 + + + [void] $client.send($send, $send.length, $ip, "6454") + $client.close() +} + + + +sendArtRequestData -requestCodeHigh 0x80 -requestCodeLow 0x00 + +for($i = 0; $i -le 100; $i++) +{ + sendArtDmx +} + + + +# Preset 0 blau +sendArtCommand -message "clearPreset={`"presetId`":0}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":1,`"value`":0}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":2,`"value`":0}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":3,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":4,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":5,`"value`":0}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":6,`"value`":0}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":7,`"value`":0}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":8,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":9,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":10,`"value`":0}" + +# Prest 0 weiß +sendArtCommand -message "clearPreset={`"presetId`":0}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":1,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":2,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":3,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":4,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":5,`"value`":0}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":6,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":7,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":8,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":9,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":0,`"groupId`":1,`"channel`":10,`"value`":0}" + +# Prest 5 weiß +sendArtCommand -message "clearPreset={`"presetId`":5}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":1,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":2,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":3,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":4,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":5,`"value`":0}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":6,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":7,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":8,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":9,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":10,`"value`":0}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":11,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":12,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":13,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":14,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":15,`"value`":0}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":16,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":17,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":18,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":19,`"value`":255}" +sendArtCommand -message "setPreset={`"presetId`":5,`"groupId`":4,`"channel`":20,`"value`":0}" + + +sendArtPoll +sendArtCommand -message "activatePreset={`"presetId`":0}" +sendArtDmx