Hallo zusammen,
ich bin mittlerweile recht weit mit der Implementierung von einem Gerät names Broadlink RM Pro https://www.amazon.de/Broadlink-Universal-Intelligent-Controller-Automation-RF-Fernbedienung-kompatibel/dp/B01HO27U5E/ (https://www.amazon.de/Broadlink-Universal-Intelligent-Controller-Automation-RF-Fernbedienung-kompatibel/dp/B01HO27U5E/) Funktioniert schon recht gut und ich würde es gerne auch einigen in Forum zum Testen bereitstellen und ggf. ins SVN stellen.
Allerdings habe ich zwei Fragen:
1. Ich habe mir das LightScene Modul angeschaut und mir dort die Load- und Save-Sub kopiert, um aufgenomme Befehle abzuspeichern. Ist das so ein Ordnung oder macht man da eher etwas anderes?
2. Beim Kopieren der zwei Subs vom LightScene Modul ist mir aufgefallen, dass hier einige Bibliotheken später geladen werden, beispielsweise so:
eval "use JSON";
$LightScene_hasJSON = 0 if($@);
In meinem Modul nutze ich Crypt::CBC und Crypt::OpenSSL::AES.
Diese Module sind standardmäßig zumindest bei meiner Installation nicht dabei. Wie gehe ich korrekt damit um, dass ein Benutzer dieses Bibliotheken nicht hat und noch installieren muss?
Vielen Dank!
Zu 2.: mit eval { require modulname }, und $@ auswerten. Siehe auch HttpUtils.pm oder 01_FHEMWEB.pm
Hab's verstanden, denke ich.
Habe dann im Define, weil ich die Module zwingend benötige, folgendes gemacht:
my $broadlink_hasAES = 1;
eval "use Crypt::OpenSSL::AES";
$broadlink_hasAES = 0 if($@);
return "install Crypt::OpenSSL::AES to use Broadlink" if( !$broadlink_hasAES);
Vielen Dank!
Ich würde sowas nie in xxx_Define() prüfen, sondern in xxx_Initialize().
Okay, werde es mal ausprobieren.
Aber direkt ne Frage - warum würdest du das nicht tun? Ich dachte nämlich, im Define macht es Sinn, weil jemand der das Modul nicht nutzt, so keine Meldungen bekommt, falls er das Modul gar nicht nutzen möchte, sondern erst, wenn er auch eins davon definiert.
Okay - das ging mal voll in die Hose xD
Ich brauche wirklich mehr Infos.
Folgendes im Define gibt eine Meldung, selbst, wenn ein Gerät installiert ist:
return "install Crypt::CBC to use Broadlink" if( !$broadlink_hasCBC);
und kommt bei angelegtem Device so auf die Startseite:
Messages collected while initializing FHEM:
configfile: install Crypt::CBC to use Broadlink
Wenn ich das ganze im Initialize mache, passiert quasi nichts und sobald ich das Device verwende stürzt FHEM ab :/
Das Rueckgabewert von XXX_Initialize wird nicht geprueft, die Funktion wird komplett per eval ausgefuehrt.
Je nachdem was man will, sind unterschiedliche Loesungen besser:
- Wenn man ohne Crypt::CBC nichts sinnvolles machen kann, dann ist es besser, require ohne eval in Initialize einzubauen: Der Benutzer bekommt zwar eine unbehandelte Fehlermeldung, kann aber nach Installieren von Crypt::CBC ohne FHEM-Neustart durch ein erneutes define weiterarbeiten.
- Wenn man ohne dieses Modul nur auf bestimmte Funktionen verzichten muss, dann fuehrt man require in eval aus, man warnt notfalls den Benutzer und man setzt entsprechend eine Variable. require kann in diesem Fall (mit eval) in Initialize oder Define stattfinden, oder gar direkt vor dem Verwendes des Features, was Crypt::CBC benoetigt. Natuerlich darf in diesem Fall jeder Zugriff auf Crypt::CBC nur nach Pruefung der Variable stattfinden. Falls der Benutzer Crypt::CBC nachinstalliert hat, dann ist entweder ein FHEM-Neustart notwendig, oder das Modul muss durch ein spezielles set/attr/etc das require erneut durchfuehren