Hi,
hab mir ein Bein gestellt und jetzt festgestellt, dass ich nicht weiss wie die controls_fhem.txt wirklich generiert wird.
Wobei, mittlerweile weiss ich es doch ein bisschen besser als ich vorher angenommen habe.
Ich habe mir erlaubt einen Konfigurationshash (ca 2000 Zeilen) in eine separate Datei auszulagern.
Den habe ich in das lib Verzeichnis gelegt.
FHEM/lib/signalduino_protocols.hash
Nun ist es aber so, dass diese Datei nicht in der controls_fhem.txt hinterlegt wird, da scheinbar nur definierte Dateitypen berücksichtigt werden.
Das Script, welche die controls_fhem.txt erstellt habe ich im SVN nicht ausfindig machen können.
Wäre es möglich das Script, welches die controls_fhem.txt erzeugt anzupassen?
Ich würde auch einen Patch erstellen, wenn ich wüsste wo ich das Script finde.
Grüße Sidey
./contrib/fhemupdate.pl
Wenn Du Deinen hash nach ./FHEM/firmware/ verlegen würdest, muss man nix am update ändern, das Verzeichnis wird komplett berücksichtigt:
"FHEM/firmware/.*"
@Betateilchen
Danke für beide hinweise.
Umlegen würde dazu führen, dass ich das Modul anpassen muss, was natürlich ebenso machbar wäre wie den Patch einzuspielen.
In Firmware würde ich so etwas halt nun eher nicht ablegen, weil es keine Firmware ist :)
Grüße Sidey
schon klar, es war nur ein Vorschlag für eine schnelle Lösung, die schon mit dem Update morgen früh greifen würde ;)
Habe ich auch so verstanden.
Ich war mir auch generell unsicher, ob ich die Datei wirklich dort hinlegen soll, aber naja, es schien irgendwie passend.
Ich könnte die Datei auch dynamisch aus dem Internet nachladen, das war mit aber dann doch erst mal zu aufwändig.
warum muß eigentlich die Endung bei einem Perl hash unbedingt .hash sein, wäre da .pm nicht passender?
Gruß Ralf
Ich habe auf die Schnelle keine Spezifikation gefunden, wann etwas ein Perl Modul ist und wann nicht, aber es erscheint mir offensichtlich, dass ein Hash kein PerlModul ist, welches via use oder require geladen wird.
Grüße Sidey
ich hab das gefunden:
https://stackoverflow.com/questions/12261525/can-i-use-hash-values-from-another-file
Ich wuerde die Datei so modifizieren, dass die Daten einer Variable zugewiesen werden (analog zu HMCCUConf.pm) und sie in FHEM/lib/signalduino_protocols.pm umbenennen. Dann kann man die Datei mit use laden, die Leute stellen keine bloede Fragen, und man muss im Framework keine Ausnahmen einbauen.
Zitat von: rudolfkoenig am 22 Februar 2019, 09:48:33
Ich wuerde die Datei so modifizieren, dass die Daten einer Variable zugewiesen werden (analog zu HMCCUConf.pm) und sie in FHEM/lib/signalduino_protocols.pm umbenennen. Dann kann man die Datei mit use laden, die Leute stellen keine bloede Fragen, und man muss im Framework keine Ausnahmen einbauen.
Hi Rudi,
ich habe die Daten einer Variable zugewiesen. Das funktioniert prinzipiell auch bereits seit Monaten. Nur leider wird die Datei nicht über den Update Befehl geladen.
Dein Vorschlag ist jetzt, dass ich mich von einer bewährten Methode des ladens von Daten aus einer Datei in einen Hash verabschieden soll.
sub SIGNALduino_LoadProtocolHash($)
{
if (! -e $_[0]) {
return %{ {"error" => "File does not exsits"}};
}
my $protocol_data = do {
open my $fh, '<', $_[0] ;
local $/; # Undefine $/ for this scope...
<$fh>; # so <> slurps up the entire file
};
my %evalret= eval $protocol_data ;
if (!%evalret) {
return %{ {"error" => $@}};
}
return %evalret;
}
Wie ich das nun mit use oder require hinbekomme eine Datei mit variablen Namen laden zu können müsste ich noch prüfen.
So wie ich HMCCUConf verstanden habe, wird dort ein Package definiert in dem wiederum die Variablen definiert sind. Um diese dann im Modul verwenden zu können, wird eine Variable im Modul als Referenz auf die Variable im Package angelegt.
Was die Ausnahmen des Frameworks angeht, verstehe ich die Regel aktuell leider nicht :-( .
Es gibt Verzeichnisse, in denen ist der Beginn des Dateinamens entscheidend. Z.B.:
"FHEM/FhemUtils/update-.*",
Es gibt Verzeichnisse, in denen ist alles erlaubt. Z.B.:
"FHEM/firmware/.*",
"FHEM/lib/SWAP/panStamp/.*",
"FHEM/lib/SWAP/justme/.*",
"www/pgm2/.*",
"www/codemirror/.*",
Und dann gibt es noch Verzeichnisse in denen sind nur manche Dateiendungen erlaubt. Z.B:
"FHEM/lib/.*.pm",
"FHEM/lib/.*.xml",
"FHEM/lib/.*.csv",
"www/images/fhemSVG/.*.svg",
Was ist denn jetzt hier genau die Regel des Frameworks von der ich abweiche?
Wenn ich die Daten jetzt in einem JSON File speichern würde. Wäre es dann okay?
.gz Dateien liegen heute auch bereits im FHEM/lib/ Verzeichnis, aktualisieren lassen die sich aber wohl auch nicht.
Grüße Sidey
ZitatWas ist denn jetzt hier genau die Regel des Frameworks von der ich abweiche?
Du willst eine Datei mit dem Namen .hash anlegen, und damit waerst du die Erste.
Deine Methode des Ladens ist auch unkonventionell.
Es reicht, wenn du deine Datei "FHEM/lib/signalduino_protocols.pm" nennst, vor dem ersten Klammer
use vars qw(%signalduino_protocols);
%signalduino_protocols =
schreibst, und die Datei mit
require "lib/signalduino_protocols.pm";
reinliest. Danach hast du Zugriff auf %signalduino_protocols.
Zitat.gz Dateien liegen heute auch bereits im FHEM/lib/ Verzeichnis, aktualisieren lassen die sich aber wohl auch nicht.
Hast Du dafuer ein Beleg?
Ich habe mir diesen Weg zwar nicht selbst ausgedacht, aber es mag sein, dass es unkonventionell ist.
Ich bau mir erst mal einen kleinen Workaround. Das Laden via require muss ich mir genauer ansehen, ob das funktioniert.
Es ist halt nicht in allen Fällen die gleiche Datei die geladen werden soll, aber das ist mein Problem. Dazu muss ich mir erst mal die Karten legen.
Grüße Sidey
ZitatEs reicht, wenn du deine Datei "FHEM/lib/signalduino_protocols.pm" nennst, vor dem ersten Klammer
use vars qw(%signalduino_protocols);
%signalduino_protocols =
Ich habe es damit mal versucht
In die signalduino_protocols.pm habe ich folgendes eingetragen:
package signalduino_protocols;
use vars qw(%ProtocolListSIGNALduino);
%ProtocolListSIGNALduino = (
In die 00_SIGNALduino.pm habe ich folgendes eingetragen:
require "lib/signalduino_protocols.pm";
my %ProtocolListSIGNALduino = %signalduino_protocols::ProtocolListSIGNALduino;
Bis auf ein paar Ausnahmen funktioniert es damit.
"18" => ## Oregon Scientific v1
{
name => 'Oregon Scientific v1',
comment => 'temperature / humidity or other sensors',
id => '18',
...
method => \&SIGNALduino_OSV1 # Call to process this message
},
"35" => ## Homeeasy
{
name => 'HE800',
comment => 'Homeeasy',
id => '35',
...
postDemodulation => \&SIGNALduino_HE800,
},
Damit
my $method = $ProtocolListSIGNALduino{$id}{method};
if (!exists &$method)
{
Log3 $name, 5, "$name: Error: Unknown function=$method. Please define it in file $0";
} else {
my ($rcode,$res) = $method->($name,$bitData,$id,$mcbitnum);
stürzt fhem mit folgender Fehlermeldung ab:
Undefined subroutine &signalduino_protocols::SIGNALduino_OSV1 called at ./FHEM/00_SIGNALduino.pm ...
und damit funktioniert es auch nicht:
($rcode,@retvalue) = SIGNALduino_callsub('postDemodulation',$ProtocolListSIGNALduino{$id}{postDemodulation},$name,@bit_msg);
sub SIGNALduino_callsub
{
my $funcname =shift;
my $method = shift;
my $name = shift;
my @args = @_;
if ( defined $method && defined &$method )
{
#my $subname = @{[eval {&$method}, $@ =~ /.*/]};
Log3 $name, 5, "$name: applying $funcname, value before: @args"; # method $subname";
my ($rcode, @returnvalues) = $method->($name, @args) ;
Gruß Ralf
Gibt es einen Grund, warum du in dieser Version auf package ("package signalduino_protocols;") bestehst?
In der .hash Version hast du es nicht verwendet, wenn du es haben willst, dann musst du es konsequent durchziehen.
ZitatGibt es einen Grund, warum du in dieser Version auf package ("package signalduino_protocols;") bestehst?
Ich habe das package reingemacht, da es in der HMCCUConf.pm auch drin ist.
Ohne das "package signalduino_protocols;" und in der 00_SIGNALduino.pm
my %ProtocolListSIGNALduino = %signalduino_protocols::ProtocolListSIGNALduino;
bekomme ich z.B. bei
if (exists($ProtocolListSIGNALduino{$protocol}{format}) && $ProtocolListSIGNALduino{$protocol}{format} eq 'manchester')
diese Fehlermeldung
Global symbol "%ProtocolListSIGNALduino" requires explicit package name at ./FHEM/00_SIGNALduino.pm
Gruß Ralf
Das SIGNALduino Modul liegt aktuell im Package main.
Jededes Modul muss meines Wissens nach in einem Package liegen.
Egal wo was liegt sind die Variablen aber auch erst mal lokal. Da helfen dann so Bezeichnet wie our.
Das meinte ich übrigens mit Karten legen
Das ist aus meiner Sicht nicht ganz so einfach die Sachen in ein Packages zu verpacken, wenn es Referenzen in beide Richtungen gibt.
von einem package hatte Rudi nie gesprochen. Er wollte einfach nur die Variable global verfügbar gemacht haben:
Zitat von: rudolfkoenig am 22 Februar 2019, 21:50:50
Es reicht, wenn du deine Datei "FHEM/lib/signalduino_protocols.pm" nennst, vor dem ersten Klammer
use vars qw(%signalduino_protocols);
%signalduino_protocols =
schreibst,
Ein bewährtes Verfahren, das auch an anderen Stellen in FHEM bereits seit langem verwendet wird.
Wäre es eine Möglichkeit in der ProtocolListSIGNALduino in method anstatt einer Referenz der Subroutine
method => \&SIGNALduino_OSV1,
den Namen der Subroutine als String zu speichern?
method => "SIGNALduino_OSV1",
Wie müsste dann dies aussehen?
my $method = $ProtocolListSIGNALduino{$id}{method};
my ($rcode,$res) = $method->($name,$bitData,$id,$mcbitnum);
habe was gefunden
https://stackoverflow.com/questions/30236740/generating-a-subroutine-reference-from-a-string
damit funktioniert es
my $method = \&{ $ProtocolListSIGNALduino{$id}{method} };
Zitatvon einem package hatte Rudi nie gesprochen. Er wollte einfach nur die Variable global verfügbar gemacht haben:
Das Problem dabei ist, daß ich bis jetzt noch kein Beispiel gefunden habe wo das auch ohne package funktioniert.
Bei HMCCUConf.pm und UConv.pm werden auch package verwendet.
Gruß Ralf
Was spricht denn gegen ein Package?
Das Package selbst verursacht doch ohnehin keine Probleme.
Das woran ich hänge ist, zur Laufzeit ein anderes Modul mit gleichem Namen zu laden und die vorhandenen Daten sauber zu ersetzen.
Es funktioniert inzwischen alles soweit, es ist aber noch ein kleine Frage aufgetaucht.
Ich habe die Protokollhashliste damit in die 00_SIGNALduino.pm eingebunden:
require "lib/signalduino_protocols.pm";
my %ProtocolListSIGNALduino = %signalduino_protocols::ProtocolListSIGNALduino;
Nun wollte ich nach dem editieren der signalduino_protocols.pm diese mit reload neuladen:
Ich habe es mit
reload lib/signalduino_protocols.pm
versucht, bekomme dabei aber die folgende Fehlermeldung:
Can't read ./FHEM/libsignalduino_protocols.pm: No such file or directory
Gibt es eine Möglichkeit ein "/" in die commandline einzugeben?
Gruß Ralf
Hi Ralf,
Das neuladen des Perl Modules, wenn es denn wie bei einem Fhem Modul funktioniert, würde dann aber noch immer nicht die Kopie der Variable erneuern.
Was für ein Problem gibt es denn mit der bereits implementierten Variante über
{SIGNALduino_LoadProtocolHash("$attr{global}{modpath}/FHEM/lib/signalduino_protocols.pm");}
Wie ich schon im github geschrieben habe, erscheint mir das mit dem Laden des Hashes über die Sub SIGNALduino_LoadProtocolHash recht aufwändig und umständlich. Wenn jemand mehrere signalduino Devices hat, wird bei jedem signalduino Device die signalduino_protocols.pm neu geladen und falls zukünftig weitere hashes in der signalduino_protocols.pm dazukommen, wird beim Laden jedes hashes auch signalduino_protocols.pm neu geladen.
sub SIGNALduino_LoadProtocolHash($)
{
if (! -e $_[0]) {
return %{ {"error" => "File does not exsits"}};
}
use Symbol 'delete_package';
delete_package 'SD_Protocols';
delete($INC{$_[0]});
if( ! eval { require "$_[0]"; 1 } ) {
return %{ {"error" => $@}};
}
return %{SD_Protocols->getProtocolList};
}
Zitat von: Ralf9 am 03 März 2019, 19:44:23
Wenn jemand mehrere signalduino Devices hat, wird bei jedem signalduino Device die signalduino_protocols.pm neu geladen und falls zukünftig weitere hashes in der signalduino_protocols.pm dazukommen, wird beim Laden jedes hashes auch signalduino_protocols.pm neu geladen.
Wieso meinst Du dass jede Definition das Laden auslöst? Das Laden wir genau 1x für das gesamte Modul ausgelöst.
Diese sub existiert, damit zur Laufzeit und nicht zur compile Zeit eine Perlmodul Datei geladen werden die das Package SD_Protocols und darin eine Funktion getProtocolList bereitstellt.
Was das Laden anderer Variablen angeht, kann ich dir nicht folgen. Die sind nach dem Laden des angegebenen Perlmodules über ihren vollqualifizierten Namen erreichbar und könnten auch über getter subs bereitgestellt werden.
Grüße Sidey