In meinen Augen ist das genau der Fall, den ich weiter oben schon skizziert habe: was interessiert es denn deinen Server, wie genau der Switch anzusprechene ist? Das hat weder da, noch in einer Datenbank etwas verloren. Eine Datenbank dient dazu, Dinge, die sich (relativ oft) aendern koennen zu speichern.Da fällt mir keine bessere Lösung für ein, da jeder Schalter-Typ (Relais, GPIO, Funk, USB-Relais) andere Argumente benötigt musste ich einen Kompromis finden.
Z.Bsp. braucht ich bei GPIO-Pins nur arg_A zum abspeichern des Pins, bei Tinkerforge Relais brauche ich arg_a zum speichern der Modul UID und arg_b um das Relais anzugeben (1-4) und zu guter letzt brauche ich beim Tinkerforge RemoteSwitch alle 4 Argumenten, in arg_a steht dann die UID, in arg_b das Funk-Protokoll und in arg_c + arg_d der eigentliche Funk-Code.
Vermeiden könnte ich das meiner Meinung nach nur, wenn ich für jeden Typ von Schalter eine extra Datenbank anlegen würde.
Oder stehe ich komplett auf dem Schlauch ?
Deine Hardware-Konfiguration aendert sich aber nicht (jedenfalls nicht oft). Stattdessen baust du einen neuen Schalter irgendwozu ein, und dann brauchst du den genau einmal anzumelden. Ich wuerde das mit einer Konfigurationsdatei machen.
Dann meldet sich eben der Schalter beim Server an - und kann geschaltet werden. Das ist ja immer dasselbe: der Server schickt dem Schalter "geh an", "geh aus", und der Schalter macht das, und meldet zurueck "bin an", "bin aus", oder "bin kaputt".
Ein bisschen Pseudocode fuer einen Schalter-Client:
Code: Alles auswählen
from smartHome import SwitchBase
class GPIOSwitch(SwitchBase):
CONFIG = SwitchBase.mergeConfigs(
SwitchBase.CONFIG,
{
"GPIO_NO" : int, # erklaert den Wert GPIO_NO als int, der in der Konfig stehen muss
}
)
def __init__(self, config):
super(...).__init__(config)
self._gpio = config["GPIO_NO"]
self._setup_gpio(self._gpio)
def set_switch(self, on):
self._set_gpio(on)
# aus Basisklasse, GPIO switch kann
# nie einen Fehler haben -also einfach
# den soll-Zustand schicken
self.send_switch_state(on)
Eine Konfiguration sieht dann so aus:
Code: Alles auswählen
SMART_HOME_URL=http://localhost:1234/
NAME=Terrarium Licht
GPIO_NO=10
Wenn du zb einen Pumpenschalter haben willst, der mit Ueberlastungsschutz arbeitet, dann saehe das ggf. so aus:
Code: Alles auswählen
from smartHome import SwitchBase
class PumpSwitch(GPIOSwitch]):
CONFIG = SwitchBase.mergeConfigs(
GPIOSwitch.CONFIG,
{
"OVERHEATED_GPIO" : int, # erklaert den Wert OVERHEATED_GPIO als int, der in der Konfig stehen muss
}
)
def __init__(self, config):
super(PumpSwitch, self).__init__(config)
self._overheat_gpio = config["GPIO_NO"]
self._setup_overheat_gpio(self._overheat_gpio)
self._overheated = False
def set_switch(self, on):
if not self._overheated:
super(PumpSwitch, self).set_switch(on)
else:
self.send_switch_state(False)
Was da natuerlich noch fehlt ist, dass der PumpSwitch den GPIO ueberwacht, und dann self._overheated setzt, und natuerlich auch sofort meldet, dass er "aus" ist.
Ich glaube ein grosses "Problem" ist, dass du mit einer nicht-client-Server Anwendung angefangen hast, und mit einem System zum zurechtkonfigurieren von GPIO-basierten Schaltaufgaben, die du in eine DB gespeichert hast. Dann erweitert um mehr - und nun soll es client-server werden, aber der ganze Code ist durchzogen mit den Annahmen ueber all die Schalter, die du unterstuetz.
Aber das ist IMHO nicht sinnvoll, wenn du client Server hast. Mit diesem Ansatz hier kannst du sogar ggf. einen Arudino mit Ethernet-Shield anklemmen, weil der nur JSON-Pakete bekommt und schickt. Versuch dem mal, MySQL beizubringen...