User-Daten schreiben und use Anweisungen

Begonnen von daniel2311, 19 April 2017, 21:42:48

Vorheriges Thema - Nächstes Thema

daniel2311

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/ 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!

rudolfkoenig

Zu 2.: mit eval { require modulname }, und $@ auswerten. Siehe auch HttpUtils.pm oder 01_FHEMWEB.pm

daniel2311

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!

betateilchen

Ich würde sowas nie in xxx_Define() prüfen, sondern in xxx_Initialize().
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

daniel2311

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.

daniel2311

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 :/

rudolfkoenig

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