3 """Ein Modul, das die Eingabe-Ausgabe-Module für den Raspberry Pi
6 Der Server kann mit folgenden Zeilen einfach erstellt werden:
8 >>> from eapi.net import EAModulServer
9 >>> easerver = EAModulServer("localhost", 9999)
11 Anschließend wird er mit einem Aufruf gestartet.
13 easerver.serve_forever()
15 Ebenso kann der Server über die Kommandozeile mit dem folgenden Befehl
18 $ python3 -m eapi.net startserver
20 Nun wartet der Server auf dem Port 9999 auf UDP-Pakete. Ein an den Server
21 gesendeter Request besteht aus genau einem Byte - weitere gesendete Bytes
22 werden ignoriert. Die letzen sechs Bit (0 oder 1) des gesendeten Bytes, werden
23 als Werte für die rote, gelbe und grüne LED interpretiert:
32 Für jede Farbe werden zwei Bit verwendet. Das erste Bit besagt, ob die
33 entsprechende LED geschaltet werden soll (1) oder nicht (0). Wenn die LED
34 geschalet werden soll, beschreibt das zweite Bit den Zustand, in den die LED
35 geschaltet werden soll: an (1) oder aus (0). Wenn die LED nicht geschaltet
36 werden soll, ist der Wert beliebig.
38 Die Bitsequenz ?? 0? 11 10 (? bedeutet 'beliebig') belässt die rote LED in
39 ihrem bisherigen Zustand, schaltet die gelbe LED an und die grüne LED aus.
41 Mit Netcat und echo kann ein Byte einfach an einen Testserver wie folgt
44 $ echo -en '\\xE' | nc -4u localhost 9999
46 Der Hexwert E entspricht dem Binärwert 00001110. Mit der Option -e wird eine
47 Escapesequenz verschickt, die Option -n besagt, dass kein Zeilenumbruch
48 gesendet werden soll - also nur die angegebenen Bytes. Die Option -4 von nc
49 sendet ein IPv4-Paket, das als UDP-Paket (-u) verschickt werden soll.
51 Das Modul enthält einen einfachen Konsolenclient, der über die Konsole
52 gestartet werden kann:
54 $ python3 -m eapi.net startclient
56 Mit dem Python-Modul socket kann ein Packet in Python selbst erstellt und an
57 den Server gesendet werden.
60 >>> client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
61 >>> daten = bytes([0xe])
63 Die zu sendenen Daten bestehen aus nur einem Byte.
65 >>> client.sendto(daten, ("localhost", 9999))
79 """Ein Handler für UDP requests an den EAModulServer."""
86 """Der UDP-Handler bearbeitet UDP-Requests gemäß der Modulbeschreibung
88 print(
"request erhalten!", self.request)
91 if EAModulUDPHandler.eamodul
is None:
92 EAModulUDPHandler.eamodul =
EAModul()
96 data = self.request[0]
109 EAModulUDPHandler.eamodul.schalte_led(EAModul.LED_ROT,
112 EAModulUDPHandler.eamodul.schalte_led(EAModul.LED_GELB,
115 EAModulUDPHandler.eamodul.schalte_led(EAModul.LED_GRUEN,
120 """Ein UDPServer für ein EA-Modul.
122 Er lässt sich unter Angabe von hostname und Portnummer erzeugen.
124 >>> easerver = EAModulServer("localhost", 9999)
126 Anschließend kann er mit dem folgenden Aufruf gestartet werden
128 easerver.serve_forever()
130 Ein an den Server gesendeter Request wird vom EAModulUDPHandler
135 """Starte einen Server auf dem angegebnen hostname, oder IP-Adresse -
136 lokale Server können hier auch 'localhost' als Name verwenden.
138 Über den Parameter eamodul kann ein EAModul übergeben werden. Wird
139 kein Modul übergeben, wird ein Standardmodul selbst erstellt.
142 super().
__init__((host, port), EAModulUDPHandler)
145 EAModulUDPHandler.eamodul = eamodul
149 """Client, um auf den EAModulServer zuzugreifen.
151 Der Client kann mit der Angabe eines Hostnamens oder einer IP-Adresse
154 >>> from eapi.net import EAModulClient
155 >>> client = EAModulClient('localhost', 9999)
157 Nun kann er mit dem Server kommunizieren und die dortigen LEDs ansteuern.
159 >>> client.sende(rot=1, gelb=0, gruen=1)
160 >>> client.sende(rot=0, gelb=0, gruen=1)
162 Die Methoden lassen sich auch kürzer aufrufen.
164 >>> client.sende(1, 0, 1)
165 >>> client.sende(0, 0, 1)
167 Wenn ein Wert ungleich 0 oder 1 gesendet wird, so wird er ignoriert und die
168 LED behält ihren Wert bei.
170 >>> client.sende(1, 9, 1)
172 schaltet die rote und grüne LED ein und belässt die gelbe LED in ihrem
177 """Starte den Client für einen laufenden Server.
179 Der angegebene servername ist eine IP-Adresse oder ein Domainname -
180 für ein lokal laufenden Server kann auch localhost verwendet
181 werden. Mit serverport wird die Portnummer angegeben, über die der
182 Server ansprechbar ist.
186 self.
client = socket.socket(socket.AF_INET,
190 """Sende an den Server die Information, welche LEDs an- bzw.
191 ausgeschaltet werden sollen.
193 Werte von 0 oder 1 für rot, gelb und grün schalten die LED aus bzw. an.
194 Andere Werte werden ignoriert und belassen die LED in ihrem bisherigen
204 if gruen == 0
or gruen == 1:
208 if gelb == 0
or gelb == 1:
212 if rot == 0
or rot == 1:
221 """Hauptprogramm, über das Client und Server gestartet werden können, wenn
222 das Modul ausgeführt wird.
226 if len(sys.argv) >= 2:
227 hostname = input(
"Hostname (Enter für localhost):")
229 hostname =
'localhost'
230 port = input(
"Port (Enter für 9999):")
234 if sys.argv[1] ==
"startserver":
235 print(
"Starte Server auf", hostname,
"auf Port", port)
237 easerver.serve_forever()
239 elif sys.argv[1] ==
"startclient":
240 print(
"Starte Client")
244 Welche LEDs sollen angeschaltet werden? Gib drei Werte (0 oder 1)
245 ein (erst rot, dann gelb, dann grün)
246 Beispiel: 010 schaltet gelb an und rot und grün aus.
248 Wenn Werte ungleich 0 der 1 verwendet werden, so bleibt die LED in
249 ihrem bisherigen Zustand: 050 schaltet rot und grün aus und belässt
250 gelb im bisherigen Zustand.
252 'q' beendet das Programm""")
260 rot = int(eingabe[0])
261 gelb = int(eingabe[1])
262 gruen = int(eingabe[2])
263 client.sende(rot, gelb, gruen)
266 print(
"Eingabe fehlerhaft. Erwarte genau drei Zahlen (0 oder 1).")
267 print(
"Bitte wiederholen!")
270 print(
"Befehl angeben: startserver oder startclient")
275 if __name__ ==
"__main__":