App Entwicklungsanleitung und Beispielapp hinzugefügt
This commit is contained in:
parent
591ab2be0c
commit
1c78390fb2
58
apps/example.py
Executable file
58
apps/example.py
Executable file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import random
|
||||
import time
|
||||
|
||||
# Groesse des Bildschirms bestimmen
|
||||
Nx = int(sys.argv[1])
|
||||
Ny = int(sys.argv[2])
|
||||
|
||||
# Bestimme den Parameter
|
||||
time_ms = 100
|
||||
try:
|
||||
time_ms = int(sys.argv[3])
|
||||
except:
|
||||
pass
|
||||
|
||||
# Puffer fuer Pixel erstellen und mit 0 initialisieren
|
||||
buffer = bytearray(b"\x00" * (3 * Nx * Ny))
|
||||
|
||||
curPixel = 0
|
||||
|
||||
while True:
|
||||
# Zufaellige Pixel waeheln
|
||||
# rot
|
||||
x_r = random.randint(0, Nx-1)
|
||||
y_r = random.randint(0, Ny-1)
|
||||
i_r = 3*(x_r+Nx*y_r)
|
||||
# gruen
|
||||
x_g = random.randint(0, Nx-1)
|
||||
y_g = random.randint(0, Ny-1)
|
||||
i_g = 3*(x_g+Nx*y_g)
|
||||
# blau
|
||||
x_b = random.randint(0, Nx-1)
|
||||
y_b = random.randint(0, Ny-1)
|
||||
i_b = 3*(x_b+Nx*y_b)
|
||||
|
||||
# Pixel in Puffer schreiben
|
||||
# rot
|
||||
buffer[i_r+0] = 0xff # Rotanteil
|
||||
buffer[i_r+1] = 0x00 # Gruenanteil
|
||||
buffer[i_r+2] = 0x00 # Blauanteil
|
||||
# gruen
|
||||
buffer[i_g+0] = 0x00 # Rotanteil
|
||||
buffer[i_g+1] = 0xff # Gruenanteil
|
||||
buffer[i_g+2] = 0x00 # Blauanteil
|
||||
# blau
|
||||
buffer[i_b+0] = 0x00 # Rotanteil
|
||||
buffer[i_b+1] = 0x00 # Gruenanteil
|
||||
buffer[i_b+2] = 0xff # Blauanteil
|
||||
|
||||
|
||||
|
||||
# Zeige den Puffer an
|
||||
os.write(1, buffer)
|
||||
# warte time_ms ms
|
||||
time.sleep(time_ms*0.001)
|
@ -26,6 +26,7 @@ Apps = [
|
||||
{"guiname": "YoutubeDL", "name": "youtubedl", "cmd": "apps/youtubedl.sh", "persistent": False},
|
||||
{"guiname": "Show Framebuffer", "name": "fbcp", "cmd": ["apps/fbcp", "/dev/fb0"]},
|
||||
{"guiname": "Strobo", "name": "strobo", "cmd": "apps/strobo.py"},
|
||||
{"guiname": "Beispiel", "name": "example", "cmd": "apps/example.py"},
|
||||
|
||||
|
||||
#{"guiname": "Colored noise", "name": "cnoise", "cmd": "apps/cnoise", "persistent": False},
|
||||
|
BIN
doku/app-development.pdf
Normal file
BIN
doku/app-development.pdf
Normal file
Binary file not shown.
153
doku/app-development.tex
Normal file
153
doku/app-development.tex
Normal file
@ -0,0 +1,153 @@
|
||||
\documentclass[a5paper]{article}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{ngerman}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{listings}
|
||||
\usepackage{parskip}
|
||||
\setlength{\parindent}{0pt}
|
||||
\title{App Entwicklungsanleitung}
|
||||
\author{Andreas}
|
||||
\begin{document}
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\section{Allgemeines}
|
||||
Apps für den Pixelserver sind normale Konsolenanwendungen. Sie werden vom Pixelserver gestartet und generieren dann Bilder. Diese geben sie über die Standardausgabe aus und der Pixelserver zeigt sie dann an. Dies erlaubt es Apps in quasi allen Programmiersprachen zu entwickeln. Wenn der Nutzer eine App startet wird das entsprechende Programm ausgeführt und es wird vom Pixelserver beendet, wenn der Nutzer eine andere App auswählt. Hierbei kann Apps vom Nutzer ein zusätzlicher freier Parameter übergeben werden.
|
||||
\subsection{Persistente Apps}
|
||||
Einzelne Apps können auch als persistent markiert werden. Das heißt sie laufen dann auch im Hintergrund weiter, wenn der User eine andere App auswählt. Sie können auch keine Parameter übernehmen. Diese persistenten Apps sollten nur verwendet werden, wenn es für die Funktionalität \textbf{zwingend} notwendig ist.
|
||||
\subsection{Konfiguration}
|
||||
Damit der Pixelserver Apps kennt müssen sich in der \textit{config.py} eingetragen werden. In der Variable \textit{Apps} befindet sich eine Liste der Apps. Jede hat das folgende Format:
|
||||
\begin{lstlisting}[frame=single, basicstyle=\small]
|
||||
{"guiname": "<Name fuer Nutzer>",
|
||||
"name": "<Kennung fuer API>",
|
||||
"cmd": "<Pfad zur ausfuehrbaren Datei>"},
|
||||
\end{lstlisting}
|
||||
Üblicherweise sollten die Apps im Verzeichnis \textit{apps/} liegen.
|
||||
|
||||
\textbf{Beispiel:}
|
||||
\begin{lstlisting}[frame=single, basicstyle=\small]
|
||||
{"guiname": "Pong",
|
||||
"name": "pong",
|
||||
"cmd": "apps/pong.py"},
|
||||
\end{lstlisting}
|
||||
|
||||
\section{Parameter}
|
||||
An die ausgeführte Anwendung werden immer drei Parameter übergeben:
|
||||
\begin{itemize}
|
||||
\item \textbf{1} (Breite): Die Breite des Bildschirms in Pixeln. Im folgenden $N_x$
|
||||
\item \textbf{2} (Höhe): Die Höhe des Bildschirms in Pixeln. Im folgenden $N_y$
|
||||
\item \textbf{3} (Parameter): Ein von der App frei nutzbarer Parameter. Persistente Apps müssen für korrekte Funktionalität ignorieren.
|
||||
\end{itemize}
|
||||
\section{Bildausgabe}
|
||||
Ein Bild besteht aus $N_x\cdot N_y$ Pixeln. Jeder Pixel besteht aus den Farben \textit{Rot}, \textit{Grün} und \textit{Blau}. Jede Farbe wird als ein Byte dargestellt, wobei $0$ minimaler Intensität und $255$ maximaler Intensität entspricht.
|
||||
|
||||
Für ein Bild müssen die Pixel Zeilenweise mit der Pixelreinfolge Rot, Grün, Blau auf die Standardausgabe geschrieben werden. Dieses muss in einem einzigen Schreibbefehl ausgegeben werden.
|
||||
|
||||
Der Index $i_{Farbe}$ des Pixels $x$ in der Breite und $y$ in der Höhe ergibt sich wie folgt:
|
||||
\begin{align*}
|
||||
i_{rot} &= 3\cdot(x+N_x\cdot y)+0\\
|
||||
i_{gruen} &= 3\cdot(x+N_x\cdot y)+1\\
|
||||
i_{blau} &= 3\cdot(x+N_x\cdot y)+2
|
||||
\end{align*}
|
||||
Hierbei werden $x \in \{0, 1, \dots, N_x-1\}$, $y \in \{0, 1, \dots, N_y-1\}$ und $i_{Farbe} \in \{0, 1, \dots, N_x\cdot N_y-1\}$ von $0$ an gezählt.
|
||||
|
||||
Wenn eine App einige Sekunden (Standardeinstellung: 40 Sekunden) kein Bild ausgibt, wird sie vom Pixelserver als abgestürzt betrachtet und beendet.
|
||||
\section{setup-apps.sh}
|
||||
Um die Apps zu installieren/kompilieren sollte der User vor dem ersten Start des Pixelservers das Skript \textit{setup-apps.sh} aufrufen. Somit sollte der Entwickler einer App hier seine App eintragen, damit sie korrekt gebaut wird. Für einige Sprachen sind schon Schema in der \textit{setup-apps.sh} hierfür vorgesehen.
|
||||
|
||||
\subsection{Skriptsprachen}
|
||||
Für Skriptsprachen sollten die Skripte im Allgemeinen ausführbare gemacht werden und es sollte eine Zeile der Form:
|
||||
\begin{lstlisting}[frame=single, basicstyle=\small]
|
||||
chmod +x apps/newapp.py
|
||||
\end{lstlisting}
|
||||
hinzugefügt werden.
|
||||
\subsection{C/C++}
|
||||
Apps in C und C++ liegen in \textit{apps/c-src} und werden mit CMake kompiliert. Sie sollten zu der entsprechenden \textit{apps/c-src/CMakeLists.txt} hinzugefügt werden.
|
||||
|
||||
Es werden dann im Verzeichnis \textit{build/c} gebaut und sollten mit einer Zeile der Form
|
||||
\begin{lstlisting}[frame=single, basicstyle=\small]
|
||||
mv build/c/nywapp apps/
|
||||
\end{lstlisting}
|
||||
in der \textit{setup-apps.sh} an den richtigen Ort kopiert werden.
|
||||
\section{Python App Beispiel}
|
||||
Hier betrachten wir eine Beispielapp in Python die zufällige Pixel nacheinander Rot, Grün oder Blau macht. Die Geschwindigkeit des Setzens der Pixel soll hier über den Parameter (in Millisekunden) eingestellt werden.
|
||||
|
||||
Dazu wird in \textit{apps/example.py} folgende Datei angelegt
|
||||
\begin{lstlisting}[frame=single, basicstyle=\small]
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import random
|
||||
import time
|
||||
|
||||
# Groesse des Bildschirms bestimmen
|
||||
Nx = int(sys.argv[1])
|
||||
Ny = int(sys.argv[2])
|
||||
|
||||
# Bestimme den Parameter
|
||||
time_ms = 100
|
||||
try:
|
||||
time_ms = int(sys.argv[3])
|
||||
except:
|
||||
pass
|
||||
|
||||
# Puffer fuer Pixel erstellen und mit 0 initialisieren
|
||||
buffer = bytearray(b"\x00" * (3 * Nx * Ny))
|
||||
|
||||
curPixel = 0
|
||||
|
||||
while True:
|
||||
# Zufaellige Pixel waeheln
|
||||
# rot
|
||||
x_r = random.randint(0, Nx-1)
|
||||
y_r = random.randint(0, Ny-1)
|
||||
i_r = 3*(x_r+Nx*y_r)
|
||||
# gruen
|
||||
x_g = random.randint(0, Nx-1)
|
||||
y_g = random.randint(0, Ny-1)
|
||||
i_g = 3*(x_g+Nx*y_g)
|
||||
# blau
|
||||
x_b = random.randint(0, Nx-1)
|
||||
y_b = random.randint(0, Ny-1)
|
||||
i_b = 3*(x_b+Nx*y_b)
|
||||
|
||||
# Pixel in Puffer schreiben
|
||||
# rot
|
||||
buffer[i_r+0] = 0xff # Rotanteil
|
||||
buffer[i_r+1] = 0x00 # Gruenanteil
|
||||
buffer[i_r+2] = 0x00 # Blauanteil
|
||||
# gruen
|
||||
buffer[i_g+0] = 0x00 # Rotanteil
|
||||
buffer[i_g+1] = 0xff # Gruenanteil
|
||||
buffer[i_g+2] = 0x00 # Blauanteil
|
||||
# blau
|
||||
buffer[i_b+0] = 0x00 # Rotanteil
|
||||
buffer[i_b+1] = 0x00 # Gruenanteil
|
||||
buffer[i_b+2] = 0xff # Blauanteil
|
||||
|
||||
|
||||
|
||||
# Zeige den Puffer an
|
||||
os.write(1, buffer)
|
||||
# warte time_ms ms
|
||||
time.sleep(time_ms*0.001)
|
||||
\end{lstlisting}
|
||||
|
||||
In \textit{config.py} wird folgendes zu den \textit{Apps} hinzugefügt:
|
||||
\begin{lstlisting}[frame=single, basicstyle=\small]
|
||||
{"guiname": "Beispiel",
|
||||
"name": "example",
|
||||
"cmd": "apps/example.py"},
|
||||
\end{lstlisting}
|
||||
|
||||
Zuletzt wird zur \textit{setup-apps.sh}
|
||||
\begin{lstlisting}[frame=single, basicstyle=\small]
|
||||
chmod +x apps/example.py
|
||||
\end{lstlisting}
|
||||
hinzugefügt und die App ist einsatzbereit.
|
||||
\end{document}
|
@ -5,6 +5,7 @@
|
||||
chmod +x apps/pong.py
|
||||
chmod +x apps/swifthohenberg.py
|
||||
chmod +x apps/strobo.py
|
||||
chmod +x apps/example.py
|
||||
chmod +x apps/youtubedl.sh
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user