Hallo,
ich hätte Fragen. Ich gehe davon aus, dass der Code von @Sirius3 ein ungetesteter Zwischenstand ist, weil mir ist da ein paar Kleinigkeiten aufgefallen sind. Aber erst meine Frage, die Funktion `mode` gibt es zwei mal, einmal mit `@property` und ein mal mit `@mode.setter`. Ist das `setter` dazu da, damit man nicht einen weiteren Namen einführen muss und Python selbstständig merkt, dass wenn `mode = ...` geschrieben wird, dann wird die Funktion mit `setter` benutzt und ansonsten die andere? Ich "weis" bzw. ich lese es öfters, das andere Sprachen so was wie `setter` und `getter` brauchen, aber hier könnte ich die Funktion einfach `set_mode` nennen und den Wert "normal" als Argument übergeben. Gibt es einen weiteren Vorteil?
Was mir aufgefallen ist, `number_of_blinks` könnte eine Konstante sein. `i` wird in der for-Schleife gar nicht genutzt. Der Dekorator `mode.setter` über der Funktion `value` sollte `value.setter` heißen. Das Wörterbuch könnte auch eine Konstante sein und ich würde nicht alles 'value' nennen.
In `mode` würde ich auch wieder eine Konstante für das Wörterbuch nehmen.
In `_write` ist man bei Wahl der Klammer für den 'f'-String verrutscht und in `_read` auch. An der Stelle würde ich dann auch `num` in `pin_number` umbenennen. Und, da hat mir aber PyCharm geholfen, 'type` ist kein guter Namen, weil so schon eine Python-Funktion heißt.
In `reset` fehlt ein Unterstrich beim Aufruf von `_write` und ein Argument.
Ich habe das noch nie gemacht, aber ich habe die Konstanten jetzt in der Klasse definiert, weil die Klasse die zwingend braucht. Ist das richtig?
Ungetestet:
Code: Alles auswählen
from pathlib import Path
from time import sleep
NUMBER_OF_BLINK = 10
class GpioPin:
GPIO_PATH = Path('/sys/class/gpio')
COMMAND_TO_GPIO_STATE = {
"0": "0",
"LOW": "0",
0: "0",
"1": "1",
"HIGH": "1",
1: "1",
}
COMMAND_TO_GPIO_MODE = {
"out": "out",
"write": "out",
"in": "in",
"read": "in",
}
def __init__(self, pin_number, mode):
if not 0 <= pin_number <= 40:
raise ValueError('Invalid Pin Number')
self.pin_number = pin_number
(self.GPIO_PATH / 'export').write_text(str(self.pin_number))
sleep(0.05)
self.mode = mode
def _read(self, file_type):
return (self.GPIO_PATH / f"gpio{self.pin_number})" / file_type).read_text()
def _write(self, file_type, value):
(self.GPIO_PATH / f"gpio{self.pin_number})" / file_type).write_text(value)
def reset(self):
self._write('value', 0)
self.mode = 'in'
@property
def mode(self):
return self._read('direction')
@mode.setter
def mode(self, command):
try:
mode = self.COMMAND_TO_GPIO_MODE[command.lower()]
except KeyError:
raise ValueError('Invalid Mode')
self._write('direction', mode)
@property
def value(self):
return int(self._read('value'))
@value.setter
def value(self, command):
try:
gpio_state = self.COMMAND_TO_GPIO_STATE[command]
except KeyError:
raise ValueError('Invalid Value')
self._write('value', gpio_state)
def cleanup(self):
self.reset()
(self.GPIO_PATH / 'unexport').write_text(str(self.pin_number))
def main():
pin = GpioPin(13, 'out')
try:
for _ in range(NUMBER_OF_BLINK):
pin.value = 1
sleep(0.5)
pin.value = 0
sleep(0.5)
finally:
pin.cleanup()
if __name__ == '__main__':
main()
Grüße
Dennis