Globale Perl Variablen und Funktionen?

Begonnen von klaymen, 30 Dezember 2016, 22:34:36

Vorheriges Thema - Nächstes Thema

klaymen

Hallo zusammen,

Ich bin dran, einige etwas kompliziertere (für meine Verhältnisse) Notifies als Perl Funktionen zu schreiben. Dabei bin ich auf 2 Probleme gestossen: wie speichert man am Besten eine globale Perl Struktur (nicht nur eine einfache Variable), und wie kann man gemeinsame Teile in den Notifies in Perl Funktionen auslagern?

Zum Ersten habe ich zwar eine Lösung gefunden, sie scheint mir aber etwas umständlich - geht das einfacher? Ich möchte z.B. folgende Struktur


$temps = [["WZ_Thermostat_Climate", 15.0, 17.0, 21.0],
          ["EZ_Thermostat_Climate", 15.0, 17.0, 21.0],
          ...
          ["GA_Thermostat_Climate", 15.0, 17.0, 19.5]];


in mehreren Funktionen nutzen (die Elemente sind Namen von Thermostaten und zu setzende Temperaturen).

Ich habe dazu ein Dummy Objekt "_Temperaturen" mit dem Inhalt rechts der Zuweisung erstellt ('[[...]]'), und greife dann im Notify wie folgt darauf zu:

WG_Heizung:away {
  foreach my $t (@{eval(Value("_Temperaturen"))})
  {
    my $name = $t->[0];
    if (ReadingsVal($name,"desired-temp",99) != $t->[1])
      {fhem("set $name desired-temp $t->[1]");}
    if (ReadingsVal($name,"controlMode","") ne "manual")
      {fhem("set $name controlMode manual");}
  }
}


Etwas Anderes als dieses eval kam mir nicht in den Sinn (wenn ich nicht die gesamte Struktur in die Funktion kopieren will). Geht das auch einfacher?

Zum Zweiten - wie ihr euch vorstellen könnte, habe ich noch 2 weiter Notifies, die sich vom Ersten nur durch den Index der zu setzenden Temperatur unterscheidet ($t->[2] statt $t->[1] etc). Da wäre es eleganter, wenn man eine allgemeine Perl Funktion definieren könnte, die dann von den drei Notifies aus augerufen werden können. Wie würde man dazu vorgehen? Eine Variante wäre wohl ein weiteres Dummy Notify, welches man mit trigger aus den eigentlichen Notifies aufrufen würde, falls man darin die Parameter auswerten kann, aber auch das scheint mir kompliziert. Geht das eventuell direkter?

Danke und Grüsse (und ein gutes Neues Jahr),

Andreas

Markus Bloch

Hallo Andreas,

zu deinen Fragen:

Zitat von: klaymen am 30 Dezember 2016, 22:34:36
wie speichert man am Besten eine globale Perl Struktur (nicht nur eine einfache Variable)

Dafür ist der allgemeine Hash %data gedacht. Hier kann der User eigene Daten ablegen, welche nicht definitions-bezogen sind.

Bsp:


$data{temps} = [["WZ_Thermostat_Climate", 15.0, 17.0, 21.0],
          ["EZ_Thermostat_Climate", 15.0, 17.0, 21.0],
          ...
          ["GA_Thermostat_Climate", 15.0, 17.0, 19.5]];


Allerdings sollte man aufpassen, dass man keine bestehenden Indizes, die von Modulen bereits benutzt werden zu überschreiben. Am einfachsten mal in den Data-Hash reinschauen durch ausführen des FHEM-Befehls:

{use Data::Dumper;;Dumper(\%data)}

gibt bei mir:

$VAR1 = {
          'min1' => 0,
          'sum3' => '5239.4',
          'max1' => 67,
          'avg3' => '9.3',
          'firstval3' => '9.3',
          'sum2' => '11356.1',
          'Status_Jalousie_Automatik' => -1,
          'mindate3' => '2016-12-30_09:01:39',
          'max3' => '11.5',
          'avg1' => '5.0',
          'firstval1' => 0,
          'currval2' => '20.2',
          'lastraw1' => undef,
          'RC_makenotify' => {
                               'YAMAHA_BD' => 'YAMAHA_BD_RCmakenotify'
                             },
          'currdate3' => '2016-12-30_22:53:40',
          'FWEXT' => {
                       '/SVG_showLog' => {
                                           'FORKABLE' => 1,
                                           'FUNC' => 'SVG_showLog'
                                         },
                       '/FileLog_logWrapper' => {
                                                  'CONTENTFUNC' => 'FileLog_logWrapper'
                                                },
                       '/geo' => {
                                   'LINK' => 'geo',
                                   'FUNC' => 'GEOFANCY_CGI',
                                   'deviceName' => 'Geofancy'
                                 },
                       '/SVG_WriteGplot' => {
                                              'CONTENTFUNC' => 'SVG_WriteGplot'
                                            },
                       '/tablet' => {
                                      'NAME' => 'Tablet-UI',
                                      'LINK' => 'tablet',
                                      'FUNC' => 'HTTPSRV_CGI',
                                      'deviceName' => 'TABLETUI'
                                    },
                       '/FileLog_toSVG' => {
                                             'CONTENTFUNC' => 'FileLog_toSVG'
                                           }
                     },
          'webCmdFn' => {
                          '~' => 'FW_widgetFallbackFn'
                        },
          'cnt3' => 561,
          'firstdate2' => '2016-12-29_23:01:19',
          'min2' => '19.8',
          'min3' => '8.7',
          'currval3' => '8.8',

....usw.




Zitat von: klaymen am 30 Dezember 2016, 22:34:36
und wie kann man gemeinsame Teile in den Notifies in Perl Funktionen auslagern?

Dafür wird jede FHEM-Installation mit einer myUtilsTemplate.pm ausgeliefert:

##############################################
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $
#
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.

package main;

use strict;
use warnings;
use POSIX;

sub
myUtils_Initialize($$)
{
  my ($hash) = @_;
}

# Enter you functions below _this_ line.


1;


Diese dient als Grundgerüst. Man sollte sich basierend darauf eine Datei 99_myUtils.pm anlegen und unterhalb der Initialize-Funktion kann man eigene Routinen ablegen. Auf diese Weise habe ich meine gesamte Speziallogik realisiert. In Notify's verwende ich dann nur noch

{myOwnCoolFunction()}

oder wenn ich Daten aus dem Event verarbeiten möchte:

{myOwnCoolFunction($EVTPART1)}


Sobald man Änderungen an dieser Datei macht muss man diese immer via "reload 99_myUtils" neu laden.

Viele Grüße

Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)