FHEM Forum

FHEM => Sonstiges => Thema gestartet von: fhainz am 14 Dezember 2013, 12:43:23

Titel: Script in Modul "umwandeln"
Beitrag von: fhainz am 14 Dezember 2013, 12:43:23
Hallo!

Ich hab in den letzten Tagen versucht mein Script zur Stromverbrauchs Berechnung über die Laufzeit in ein Modul umzuwandeln. Hab mich durch diverse Wiki- und Foren Einträge geschlagen aber wenn ich ehrlich bin, bin ich nicht schlauer als vorher.

Das Ding macht bisher folgendes: Wenn ich einen Aktor zB. Steckdose, UP-Licht-Schalter, etc. einschalte wird die Start-Zeit ins Reading des Aktors geschrieben. Beim Ausschalten wird dann der Verbrauch berechnet und ins Reading geschrieben. Das funktioniert mittlerweile.
Der Aufruf des Scripts erfolgt derzeit über ein notify. define n_DeckenfluterVerbrauchR notify wzDeckenfluter { stromverbrauch($NAME, <WATT>);; }

Mein Ziel ist es das man das Modul definiert und es per on/off des Aktors automatisch gestartet und beendet wird. In einem Abstand von x Sekunden soll das Modul wenn der Aktor ein ist starten, die Readings neu berechnen und eintragen.
Dieser Abstands soll sowie die Leistung in Watt per Attribut definierbar sein.
Wenn ich das geschafft hab, kommt noch der Verbrauch von Heute, Monat, etc.

Nun meine Frage: Gibt es irgendwo eine Anleitung wie man ein Modul erstellt die ich übersehen hab? Oder kann mir das vielleicht jemand erklären?

Viele Grüße,
fhainz

Und sry falls ich das falsche Forum erwischt hab. Wusste nicht genau wohin damit ;)
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 14:23:37
Ich hab jetzt einfach versucht aus vorhandenen Modulen mir etwas zusammen zu kopieren.
Wie zu erwarten funktioniert das ganze nicht ;)

Ich schaff es nicht mal das Modul zu definieren, bekomm immer Unknown module currentCalculator . Kann mir jemand sagen was ich alles falsch mache? Hab ich es wenigstens ansatzweise richtig gemacht oder bin ich komplett am falschen weg?

Hier mal das Modul:
package main;

use strict;
use warnings;
use Time::HiRes qw(gettimeofday sleep);

sub currentCalculator_Get($@);
sub currentCalculator_Define($$);
sub currentCalculator_GetStatus($;$);
sub currentCalculator_Undefine($$);


sub
currentCalculator_Initialize($)
{
my ($hash) = @_;

$hash->{GetFn}     = "currentCalculator_Get";
  $hash->{SetFn}     = "currentCalculator_Set";
  $hash->{DefFn}    = "currentCalculator_Define";
  $hash->{UndefFn}   = "currentCalculator_Undefine"; 
  $hash->{ParseFn}  = "currentCalculator_ParseFn";
}

#####################################

sub
currentCalculator_Define($$)
{
my ($hash, $def) = @_;

  my @a = split("[ \t][ \t]*", $def);

  return "Usage: define <name> currentCalculator [aktor] [watt] [invterval]"  if(@a < 4 || @a > 5);

  my $name = $a[0];
  my $device = $a[2]; 
  my $watt = $a[3];
 
  my $interval = 60;
  $interval = $a[4] if($interval < 60);
 
  $hash->{NAME} = $name;
  $hash->{DEVICE} = $device;
  $hash->{STATE} = "Active";
  $hash->{INTERVAL} = $interval;
  $hash->{WATT} = $watt;

  return undef;
}

sub
currentCalculator_Set()
{}

sub currentCalculator_Undefine($$)
{}


sub
currentCalculator_ParseFn($)
{
  my ($hash) = @_;
  my $name = $hash->{NAME};
  my $device = $hash->{DEVICE};

#----- Untoggle Fix-----#
if ( Value($hash->{DEVICE}) eq "toggle" ) {
if ( OldValue($hash->{DEVICE}) eq "off" ) {
fhem("set $device on");
}
else {
fhem("set $device off");
}
}

my $on = "";
$hash->{ON} = $on;

if ( Value($device) eq "on" ) {
$hash->{ON} = int( time() );

speedtest_setReading( $hash->{DEVICE}, "on", $hash->{ON} );
speedtest_setReading( $hash->{DEVICE}, "power", $hash->{WATT} );
}
elsif ( Value($device) eq "off" ) {
currentCalculator_berechnen( $hash->{DEVICE}, $hash->{WATT} );
}
else {
Log3 $hash->{NAME}, 3, "Untoggle Problem";
}
}

#-----     Stromverbrauch berechnen     -----#
sub
currentCalculator_Berechnen($)
{
my ($hash) = @_;

$hash->{ON} = ReadingsVal( $hash->{DEVICE}, "on", "0" );
$hash->{OFF} = int( time() );

$hash->{ONLAST} = $hash->{OFF} - $hash->{ON};

$hash->{ONTOTAL}          = ReadingsVal( $hash->{DEVICE}, "onTotal",          "0" );
$hash->{CONSUMPTIONTOTAL} = ReadingsVal( $hash->{DEVICE}, "consumptionTotal", "" );
$hash->{ONTOTAL}          = int( $hash->{ONTOTAL} + $hash->{ONLAST} );

$hash->{CONSUMPTIONLAST}  = $hash->{ONLAST} * $hash->{WATT} / 1000 / 3600;
$hash->{CONSUMPTIONTOTAL} = $hash->{CONSUMPTIONTOTAL} + $hash->{CONSUMPTIONLAST};

#$consumptionTotal = sprintf "%.2f", $consumptionTotal;

if ( $hash->{ON} > 0 ) {
setReading( $hash->{DEVICE}, "on", 0 );
setReading( $hash->{DEVICE}, "off", $hash->{OFF} );
setReading( $hash->{DEVICE}, "onLast", $hash->{ONLAST} );
setReading( $hash->{DEVICE}, "onTotal", $hash->{ONTOTAL} );
setReading( $hash->{DEVICE}, "power", "0" );
setReading( $hash->{DEVICE}, "consumptionTotal", $hash->{CONSUMPTIONTOTAL} );
}
else {
Log3 $hash->{DEVICE}, 3, "Keine Startzeit ermittelt";
}
}

#-----     setReading     -----#
sub setReading($$$) {
my ($hash, $readingsName, $readingsWert) = @_;

readingsBeginUpdate( $hash );
readingsBulkUpdate( $hash, $readingsName, $readingsWert );
readingsBulkUpdate( $hash, $readingsName, $readingsWert );
readingsEndUpdate( $hash, 1 );
}


Ich hoffe mir kann jemand weiterhelfen.

Grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 15 Dezember 2013, 14:39:30
ganz ans ende muss ein 1;sonst läd fhem das modul nicht.

für die notifys ist notifyFn zuständig. nicht parseFn.

es taucht noch ein spendetest_... auf. das ist ziemlich sicher nicht beabsichtig.

die mehrfachen readingsBeginUpdate/readingsEndUpdate sind nicht optimal. die würde ich auf einen rutsch schreiben.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 14:48:19
Ich hab die Punkte geändert. Nun schmiert FHEM direkt nach dem speichern der fhem.cfg ab.

package main;

use strict;
use warnings;
use Time::HiRes qw(gettimeofday sleep);

sub currentCalculator_Get($@);
sub currentCalculator_Define($$);
sub currentCalculator_GetStatus($;$);
sub currentCalculator_Undefine($$);

sub currentCalculator_Initialize($) {
my ($hash) = @_;

$hash->{GetFn}   = "currentCalculator_Get";
$hash->{SetFn}   = "currentCalculator_Set";
$hash->{DefFn}   = "currentCalculator_Define";
$hash->{UndefFn} = "currentCalculator_Undefine";
$hash->{NotifyFn} = "currentCalculator_NotifyFn";
}

#####################################

sub currentCalculator_Define($$) {
my ( $hash, $def ) = @_;

my @a = split( "[ \t][ \t]*", $def );
return "Usage: define <name> currentCalculator [aktor] [watt] [invterval]"
if ( @a < 4 || @a > 5 );

my $name   = $a[0];
my $device = $a[2];
my $watt   = $a[3];

my $interval = 60;
$interval = $a[4] if ( $interval < 60 );

$hash->{NAME}     = $name;
$hash->{DEVICE}   = $device;
$hash->{STATE}    = "Active";
$hash->{INTERVAL} = $interval;
$hash->{WATT}     = $watt;

return undef;
}

sub currentCalculator_Set() {
}

sub currentCalculator_Undefine($$) { }

sub currentCalculator_NotifyFn($) {
my ($hash) = @_;
my $name   = $hash->{NAME};
my $device = $hash->{DEVICE};

#----- Untoggle Fix-----#
if ( Value( $hash->{DEVICE} ) eq "toggle" ) {
if ( OldValue( $hash->{DEVICE} ) eq "off" ) {
fhem("set $device on");
}
else {
fhem("set $device off");
}
}

my $on = "";
$hash->{ON} = $on;

if ( Value($device) eq "on" ) {
$hash->{ON} = int( time() );

setReading( $hash->{DEVICE}, "on",    $hash->{ON} );
setReading( $hash->{DEVICE}, "power", $hash->{WATT} );
}
elsif ( Value($device) eq "off" ) {
currentCalculator_berechnen( $hash->{DEVICE}, $hash->{WATT} );
}
else {
Log3 $hash->{NAME}, 3, "Untoggle Problem";
}
}

#-----     Stromverbrauch berechnen     -----#
sub currentCalculator_Berechnen($) {
my ($hash) = @_;

$hash->{ON} = ReadingsVal( $hash->{DEVICE}, "on", "0" );
$hash->{OFF} = int( time() );

$hash->{ONLAST} = $hash->{OFF} - $hash->{ON};

$hash->{ONTOTAL} = ReadingsVal( $hash->{DEVICE}, "onTotal", "0" );
$hash->{CONSUMPTIONTOTAL} = ReadingsVal( $hash->{DEVICE}, "consumptionTotal", "" );
$hash->{ONTOTAL} = int( $hash->{ONTOTAL} + $hash->{ONLAST} );

$hash->{CONSUMPTIONLAST} = $hash->{ONLAST} * $hash->{WATT} / 1000 / 3600;
$hash->{CONSUMPTIONTOTAL} = $hash->{CONSUMPTIONTOTAL} + $hash->{CONSUMPTIONLAST};

#$consumptionTotal = sprintf "%.2f", $consumptionTotal;

if ( $hash->{ON} > 0 ) {
setReading( $hash->{DEVICE}, "on",      0 );
setReading( $hash->{DEVICE}, "off",     $hash->{OFF} );
setReading( $hash->{DEVICE}, "onLast",  $hash->{ONLAST} );
setReading( $hash->{DEVICE}, "onTotal", $hash->{ONTOTAL} );
setReading( $hash->{DEVICE}, "power",   "0" );
setReading( $hash->{DEVICE}, "consumptionTotal",
$hash->{CONSUMPTIONTOTAL} );
}
else {
Log3 $hash->{DEVICE}, 3, "Keine Startzeit ermittelt";
}
}

#-----     setReading     -----#
sub setReading($$$) {
my ( $hash, $readingsName, $readingsWert ) = @_;

readingsBeginUpdate($hash);
readingsBulkUpdate( $hash, $readingsName, $readingsWert );
readingsEndUpdate( $hash, 1 );
}

1;


grüße
Titel: Antw:Script in Modul &quot;umwandeln&quot;
Beitrag von: justme1968 am 15 Dezember 2013, 14:50:14
schau ins log was der grund ist.

oder auf der konsole auf der du fhem gestartet hast.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 15:00:28
Leider steht nichts im Log das sich auf das Modul bezieht. Nur das neustarten nach dem Absturz.

Edit:
Ich habs nochmal versucht. Dieses mal direkt in der Eingabezeile in fhemweb. Selbes Ergebnis:
2013.12.15 15:12:36.163 3: FS20 set wzDeckenfluter on
2013.12.15 15:12:36.847 1: Perfmon: possible freeze starting at 15:12:34, delay is 2.847
2013.12.15 15:12:45.518 1: Perfmon: possible freeze starting at 15:12:39, delay is 6.518
2013.12.15 15:12:50.803 1: Perfmon: possible freeze starting at 15:12:46, delay is 4.802
2013.12.15 15:13:40.131 1: Including fhem.cfg

Direkt nachdem mich den deckenfluter eingeschaltet hab hab ich in die adresszeile define sv_wzDeckenfluter currentCalculator wzDeckenfluter 9 60 kopiert, bestätigt, abgestürzt.
Die freeze's sind "normal" die hab ich ständig.
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: John am 15 Dezember 2013, 15:17:52
Hallo fhainz,

vielleicht hilft dir ja mein Betriebsstundenzähler weiter
http://www.fhemwiki.de/wiki/HourCounter (http://www.fhemwiki.de/wiki/HourCounter)

Über UserReadings kannst du beliebige Wert, also auch den Stromverbrauch über die Einschaltzeit berechnen lassen.


John
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 15:22:58
Hallo John,

den HourCounter hab ich mir schon angesehen. Habs mir auch teilweise zur Vorlage genommen aber leider blick ich nicht ganz durch den code.
Wahrscheinlich würde es mit deinem Modul auch irgendwie klappen, aber das bringt mir in meiner jetzigen Situation nicht. Ich will ja lernen wie man ein Modul schreibt.
Deshalb auch der "aufwand" etwas neu zu programmieren was es vielleicht in irgendeiner form schon gibt.

Grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: UliM am 15 Dezember 2013, 16:16:36
setz mal
attr global verbose 5
bevor du das define absetzt.
Vll siehst Du dann besser, bis zu welcher Stelle das ganze kommt.
Vorher vll. noch Dein Prog mit
Log 1, cc: Zeile ###";
pflastern, damit Du sihest, was noch aufgerufen wurde und was nicht mehr.

Es könnte an der leeren set-routine liegen, denn fhemweb setzt zum Anzeigen des device ein "set <device> ?" ab, um die verfügbaren Befehle zurückzubekommen.

Wenn Du nur eine Variable belegst, funktioniert = @_ nicht, da musst Du shift nehmen.

Wird denn eine Fehlermeldung erzeugt, wenn Du ein reload Deines Moduls ausführst?

=8-)
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 15 Dezember 2013, 16:32:03
starte vor allem fhem selber von hand auf der kommandozeile so das du ausgaben sehen kannst oder leite stdout und stderr um so das du beides auch im log hast.

my ($hash) = @_;funktioniert auch mit einer variable. shift nur verwenden wenn du @_ auch tastächlich modifizieren willst.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 18:25:52
Ok habs num mit verbose 5 versucht.

Im Log steht folgendes:
Zitat2013.12.15 17:47:55.012 4: HTTP FHEMWEB:10.0.0.1:65154 GET /fhem&cmd=define+sv_wzDeckenfluter+currentCalculator+wzDeckenfluter+9+60
2013.12.15 17:47:55.017 5: Cmd: >define sv_wzDeckenfluter currentCalculator wzDeckenfluter 9 60<
2013.12.15 17:47:55.020 5: Loading ./FHEM/60_currentCalculator.pm
2013.12.15 17:47:55.078 5: Triggering global (1 changes)
2013.12.15 17:47:55.090 5: Notify loop for global DEFINED sv_wzDeckenfluter
2013.12.15 17:47:55.190 4: HTTP FHEMWEB:10.0.0.1:65154 GET /fhem?detail=sv_wzDeckenfluter
2013.12.15 17:49:22.531 1: Including fhem.cfg

Im Telnet Fenster hatte ich nur
Zitat2013-12-15 17:47:55.175 Global global DEFINED sv_wzDeckenfluter
Connection closed by foreign host.

Ich hab dann die Zeilen logs eingebaut. Ich komm bis zum return undef; in der sub currentCalculator_Define()
Hab direkt drunter noch ein Log und der wird nicht angezeigt.

Hilft das was?

Grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 15 Dezember 2013, 18:27:52
schau auf die konsole wenn du fhem von hand startest.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 18:29:05
Was meinst du mit von hand starten?

Nachdem abstürzen starte ich das raspi der sudo reboot neu.
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 15 Dezember 2013, 18:36:59
also wenn fhem abschmiert musst du nicht den ganzen rechner neu starten.

irgendwo gibt es ein start script das fhem startet. das kannst du auch von hand starten. etwas in der art /etc/init.d/fhem startje nach user vermutlich mit sudo. in diesem terminal in dem du das gemacht hast sollte beim absturz etwas zu sehen sein.

du kannst auch die zeile perl fhem.pl fhem.cfg so ändern das stdout und stderr geloggt werden:perl fhem.pl fhem.cfg >>/opt/fhem/log/fhem-stdout 2>>/opt/fhem/log/fhem-stderr

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 18:43:38
Zitat von: justme1968 am 15 Dezember 2013, 18:36:59also wenn fhem abschmiert musst du nicht den ganzen rechner neu starten.
Gut zu wissen ;) Das script ist in dem ordner den du beschrieben hast.

Zitat von: justme1968 am 15 Dezember 2013, 18:36:59in diesem terminal in dem du das gemacht hast sollte beim absturz etwas zu sehen sein.
Wann? Wenn ich dann per telnet eingeloggt bin?

Zitat von: justme1968 am 15 Dezember 2013, 18:36:59du kannst auch die zeile perl fhem.pl fhem.cfg so ändern das stdout und stderr geloggt werden:perl fhem.pl fhem.cfg >>/opt/fhem/log/fhem-stdout 2>>/opt/fhem/log/fhem-stderr
Wo soll sich diese Zeile befinden?

Ich glaub ich steh am Schlauch  :(

grüße
Titel: Antw:Script in Modul &quot;umwandeln&quot;
Beitrag von: justme1968 am 15 Dezember 2013, 18:46:46
ja wenn du per ssh oder telnet verbunden bist.

die zeile ist in dem start script.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 18:54:25
Alles klar. Jetzt hab ich es überissen ;)

Wenn ich fhem so starte bekomm ich gleich jede menge Fehlermeldungen
Useless use of private variable in void context at ./FHEM/33_readingsGroup.pm line 525, <> line 8.
Use of uninitialized value $name in substitution (s///) at ./FHEM/01_FHEMWEB.pm line 1824.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in substitution (s///) at ./FHEM/01_FHEMWEB.pm line 1824.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in substitution (s///) at ./FHEM/01_FHEMWEB.pm line 1824.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in substitution (s///) at ./FHEM/01_FHEMWEB.pm line 1824.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in substitution (s///) at ./FHEM/01_FHEMWEB.pm line 1824.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in substitution (s///) at ./FHEM/01_FHEMWEB.pm line 1824.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in substitution (s///) at ./FHEM/01_FHEMWEB.pm line 1824.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in substitution (s///) at ./FHEM/01_FHEMWEB.pm line 1824.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in substitution (s///) at ./FHEM/01_FHEMWEB.pm line 1824.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Use of uninitialized value $name in hash element at ./FHEM/01_FHEMWEB.pm line 1826.
Undefined subroutine &main::currentCalculator_Get called at fhem.pl line 2636


Undefined subroutine kam direkt nachdem ich das define in der eingabezeile abgesetzt hab. Der rest gleich nach dem starten.
Eigenartig das der Fehler aussagt das ich keine currentCalculator_Get habe. Das hab ich ja mit $hash->{GetFn}   = "currentCalculator_Get"; definiert oder?

grüße
Titel: Antw:Script in Modul &quot;umwandeln&quot;
Beitrag von: justme1968 am 15 Dezember 2013, 18:55:57
du muss sie auch schreiben. nicht nur deklarieren.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 19:02:00
OK das hat jetzt geklappt aber nachdem die detail Seite angezeigt wurde hat sich fhem mit dem Fehler
ZitatCan't use string ("wzDeckenfluter") as a HASH ref while "strict refs" in use at ./FHEM/60_currentCalculator.pm line 96.
wieder aufgehängt ;)

Zeile 96:
$hash->{ON} = ReadingsVal( $hash->{DEVICE}, "on", "0" );

grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 15 Dezember 2013, 19:14:23
du übergibst beim aufruf von currentCalculator_Berechnen nicht $hash sondern $hash->{DEVICE}. das ist falsch. jedenfalls dann wenn du in currentCalculator_Berechnen einen $hash erwartest...

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 19:17:03
Kannst du mir ein Beispiel schreiben wie es richtig ist?
Wie gesagt ist mein erstes Modul und eigentlich hab ich, durch mangel an developer einsteiger infos, keinen Plan was ich da mache ;)

grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 15 Dezember 2013, 19:19:43
versuch es mal nur mit $hash. aber es ist dein modul und ich kann nicht in deinen kopf schauen. es gibt kein einziges richtig sonder sehr viele möglichkeiten.


gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 15 Dezember 2013, 19:20:57
vielleicht allgemein: es ist wichtig das du dein device (meistens $hash) und das device an das du dich dran hängst nicht durcheinander bringst.

du willst in fast allen routinen dein device übergeben und da einen link zum device das überwacht werden soll drine haben.

gruss
   andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 15 Dezember 2013, 19:31:39
Sry ich versteh's nicht.
Ich weiß nicht mal was was dieses $hash ist bzw. was es macht oder wie bzw. wann ich es einsetze

Soll ich anstatt $hash->{} "normale" variablen verwenden so wie in dem script das ich in der 99_myUtils.pm hatte?

#-------------------------     Stromverbrauch nach Laufzeit ermitteln     ---------------#
#-----     Stromverbrauch -----#

sub stromverbrauch($$) {
my $device           = shift;
my $watt             = shift;
my $on               = "";
my $off              = 0;
my $onLast           = 0;
my $consumptionLast  = 0;
my $onTotal          = 0;
my $consumptionTotal = 0;

#----- Untoggle Fix-----#
if ( Value($device) eq "toggle" ) {
if ( OldValue($device) eq "off" ) {
fhem("set $device on");
}
else {
fhem("set $device off");
}
}

if ( Value($device) eq "on" ) {
$on = int( time() );

setReading( $device, "on", $on );
setReading( $device, "power", $watt );
}
elsif ( Value($device) eq "off" ) {
stromverbrauchBerechnen( $device, $watt );
}
else {
Log3 $device, 3, "Untoggle Problem";
}
}

#-----     Stromverbrauch berechnen     -----#
sub stromverbrauchBerechnen($$) {
$device = shift;
$watt   = shift;

$on = ReadingsVal( $device, "on", "0" );
$off = int( time() );

$onLast = $off - $on;

$onTotal          = ReadingsVal( $device, "onTotal",          "0" );
$consumptionTotal = ReadingsVal( $device, "consumptionTotal", "" );
$onTotal          = int( $onTotal + $onLast );

$consumptionLast  = $onLast * $watt / 1000 / 3600;
$consumptionTotal = $consumptionTotal + $consumptionLast;

$consumptionTotal = sprintf "%.2f", $consumptionTotal;

if ( $on > 0 ) {
setReading( $device, "on",               0 );
setReading( $device, "off",              $off );
setReading( $device, "onLast",           $onLast );
setReading( $device, "onTotal",          $onTotal );
setReading( $device, "power",            "0" );
setReading( $device, "consumptionTotal", $consumptionTotal );
}
else {
Log3 $device, 3, "Keine Startzeit ermittelt";
}
}

#-----     setReading     -----#
sub setReading($$$) {
my $device       = shift;
my $readingsName = shift;
my $readingsWert = shift;

readingsBeginUpdate( $main::defs{$device} );
readingsBulkUpdate( $main::defs{$device}, $readingsName, $readingsWert );
readingsBulkUpdate( $main::defs{$device}, $readingsName, $readingsWert );
readingsEndUpdate( $main::defs{$device}, 1 );
}


Grüße

Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 29 Dezember 2013, 18:56:47
Ich hab jetzt das Modul nochmals umgebaut und es funktioniert schon so halbwegs.
Mein Problem ist jetzt, dass das die currentCalculator_NotifyFn sich in einer endlosschleife andauernd aufruft.
Schaff ich es irgendwie das sich das notifyFn nur aufruft wenn das entsprechende device on ist und sich solang alle interval Sekunden wiederholt bis das device off ist?

Hier mein Code:
package main;

use strict;
use warnings;
use Time::HiRes qw(gettimeofday sleep);

sub currentCalculator_Initialize($) {
my ($hash) = @_;

$hash->{GetFn}   = "currentCalculator_Get";
$hash->{SetFn}   = "currentCalculator_Set";
$hash->{DefFn}   = "currentCalculator_Define";
$hash->{UndefFn} = "currentCalculator_Undefine";
$hash->{NotifyFn} = "currentCalculator_NotifyFn";
}

#####################################

sub currentCalculator_Define($$) {
my ( $hash, $def ) = @_;

my @a = split( "[ \t][ \t]*", $def );
return "Usage: define <name> currentCalculator [device] [watt] [invterval]"
if ( @a < 4 || @a > 5 );

my $name   = $a[0];
my $device = $a[2];
my $watt   = $a[3];

my $interval = 60;
$interval = $a[4] if ( $interval < 60 );

$hash->{NAME}     = $name;
$hash->{DEVICE}   = $device;
$hash->{STATE}    = "Active";
$hash->{INTERVAL} = $interval;
$hash->{WATT}     = $watt;
Log3 $name, 3, "cc: Zeile 38";
 
return undef;
}

sub currentCalculator_Set() {}
sub currentCalculator_Get() {}
sub currentCalculator_Undefine($) {
my ($hash) = @_;
RemoveInternalTimer($hash->{NAME});

return undef;
}

sub currentCalculator_NotifyFn($) {
my ($hash) = @_;
my $name   = $hash->{NAME};
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

#----- Untoggle Fix-----#
if ( Value( $device ) eq "toggle" ) {
if ( OldValue( $device ) eq "off" ) {
fhem("set $device on");
}
else {
fhem("set $device off");
}
}
Log3 $name, 3, "cc: Zeile 67";

my $on = "";

if( Value($device) eq "on" ) {
$on = int( time() );
Log3 $name, 3, "cc: Zeile 73";
setReading( $device, "on",    $on );
setReading( $device, "power", $watt );
Log3 $name, 3, "cc: Zeile 76";
}
elsif ( Value($device) eq "off" ) {
currentCalculator_Berechnen( $hash, $device, $watt );
}
else {
Log3 $name, 3, "Untoggle Problem";
}
Log3 $name, 3, "cc: Zeile 84";
return undef;

RemoveInternalTimer($hash->{NAME});
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "currentCalculator_NotifyFn",$hash, 0);
}

#-----     Stromverbrauch berechnen     -----#
sub currentCalculator_Berechnen($$$) {
my ($hash) = @_;
my $device = shift;
my $watt = shift;

Log3 $device, 3, "cc: Zeile 98";

my $on               = "";
my $off              = 0;
my $onLast           = 0;
my $consumptionLast  = 0;
my $onTotal          = 0;
my $consumptionTotal = 0;

$on = ReadingsVal( $device, "on", "0" );
$off = int( time() );

$onLast = $off - $on;

$onTotal          = ReadingsVal( $device, "onTotal",          "0" );
$consumptionTotal = ReadingsVal( $device, "consumptionTotal", "0" );
$onTotal          = int( $onTotal + $onLast );

$consumptionLast  = $onLast * $watt / 1000 / 3600;
$consumptionTotal = $consumptionTotal + $consumptionLast;

$consumptionTotal = sprintf "%.2f", $consumptionTotal;

Log3 $device, 3, "cc: Zeile 121";
Log3 $device, 3, "Device:".$device.", On:".$on.", Off:".$off;

if ( $on > 0 ) {
setReading( $device, "on",      0 );
setReading( $device, "off",     $off );
setReading( $device, "onLast",  $onLast );
setReading( $device, "onTotal", $onTotal );
setReading( $device, "power",   "0" );
setReading( $device, "consumptionTotal", $consumptionTotal );
}
else {
Log3 $device, 3, "Keine Startzeit ermittelt";
}
Log3 $device, 3, "cc: Zeile 134";
}

#-----     setReading     -----#
sub setReading($$$) {
my $device       = shift;
my $readingsName = shift;
my $readingsWert = shift;

Log3 $device, 3, "cc: Zeile 143";
readingsBeginUpdate($main::defs{$device});
readingsBulkUpdate( $main::defs{$device}, $readingsName, $readingsWert );
readingsEndUpdate( $main::defs{$device}, 1 );
}

1;



Log:
2013.12.29 18:43:48.089 3: Device:HASH(0x21e21f8), On:0, Off:1388339028
2013.12.29 18:43:48.089 3: Keine Startzeit ermittelt
2013.12.29 18:43:48.090 3: cc: Zeile 134
2013.12.29 18:43:48.091 3: cc: Zeile 84
2013.12.29 18:43:48.484 3: cc: Zeile 67
2013.12.29 18:43:48.485 3: cc: Zeile 98
2013.12.29 18:43:48.488 3: cc: Zeile 121
2013.12.29 18:43:48.489 3: Device:HASH(0x21e21f8), On:0, Off:1388339028
2013.12.29 18:43:48.490 3: Keine Startzeit ermittelt
2013.12.29 18:43:48.491 3: cc: Zeile 134
2013.12.29 18:43:48.492 3: cc: Zeile 84
2013.12.29 18:43:48.883 3: cc: Zeile 67
2013.12.29 18:43:48.884 3: cc: Zeile 98
2013.12.29 18:43:48.887 3: cc: Zeile 121
2013.12.29 18:43:48.888 3: Device:HASH(0x21e21f8), On:0, Off:1388339028
2013.12.29 18:43:48.889 3: Keine Startzeit ermittelt
2013.12.29 18:43:48.890 3: cc: Zeile 134
2013.12.29 18:43:48.891 3: cc: Zeile 84
2013.12.29 18:43:55.097 3: cc: Zeile 67
2013.12.29 18:43:55.098 3: cc: Zeile 98
2013.12.29 18:43:55.101 3: cc: Zeile 121



Grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 29 Dezember 2013, 19:04:40
du solltest für notify und für den timer zwei unterschiedliche funktionen verwenden. und am besten noch eine update funktion die die werte aktualisiert.


currentCalculator_NotifyFn nur um festzustellen ob dein device den zustand gewechselt hat und eine andere funktion die regelnässig aufgerufen wird solange dein device an ist. also sobald das überwachte device auf on geht die timer funktion ein mal aufrufen. in der timer funktion die update aufrufen und das RemoveInternalTimer / InternalTimer und wenn dein device auf off geht ein mal ein RemoveInternalTimer und update.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 29 Dezember 2013, 19:48:52
ok ich hab jetzt noch eine Funktion run. Die Funktion setzt die startzeit und ruft per timer die berechnen() auf, diese wiederum die setReading().
Leider immer noch in einer endlosschleife und nun wird auch $device nicht mehr an die Funktion setReading übergeben. :(

Code:
package main;

use strict;
use warnings;
use Time::HiRes qw(gettimeofday sleep);

sub currentCalculator_Initialize($) {
my ($hash) = @_;

$hash->{GetFn}   = "currentCalculator_Get";
$hash->{SetFn}   = "currentCalculator_Set";
$hash->{DefFn}   = "currentCalculator_Define";
$hash->{UndefFn} = "currentCalculator_Undefine";
$hash->{NotifyFn} = "currentCalculator_NotifyFn";
}

#####################################

sub currentCalculator_Define($$) {
my ( $hash, $def ) = @_;

my @a = split( "[ \t][ \t]*", $def );
return "Usage: define <name> currentCalculator [device] [watt] [invterval]"
if ( @a < 4 || @a > 5 );

my $name   = $a[0];
my $device = $a[2];
my $watt   = $a[3];

my $interval = 60;
$interval = $a[4] if ( $interval < 60 );

$hash->{NAME}     = $name;
$hash->{DEVICE}   = $device;
$hash->{STATE}    = "Active";
$hash->{INTERVAL} = $interval;
$hash->{WATT}     = $watt;
Log3 $name, 3, "cc: Zeile 38";
 
return undef;
}

sub currentCalculator_Set() {}
sub currentCalculator_Get() {}
sub currentCalculator_Undefine($) {
my ($hash) = @_;
RemoveInternalTimer($hash->{NAME});

return undef;
}

sub currentCalculator_NotifyFn($) {
my ($hash) = @_;
my $name   = $hash->{NAME};
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

#----- Untoggle Fix-----#
if ( Value( $device ) eq "toggle" ) {
if ( OldValue( $device ) eq "off" ) {
fhem("set $device on");
}
else {
fhem("set $device off");
}
}

my $on = "";

if( Value($device) eq "on" ) {
currentCalculator_Run($hash,$device,$watt);
}
elsif ( Value($device) eq "off" ) {
currentCalculator_Berechnen( $hash, $device, $watt );
setReading( $device, "on", 0 );
RemoveInternalTimer($hash->{NAME});
}
else {
Log3 $name, 3, "Untoggle Problem";
}
return undef;
}

#-----     Stromverbrauch Startzeit setzen     -----#
sub currentCalculator_Run($$$){
my ($hash) = @_;
my $device = shift;
my $watt = shift;

my $on = int( time() );

setReading( $device, "on",    $on );
setReading( $device, "power", $watt );

currentCalculator_Berechnen($hash,$device,$watt);

RemoveInternalTimer($hash->{NAME});
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "currentCalculator_Berechnen",$hash, 0);
}

#-----     Stromverbrauch berechnen     -----#
sub currentCalculator_Berechnen($$$) {
my ($hash) = @_;
my $device = shift;
my $watt = shift;

my $on               = "";
my $off              = 0;
my $onLast           = 0;
my $consumptionLast  = 0;
my $onTotal          = 0;
my $consumptionTotal = 0;

$on = ReadingsVal( $device, "on", "0" );
$off = int( time() );

$onLast = $off - $on;

$onTotal          = ReadingsVal( $device, "onTotal",          "0" );
$consumptionTotal = ReadingsVal( $device, "consumptionTotal", "0" );
$onTotal          = int( $onTotal + $onLast );

$consumptionLast  = $onLast * $watt / 1000 / 3600;
$consumptionTotal = $consumptionTotal + $consumptionLast;

$consumptionTotal = sprintf "%.2f", $consumptionTotal;

Log3 $device, 3, "Device:".$device.", On:".$on.", Off:".$off;

setReading( $device, "on",      $on );
setReading( $device, "off",     $off );
setReading( $device, "onLast",  $onLast );
setReading( $device, "onTotal", $onTotal );
setReading( $device, "power",   "0" );
setReading( $device, "consumptionTotal", $consumptionTotal );
}

#-----     setReading     -----#
sub setReading($$$) {
my $device       = shift;
my $readingsName = shift;
my $readingsWert = shift;

Log3 $device, 3, "cc: Zeile 143";
readingsBeginUpdate($main::defs{$device});
readingsBulkUpdate( $main::defs{$device}, $readingsName, $readingsWert );
readingsEndUpdate( $main::defs{$device}, 1 );
}

1;


Log:
2013.12.29 19:40:50.541 3: cc: Zeile 38
2013.12.29 19:40:59.913 3: Device:HASH(0x18b23e0), On:0, Off:1388342459
2013.12.29 19:40:59.914 3: cc: Zeile 143
2013.12.29 19:40:59.918 1: readingsUpdate(,on,0) missed to call readingsBeginUpdate first.
2013.12.29 19:40:59.922 3: cc: Zeile 143
2013.12.29 19:40:59.926 1: readingsUpdate(,off,1388342459) missed to call readingsBeginUpdate first.
2013.12.29 19:40:59.929 3: cc: Zeile 143
2013.12.29 19:40:59.933 1: readingsUpdate(,onLast,1388342459) missed to call readingsBeginUpdate first.
2013.12.29 19:40:59.936 3: cc: Zeile 143
2013.12.29 19:40:59.939 1: readingsUpdate(,onTotal,1388342459) missed to call readingsBeginUpdate first.
2013.12.29 19:40:59.942 3: cc: Zeile 143
2013.12.29 19:40:59.945 1: readingsUpdate(,power,0) missed to call readingsBeginUpdate first.
2013.12.29 19:40:59.948 3: cc: Zeile 143
2013.12.29 19:40:59.952 1: readingsUpdate(,consumptionTotal,0.00) missed to call readingsBeginUpdate first.
2013.12.29 19:40:59.954 3: cc: Zeile 143
2013.12.29 19:41:00.139 3: Device:HASH(0x18b23e0), On:0, Off:1388342460
2013.12.29 19:41:00.140 3: cc: Zeile 143
2013.12.29 19:41:00.143 1: readingsUpdate(,on,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.146 3: cc: Zeile 143
2013.12.29 19:41:00.150 1: readingsUpdate(,off,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.154 3: cc: Zeile 143
2013.12.29 19:41:00.158 1: readingsUpdate(,onLast,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.163 3: cc: Zeile 143
2013.12.29 19:41:00.167 1: readingsUpdate(,onTotal,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.171 3: cc: Zeile 143
2013.12.29 19:41:00.175 1: readingsUpdate(,power,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.179 3: cc: Zeile 143
2013.12.29 19:41:00.183 1: readingsUpdate(,consumptionTotal,0.00) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.187 3: cc: Zeile 143
2013.12.29 19:41:00.259 3: Device:HASH(0x18b23e0), On:0, Off:1388342460
2013.12.29 19:41:00.260 3: cc: Zeile 143
2013.12.29 19:41:00.263 1: readingsUpdate(,on,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.267 3: cc: Zeile 143
2013.12.29 19:41:00.271 1: readingsUpdate(,off,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.274 3: cc: Zeile 143
2013.12.29 19:41:00.278 1: readingsUpdate(,onLast,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.281 3: cc: Zeile 143
2013.12.29 19:41:00.284 1: readingsUpdate(,onTotal,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.288 3: cc: Zeile 143
2013.12.29 19:41:00.292 1: readingsUpdate(,power,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.295 3: cc: Zeile 143
2013.12.29 19:41:00.299 1: readingsUpdate(,consumptionTotal,0.00) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.303 3: cc: Zeile 143
2013.12.29 19:41:00.382 3: Device:HASH(0x18b23e0), On:0, Off:1388342460
2013.12.29 19:41:00.383 3: cc: Zeile 143
2013.12.29 19:41:00.386 1: readingsUpdate(,on,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.390 3: cc: Zeile 143
2013.12.29 19:41:00.393 1: readingsUpdate(,off,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.397 3: cc: Zeile 143
2013.12.29 19:41:00.400 1: readingsUpdate(,onLast,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.404 3: cc: Zeile 143
2013.12.29 19:41:00.408 1: readingsUpdate(,onTotal,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.411 3: cc: Zeile 143
2013.12.29 19:41:00.415 1: readingsUpdate(,power,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.418 3: cc: Zeile 143
2013.12.29 19:41:00.422 1: readingsUpdate(,consumptionTotal,0.00) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.426 3: cc: Zeile 143
2013.12.29 19:41:00.583 3: Device:HASH(0x18b23e0), On:0, Off:1388342460
2013.12.29 19:41:00.585 3: cc: Zeile 143
2013.12.29 19:41:00.588 1: readingsUpdate(,on,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.591 3: cc: Zeile 143
2013.12.29 19:41:00.595 1: readingsUpdate(,off,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.598 3: cc: Zeile 143
2013.12.29 19:41:00.602 1: readingsUpdate(,onLast,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.605 3: cc: Zeile 143
2013.12.29 19:41:00.609 1: readingsUpdate(,onTotal,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.613 3: cc: Zeile 143
2013.12.29 19:41:00.616 1: readingsUpdate(,power,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.620 3: cc: Zeile 143
2013.12.29 19:41:00.623 1: readingsUpdate(,consumptionTotal,0.00) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.627 3: cc: Zeile 143
2013.12.29 19:41:00.694 3: Device:HASH(0x18b23e0), On:0, Off:1388342460
2013.12.29 19:41:00.695 3: cc: Zeile 143
2013.12.29 19:41:00.698 1: readingsUpdate(,on,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.702 3: cc: Zeile 143
2013.12.29 19:41:00.705 1: readingsUpdate(,off,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.709 3: cc: Zeile 143
2013.12.29 19:41:00.713 1: readingsUpdate(,onLast,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.716 3: cc: Zeile 143
2013.12.29 19:41:00.720 1: readingsUpdate(,onTotal,1388342460) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.723 3: cc: Zeile 143
2013.12.29 19:41:00.727 1: readingsUpdate(,power,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.731 3: cc: Zeile 143
2013.12.29 19:41:00.734 1: readingsUpdate(,consumptionTotal,0.00) missed to call readingsBeginUpdate first.
2013.12.29 19:41:00.738 3: cc: Zeile 143
2013.12.29 19:41:03.419 3: Device:HASH(0x18b23e0), On:0, Off:1388342463
2013.12.29 19:41:03.420 3: cc: Zeile 143
2013.12.29 19:41:03.424 1: readingsUpdate(,on,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:03.427 3: cc: Zeile 143
2013.12.29 19:41:03.430 1: readingsUpdate(,off,1388342463) missed to call readingsBeginUpdate first.
2013.12.29 19:41:03.434 3: cc: Zeile 143
2013.12.29 19:41:03.436 1: readingsUpdate(,onLast,1388342463) missed to call readingsBeginUpdate first.
2013.12.29 19:41:03.439 3: cc: Zeile 143
2013.12.29 19:41:03.442 1: readingsUpdate(,onTotal,1388342463) missed to call readingsBeginUpdate first.
2013.12.29 19:41:03.444 3: cc: Zeile 143
2013.12.29 19:41:03.447 1: readingsUpdate(,power,0) missed to call readingsBeginUpdate first.
2013.12.29 19:41:03.450 3: cc: Zeile 143
2013.12.29 19:41:03.453 1: readingsUpdate(,consumptionTotal,0.00) missed to call readingsBeginUpdate first.
2013.12.29 19:41:03.455 3: cc: Zeile 143
2013.12.29 19:41:03.627 3: Device:HASH(0x18b23e0), On:0, Off:1388342463
2013.12.29 19:41:03.628 3: cc: Zeile 143
2013.12.29 19:41:03.632 1: readingsUpdate(,on,0) missed to call readingsBeginUpdate first.


Ich raff es nicht...  :(

Grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 29 Dezember 2013, 19:59:16
die NotifyFn wird für jedes event in fhem aufgerufen.

du darfst nur darauf reagieren wenn es auch dein device betrifft. und nur auf on und off und delete.

sonst hat du ein run für wirklich jedes event das in fhem passiert getriggert.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 29 Dezember 2013, 20:12:53
Zitat von: justme1968 am 29 Dezember 2013, 19:59:16
du darfst nur darauf reagieren wenn es auch dein device betrifft. und nur auf on und off und delete.

ich hab mir jetzt ein paar module mit einer notifyfn angesehen. Meinst du sowas wie
return if($dev->{NAME} eq $name);
in deiner readingsGroup.pm?

Ich komm nicht drauf..


Grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 29 Dezember 2013, 21:01:53
so ähnlich aber das alleine reicht nicht. das ignoriert nur notifys die für den currentCalculator. du willst aber alles ignorieren bis auf die notifys für das device an dem der currentCalculator hängt. also eher so:return if($dev->{NAME} ne $hash->{DEVICE});

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 29 Dezember 2013, 23:23:52
OK, das funktioniert nun auch.

Nach einige male Haare raufen und ca. 100x fhem neu starten sieht mein Modul nun so aus
package main;

use strict;
use warnings;
use Time::HiRes qw(gettimeofday sleep);

sub currentCalculator_Initialize($) {
my ($hash) = @_;

$hash->{GetFn}   = "currentCalculator_Get";
$hash->{SetFn}   = "currentCalculator_Set";
$hash->{DefFn}   = "currentCalculator_Define";
$hash->{UndefFn} = "currentCalculator_Undefine";
$hash->{NotifyFn} = "currentCalculator_NotifyFn";
}

#####################################

sub currentCalculator_Define($$) {
my ( $hash, $def ) = @_;

my $version = "0.1";

my @a = split( "[ \t][ \t]*", $def );
return "Usage: define <name> currentCalculator [device] [watt] [invterval]"
if ( @a < 4 || @a > 5 );

my $name   = $a[0];
my $device = $a[2];
my $watt   = $a[3];

my $interval = 60;
$interval = $a[4] if ( $interval < 60 );

$hash->{NAME}     = $name;
$hash->{DEVICE}   = $device;
$hash->{STATE}    = "Active";
$hash->{INTERVAL} = $interval;
$hash->{WATT}     = $watt;
 
  Log3 $name, 3, "[currentCalculator v".$version." initialisiert]";
 
return undef;
}

sub currentCalculator_Set() {}
sub currentCalculator_Get() {}
sub currentCalculator_Undefine($) {
my ($hash) = @_;
RemoveInternalTimer($hash->{NAME});

return undef;
}

sub currentCalculator_NotifyFn($$) {
my ( $hash, $dev ) = @_;

return if($dev->{NAME} ne $hash->{DEVICE});

my $name   = $hash->{NAME};
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

#----- Untoggle Fix-----#
if ( Value( $device ) eq "toggle" ) {
if ( OldValue( $device ) eq "off" ) {
fhem("set $device on");
}
else {
fhem("set $device off");
}
}

my $on = "";

if( Value($device) eq "on" ) {
currentCalculator_Run($hash);
}
elsif ( Value($device) eq "off" ) {
currentCalculator_Berechnen( $hash, $device, $watt );
currentCalculator_setReading( $device, "on", 0 );
currentCalculator_setReading( $device, "watt", 0 );
RemoveInternalTimer($hash->{NAME});
}
else {
Log3 $name, 3, "Untoggle Problem";
}
return undef;
}

#-----     Stromverbrauch Startzeit setzen     -----#
sub currentCalculator_Run($){
my ($hash) = @_;

my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

#Log3 $device, 3, "device:".$device.", Watt:".$watt.", cc_Run";

my $on = int( time() );

currentCalculator_setReading( $device, "on",    $on );
currentCalculator_setReading( $device, "power", $watt );

currentCalculator_Berechnen($hash,$device,$watt);

RemoveInternalTimer($hash->{NAME});
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "currentCalculator_Berechnen",$hash, 0);

Log3 $device, 3, "[currentCalculator] cc_Run";
}

#-----     Stromverbrauch berechnen     -----#
sub currentCalculator_Berechnen($$$) {
my ($hash) = @_;
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

my $on               = "";
my $off              = 0;
my $onLast           = 0;
my $consumptionLast  = 0;
my $onTotal          = 0;
my $consumptionTotal = 0;

Log3 $device, 3, "[currentCalculator] cc_Berechnen";

$on = ReadingsVal( $device, "on", "0" );
$off = int( time() );

$onLast = $off - $on;

$onTotal          = ReadingsVal( $device, "onTotal",          "0" );
$consumptionTotal = ReadingsVal( $device, "consumptionTotal", "0" );
$onTotal          = int( $onTotal + $onLast );

$consumptionLast  = $onLast * $watt / 1000 / 3600;
$consumptionTotal = $consumptionTotal + $consumptionLast;

$consumptionTotal = sprintf "%.2f", $consumptionTotal;

  #Log3 $device, 3, "Device:".$device.", On:".$on.", Off:".$off;

currentCalculator_setReading( $device, "on",      $on );
currentCalculator_setReading( $device, "off",     $off );
currentCalculator_setReading( $device, "onLast",  $onLast );
currentCalculator_setReading( $device, "onTotal", $onTotal );
currentCalculator_setReading( $device, "power",   "0" );
currentCalculator_setReading( $device, "consumptionTotal", $consumptionTotal );
}

#-----     setReading     -----#

#Log3 $device, 3, "device:".$device.", readingsName:".$readingsName.", readingsWert:".$readingsName.", cc_setReading";
sub currentCalculator_setReading($$$) {
my $device       = shift;
my $readingsName = shift;
my $readingsWert = shift;

Log3 $device, 3, "[currentCalculator] cc_setReading";

readingsBeginUpdate($main::defs{$device});
readingsBulkUpdate( $main::defs{$device}, $readingsName, $readingsWert );
readingsEndUpdate( $main::defs{$device}, 1 );
}

1;


Wenn ich nun das "überwachte" device on schalte werden die readings gesetzt und 1 min pausiert. Bis hier hin passt's. Ab der 2. minute gehts aber wieder rund, sprich endlosschleife.

2013.12.29 23:15:46.655 3: [currentCalculator v0.1 initialisiert]
2013.12.29 23:16:11.539 3: FS20 set wzDeckenfluter on
2013.12.29 23:16:11.820 3: [currentCalculator] cc_setReading
2013.12.29 23:16:11.823 3: [currentCalculator] cc_setReading
2013.12.29 23:16:11.826 3: [currentCalculator] cc_Berechnen
2013.12.29 23:16:11.828 3: [currentCalculator] cc_setReading
2013.12.29 23:16:11.832 3: [currentCalculator] cc_setReading
2013.12.29 23:16:11.835 3: [currentCalculator] cc_setReading
2013.12.29 23:16:11.838 3: [currentCalculator] cc_setReading
2013.12.29 23:16:11.842 3: [currentCalculator] cc_setReading
2013.12.29 23:16:11.845 3: [currentCalculator] cc_setReading
2013.12.29 23:16:11.849 3: [currentCalculator] cc_Run
2013.12.29 23:17:11.854 3: [currentCalculator] cc_Berechnen
2013.12.29 23:17:11.856 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.106 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.109 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.112 3: [currentCalculator] cc_Berechnen
2013.12.29 23:17:12.114 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.117 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.120 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.123 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.127 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.130 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.134 3: [currentCalculator] cc_Run
2013.12.29 23:17:12.210 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.432 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.435 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.438 3: [currentCalculator] cc_Berechnen
2013.12.29 23:17:12.439 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.442 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.445 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.448 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.451 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.454 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.458 3: [currentCalculator] cc_Run
2013.12.29 23:17:12.529 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.747 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.750 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.753 3: [currentCalculator] cc_Berechnen
2013.12.29 23:17:12.754 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.758 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.761 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.763 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.766 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.769 3: [currentCalculator] cc_setReading
2013.12.29 23:17:12.773 3: [currentCalculator] cc_Run
2013.12.29 23:17:12.847 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.056 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.060 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.062 3: [currentCalculator] cc_Berechnen
2013.12.29 23:17:13.064 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.067 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.070 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.072 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.075 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.078 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.082 3: [currentCalculator] cc_Run
2013.12.29 23:17:13.154 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.365 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.368 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.371 3: [currentCalculator] cc_Berechnen
2013.12.29 23:17:13.373 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.376 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.379 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.381 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.384 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.387 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.391 3: [currentCalculator] cc_Run
2013.12.29 23:17:13.464 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.672 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.675 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.677 3: [currentCalculator] cc_Berechnen
2013.12.29 23:17:13.679 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.682 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.686 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.689 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.691 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.694 3: [currentCalculator] cc_setReading
2013.12.29 23:17:13.698 3: [currentCalculator] cc_Run


Woran kann das liegen?


Grüße
Titel: Antw:Script in Modul &quot;umwandeln&quot;
Beitrag von: justme1968 am 29 Dezember 2013, 23:30:42
du darfst das run nur aufrufen wenn dein device von off auf on wechselt. sonst nicht.

du rufst es bei jedem notify auf das dein device betrifft. also auch z.b. wenn nach der ersten minute das verbrauchs reading geschrieben wird.

gruss
  andre
Titel: Antw:Script in Modul &quot;umwandeln&quot;
Beitrag von: fhainz am 29 Dezember 2013, 23:34:06
Zitat von: justme1968 am 29 Dezember 2013, 23:30:42
du darfst das run nur aufrufen wenn dein device von off auf on wechselt. sonst nicht.

currentCalculator_Run wird nur hier aufgerufen:
if( Value($device) eq "on" ) {
currentCalculator_Run($hash);
}


Grüße
Titel: Antw:Script in Modul &quot;umwandeln&quot;
Beitrag von: justme1968 am 29 Dezember 2013, 23:35:49
ja. immer wenn das device on ist. du darfst es aber nur genau dann ein mal aufrufen wenn es eingeschaltet wird. nicht wenn es schon an ist.
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 29 Dezember 2013, 23:48:48
Ok, klar die notifyFn wird ja immer aufgerufen.

Wie schaff ich es zu prüfen ob die run schonmal gelaufen ist? Ein reading setzen das run auf 1 setzt und das jedes mal abfragen? Da gibts sicher ne einfachere Lösung oder?

Grüße
Titel: Antw:Script in Modul &quot;umwandeln&quot;
Beitrag von: justme1968 am 29 Dezember 2013, 23:51:08
es muss kein reading sein. eine interne Variable reicht. z.b. $hash->{running}

du kannst aber auch schauen ob das device vorher aus war.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 30 Dezember 2013, 00:30:28
Jetzt werden nach 2 Wiederholung keine Readings mehr gesetzt. Vermute mal das Modul stoppt irgendwie. Fehler gibts keinen. Hast du noch eine Idee?

package main;

use strict;
use warnings;
use Time::HiRes qw(gettimeofday sleep);

sub currentCalculator_Initialize($) {
my ($hash) = @_;

$hash->{GetFn}   = "currentCalculator_Get";
$hash->{SetFn}   = "currentCalculator_Set";
$hash->{DefFn}   = "currentCalculator_Define";
$hash->{UndefFn} = "currentCalculator_Undefine";
$hash->{NotifyFn} = "currentCalculator_NotifyFn";
}

#####################################

sub currentCalculator_Define($$) {
my ( $hash, $def ) = @_;

my $version = "0.1";

my @a = split( "[ \t][ \t]*", $def );
return "Usage: define <name> currentCalculator [device] [watt] [invterval]"
if ( @a < 4 || @a > 5 );

my $name   = $a[0];
my $device = $a[2];
my $watt   = $a[3];

my $interval = 60;
$interval = $a[4] if ( $interval < 60 );

$hash->{NAME}     = $name;
$hash->{DEVICE}   = $device;
$hash->{STATE}    = "Active";
$hash->{INTERVAL} = $interval;
$hash->{WATT}     = $watt;
 
  Log3 $name, 3, "[currentCalculator v".$version." initialisiert]";
 
return undef;
}

sub currentCalculator_Set() {}
sub currentCalculator_Get() {}
sub currentCalculator_Undefine($) {
my ($hash) = @_;
RemoveInternalTimer($hash->{NAME});

return undef;
}

sub currentCalculator_NotifyFn($$) {
my ( $hash, $dev ) = @_;

return if($dev->{NAME} ne $hash->{DEVICE});

my $name   = $hash->{NAME};
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

#----- Untoggle Fix-----#
if ( Value( $device ) eq "toggle" ) {
if ( OldValue( $device ) eq "off" ) {
fhem("set $device on");
}
else {
fhem("set $device off");
}
}

my $on = "";

if( Value($device) eq "on") {
if( $hash->{running} <= 0)
{
$hash->{running} = 1;
currentCalculator_Run($hash);
}

}
elsif ( Value($device) eq "off" ) {
currentCalculator_Berechnen( $hash, $device, $watt );
currentCalculator_setReading( $device, "on", 0 );
currentCalculator_setReading( $device, "power", 0 );
RemoveInternalTimer($hash->{NAME});
$hash->{running} = 0;
}
else {
Log3 $name, 3, "Untoggle Problem";
}
return undef;
}

#-----     Stromverbrauch Startzeit setzen     -----#
sub currentCalculator_Run($){
my ($hash) = @_;

my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

#Log3 $device, 3, "device:".$device.", Watt:".$watt.", cc_Run";

my $on = int( time() );

currentCalculator_setReading( $device, "on",    $on );
currentCalculator_setReading( $device, "power", $watt );

currentCalculator_Berechnen($hash,$device,$watt);

RemoveInternalTimer($hash->{NAME});
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "currentCalculator_Berechnen",$hash, 0);

Log3 $device, 3, "[currentCalculator] cc_Run";
}

#-----     Stromverbrauch berechnen     -----#
sub currentCalculator_Berechnen($$$) {
my ($hash) = @_;
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

my $on               = "";
my $off              = 0;
my $onLast           = 0;
my $consumptionLast  = 0;
my $onTotal          = 0;
my $consumptionTotal = 0;

Log3 $device, 3, "[currentCalculator] cc_Berechnen";

$on = ReadingsVal( $device, "on", "0" );
$off = int( time() );

$onLast = $off - $on;

$onTotal          = ReadingsVal( $device, "onTotal",          "0" );
$consumptionTotal = ReadingsVal( $device, "consumptionTotal", "0" );
$onTotal          = int( $onTotal + $onLast );

$consumptionLast  = $onLast * $watt / 1000 / 3600;
$consumptionTotal = $consumptionTotal + $consumptionLast;

$consumptionTotal = sprintf "%.2f", $consumptionTotal;

  #Log3 $device, 3, "Device:".$device.", On:".$on.", Off:".$off;

currentCalculator_setReading( $device, "on",      $on );
currentCalculator_setReading( $device, "off",     $off );
currentCalculator_setReading( $device, "onLast",  $onLast );
currentCalculator_setReading( $device, "onTotal", $onTotal );
currentCalculator_setReading( $device, "consumptionTotal", $consumptionTotal );
}

#-----     setReading     -----#

#Log3 $device, 3, "device:".$device.", readingsName:".$readingsName.", readingsWert:".$readingsName.", cc_setReading";
sub currentCalculator_setReading($$$) {
my $device       = shift;
my $readingsName = shift;
my $readingsWert = shift;

Log3 $device, 3, "[currentCalculator] cc_setReading";

readingsBeginUpdate($main::defs{$device});
readingsBulkUpdate( $main::defs{$device}, $readingsName, $readingsWert );
readingsEndUpdate( $main::defs{$device}, 1 );
}

1;


2013.12.30 00:20:11.775 3: FS20 set wzDeckenfluter on
2013.12.30 00:20:11.989 3: [currentCalculator] cc_setReading
2013.12.30 00:20:11.992 3: [currentCalculator] cc_setReading
2013.12.30 00:20:11.994 3: [currentCalculator] cc_Berechnen
2013.12.30 00:20:11.996 3: [currentCalculator] cc_setReading
2013.12.30 00:20:11.999 3: [currentCalculator] cc_setReading
2013.12.30 00:20:12.001 3: [currentCalculator] cc_setReading
2013.12.30 00:20:12.004 3: [currentCalculator] cc_setReading
2013.12.30 00:20:12.007 3: [currentCalculator] cc_setReading
2013.12.30 00:20:12.011 3: [currentCalculator] cc_Run
2013.12.30 00:21:12.014 3: [currentCalculator] cc_Berechnen
2013.12.30 00:21:12.016 3: [currentCalculator] cc_setReading
2013.12.30 00:21:12.344 3: [currentCalculator] cc_setReading
2013.12.30 00:21:12.622 3: [currentCalculator] cc_setReading
2013.12.30 00:21:12.887 3: [currentCalculator] cc_setReading
2013.12.30 00:21:13.153 3: [currentCalculator] cc_setReading
2013.12.30 00:25:06.313 3: FS20 set wzDeckenfluter on
2013.12.30 00:25:29.827 3: FS20 set wzDeckenfluter off
2013.12.30 00:25:30.103 3: [currentCalculator] cc_Berechnen
2013.12.30 00:25:30.105 3: [currentCalculator] cc_setReading
2013.12.30 00:25:30.108 3: [currentCalculator] cc_setReading
2013.12.30 00:25:30.111 3: [currentCalculator] cc_setReading
2013.12.30 00:25:30.115 3: [currentCalculator] cc_setReading
2013.12.30 00:25:30.118 3: [currentCalculator] cc_setReading
2013.12.30 00:25:30.121 3: [currentCalculator] cc_setReading
2013.12.30 00:25:30.124 3: [currentCalculator] cc_setReading
2013.12.30 00:25:37.519 3: FS20 set wzDeckenfluter on
2013.12.30 00:25:37.767 3: [currentCalculator] cc_setReading
2013.12.30 00:25:37.770 3: [currentCalculator] cc_setReading
2013.12.30 00:25:37.773 3: [currentCalculator] cc_Berechnen
2013.12.30 00:25:37.774 3: [currentCalculator] cc_setReading
2013.12.30 00:25:37.777 3: [currentCalculator] cc_setReading
2013.12.30 00:25:37.780 3: [currentCalculator] cc_setReading
2013.12.30 00:25:37.783 3: [currentCalculator] cc_setReading
2013.12.30 00:25:37.786 3: [currentCalculator] cc_setReading
2013.12.30 00:25:37.789 3: [currentCalculator] cc_Run
2013.12.30 00:26:37.800 3: [currentCalculator] cc_Berechnen
2013.12.30 00:26:37.801 3: [currentCalculator] cc_setReading
2013.12.30 00:26:38.118 3: [currentCalculator] cc_setReading
2013.12.30 00:26:38.423 3: [currentCalculator] cc_setReading
2013.12.30 00:26:38.689 3: [currentCalculator] cc_setReading
2013.12.30 00:26:38.958 3: [currentCalculator] cc_setReading


Grüße
Titel: Antw:Script in Modul &quot;umwandeln&quot;
Beitrag von: justme1968 am 30 Dezember 2013, 00:31:08
hatte ich dir das eigentlich schon gezeigt: http://www.fhemwiki.de/wiki/HourCounter ?

wenn es nicht schon macht was du willst hilft es bestimmt mal rein zu schauen.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 30 Dezember 2013, 00:37:57
Ich kenne das Modul danke. John hat es auch hier schon auf der ersten Seite erwähnt. Aber ich will mit diesem Modul lernen wie man ein Modul schreibt ;) Hatte es vorher schon so in php programmiert (anderes Haussteuerungsystem) und perl sagt mir bisher sehr sehr wenig.

Deshalb strapazier ich hier deine nerven so ;)

Grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 30 Dezember 2013, 10:35:55
du musst InternalTimer für run aufrufen. nur für berechne.

gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 30 Dezember 2013, 11:34:28
Hallo!
Zitat von: justme1968 am 30 Dezember 2013, 10:35:55
du musst InternalTimer für run aufrufen. nur für berechne.

Sry ich versteh nicht was du meinst.

Ich hab jetzt das Aufrufen der Berechnung in der Run auskommentiert und einen zweiten Timer in der cc_berechnen() gesetzt, der wenn $hash->{running} > 0 ist, cc_berechnen() alle x Sekunden wieder startet. Das klappt.
Wenn ich dann aber das Device off schalte werden die readings richtig gesetzt, aber nach ca. 30 Sekunden wird die cc_berechnen() nochmals aufgerufen, obwohl $hash->{running} schon 0 ist.

package main;

use strict;
use warnings;
use Time::HiRes qw(gettimeofday sleep);

sub currentCalculator_Initialize($) {
my ($hash) = @_;

$hash->{GetFn}   = "currentCalculator_Get";
$hash->{SetFn}   = "currentCalculator_Set";
$hash->{DefFn}   = "currentCalculator_Define";
$hash->{UndefFn} = "currentCalculator_Undefine";
$hash->{NotifyFn} = "currentCalculator_NotifyFn";
}

#####################################

sub currentCalculator_Define($$) {
my ( $hash, $def ) = @_;

my $version = "0.1";

my @a = split( "[ \t][ \t]*", $def );
return "Usage: define <name> currentCalculator [device] [watt] [invterval]"
if ( @a < 4 || @a > 5 );

my $name   = $a[0];
my $device = $a[2];
my $watt   = $a[3];

my $interval = 60;
$interval = $a[4] if ( $interval < 60 );

$hash->{NAME}     = $name;
$hash->{DEVICE}   = $device;
$hash->{STATE}    = "Active";
$hash->{INTERVAL} = $interval;
$hash->{WATT}     = $watt;
 
  Log3 $name, 3, "[currentCalculator v".$version." initialisiert]";
 
return undef;
}

sub currentCalculator_Set() {}
sub currentCalculator_Get() {}
sub currentCalculator_Undefine($) {
my ($hash) = @_;
RemoveInternalTimer($hash->{NAME});

return undef;
}

sub currentCalculator_NotifyFn($$) {
my ( $hash, $dev ) = @_;

return if($dev->{NAME} ne $hash->{DEVICE});

my $name   = $hash->{NAME};
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

#----- Untoggle Fix-----#
if ( Value( $device ) eq "toggle" ) {
if ( OldValue( $device ) eq "off" ) {
fhem("set $device on");
}
else {
fhem("set $device off");
}
}

my $on = "";

if( Value($device) eq "on") {
if( $hash->{running} <= 0)
{
$hash->{running} = 1;
currentCalculator_Run($hash);
}

}
elsif ( Value($device) eq "off" ) {
if( $hash->{running} > 0)
{
$hash->{running} = 0;

my $on = ReadingsVal( $device, "on", "0" );
my $off = int( time() );
my $onLast = $off - $on;

currentCalculator_setReading( $device, "off", $off );

currentCalculator_Berechnen( $hash, $device, $watt );

currentCalculator_setReading( $device, "on", 0 );
currentCalculator_setReading( $device, "onNow", 0 );
currentCalculator_setReading( $device, "power", 0 );
currentCalculator_setReading( $device, "onLast", $onLast );

RemoveInternalTimer($hash->{NAME});
}
}
else {
Log3 $name, 3, "[currentCalculator] Kein on/off state";
}
return undef;
}

#-----     Stromverbrauch Startzeit setzen     -----#
sub currentCalculator_Run($){
my ($hash) = @_;

my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

my $on = int( time() );

currentCalculator_setReading( $device, "on",    $on );
currentCalculator_setReading( $device, "power", $watt );

#currentCalculator_Berechnen($hash,$device,$watt);

RemoveInternalTimer($hash->{NAME});
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "currentCalculator_Berechnen",$hash, 0);

Log3 $device, 3, "[currentCalculator] cc_Run";
}

#-----     Stromverbrauch berechnen     -----#
sub currentCalculator_Berechnen($$$) {
my ($hash) = @_;
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

my $on               = "";
my $off              = 0;
my $onNow            = 0;
my $consumptionLast  = 0;
my $onTotal          = 0;
my $consumptionTotal = 0;

Log3 $device, 3, "[currentCalculator] cc_Berechnen";

$on = ReadingsVal( $device, "on", "0" );
$off = int( time() );

$onNow = $off - $on;

$onTotal          = ReadingsVal( $device, "onTotal",          "0" );
$consumptionTotal = ReadingsVal( $device, "consumptionTotal", "0" );
$onTotal          = int( $onTotal + $onNow );

$consumptionLast  = $onNow * $watt / 1000 / 3600;
$consumptionTotal = $consumptionTotal + $consumptionLast;

$consumptionTotal = sprintf "%.2f", $consumptionTotal;

currentCalculator_setReading( $device, "on",      $on );
currentCalculator_setReading( $device, "onNow",  $onNow );
currentCalculator_setReading( $device, "onTotal", $onTotal );
currentCalculator_setReading( $device, "consumptionTotal", $consumptionTotal );

if( $hash->{running} > 0 ) {
RemoveInternalTimer($hash->{NAME});
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "currentCalculator_Berechnen",$hash, 0);
}
}

#-----     setReading     -----#

sub currentCalculator_setReading($$$) {
my $device       = shift;
my $readingsName = shift;
my $readingsWert = shift;

Log3 $device, 3, "[currentCalculator] cc_setReading";

readingsBeginUpdate($main::defs{$device});
readingsBulkUpdate( $main::defs{$device}, $readingsName, $readingsWert );
readingsEndUpdate( $main::defs{$device}, 1 );
}

1;


Log on:
2013.12.30 11:15:21.793 3: FS20 set wzDeckenfluter on
2013.12.30 11:15:21.994 3: [currentCalculator] cc_setReading
2013.12.30 11:15:21.997 3: [currentCalculator] cc_setReading
2013.12.30 11:15:22.001 3: [currentCalculator] cc_Run
2013.12.30 11:15:37.255 3: FS20 set wzDeckenfluter off
2013.12.30 11:15:37.502 3: [currentCalculator] cc_setReading
2013.12.30 11:15:37.505 3: [currentCalculator] cc_Berechnen
2013.12.30 11:15:37.507 3: [currentCalculator] cc_setReading
2013.12.30 11:15:37.511 3: [currentCalculator] cc_setReading
2013.12.30 11:15:37.514 3: [currentCalculator] cc_setReading
2013.12.30 11:15:37.518 3: [currentCalculator] cc_setReading
2013.12.30 11:15:37.521 3: [currentCalculator] cc_setReading
2013.12.30 11:15:37.524 3: [currentCalculator] cc_setReading
2013.12.30 11:15:37.526 3: [currentCalculator] cc_setReading
2013.12.30 11:15:37.529 3: [currentCalculator] cc_setReading
2013.12.30 11:16:22.005 3: [currentCalculator] cc_Berechnen
2013.12.30 11:16:22.006 3: [currentCalculator] cc_setReading
2013.12.30 11:16:22.259 3: [currentCalculator] cc_setReading
2013.12.30 11:16:22.528 3: [currentCalculator] cc_setReading
2013.12.30 11:16:22.788 3: [currentCalculator] cc_setReading
2013.12.30 11:18:49.686 3: FS20 set wzDeckenfluter on
2013.12.30 11:18:49.920 3: [currentCalculator] cc_setReading
2013.12.30 11:18:49.923 3: [currentCalculator] cc_setReading
2013.12.30 11:18:49.928 3: [currentCalculator] cc_Run
2013.12.30 11:18:57.067 3: FHT8V set szStellventil valve 7
2013.12.30 11:19:49.932 3: [currentCalculator] cc_Berechnen
2013.12.30 11:19:49.934 3: [currentCalculator] cc_setReading
2013.12.30 11:19:50.226 3: [currentCalculator] cc_setReading
2013.12.30 11:19:50.514 3: [currentCalculator] cc_setReading
2013.12.30 11:19:50.758 3: [currentCalculator] cc_setReading
2013.12.30 11:20:51.013 3: [currentCalculator] cc_Berechnen
2013.12.30 11:20:51.015 3: [currentCalculator] cc_setReading
2013.12.30 11:20:51.321 3: [currentCalculator] cc_setReading
2013.12.30 11:20:51.562 3: [currentCalculator] cc_setReading
2013.12.30 11:20:51.806 3: [currentCalculator] cc_setReading
2013.12.30 11:21:52.053 3: [currentCalculator] cc_Berechnen
2013.12.30 11:21:52.055 3: [currentCalculator] cc_setReading
2013.12.30 11:21:52.344 3: [currentCalculator] cc_setReading
2013.12.30 11:21:52.643 3: [currentCalculator] cc_setReading
2013.12.30 11:21:52.886 3: [currentCalculator] cc_setReading
2013.12.30 11:22:53.140 3: [currentCalculator] cc_Berechnen
2013.12.30 11:22:53.142 3: [currentCalculator] cc_setReading
2013.12.30 11:22:53.435 3: [currentCalculator] cc_setReading
2013.12.30 11:22:53.710 3: [currentCalculator] cc_setReading
2013.12.30 11:22:53.949 3: [currentCalculator] cc_setReading


Log off:
2013.12.30 11:27:26.320 3: FS20 set wzDeckenfluter off
2013.12.30 11:27:26.536 3: [currentCalculator] cc_setReading
2013.12.30 11:27:26.539 3: [currentCalculator] cc_Berechnen
2013.12.30 11:27:26.541 3: [currentCalculator] cc_setReading
2013.12.30 11:27:26.544 3: [currentCalculator] cc_setReading
2013.12.30 11:27:26.546 3: [currentCalculator] cc_setReading
2013.12.30 11:27:26.549 3: [currentCalculator] cc_setReading
2013.12.30 11:27:26.552 3: [currentCalculator] cc_setReading
2013.12.30 11:27:26.555 3: [currentCalculator] cc_setReading
2013.12.30 11:27:26.558 3: [currentCalculator] cc_setReading
2013.12.30 11:27:26.560 3: [currentCalculator] cc_setReading
2013.12.30 11:28:09.129 3: [currentCalculator] cc_Berechnen
2013.12.30 11:28:09.131 3: [currentCalculator] cc_setReading
2013.12.30 11:28:09.432 3: [currentCalculator] cc_setReading
2013.12.30 11:28:09.722 3: [currentCalculator] cc_setReading
2013.12.30 11:28:09.978 3: [currentCalculator] cc_setReading


Hast du noch Idee?


Grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: justme1968 am 30 Dezember 2013, 11:43:11
du brauchst nur einen timer. aber die funktion die du per timer aufrufst muss den timer immer wieder starten weil der timer sonst nur ein mal aufgerufen wird.

die logik sollte etwa so sein:


gruss
  andre
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 30 Dezember 2013, 12:18:11
Ich verstehs nicht... ich denke ich hab alle deine punkte eingebaut aber das off klappt immer noch nicht.

Das run() wird auch aufgerufen wenn das device off ist. Aber warum? Das ist doch eine if davor die checkt ob $hash->{DEVICE} off ist.

package main;

use strict;
use warnings;
use Time::HiRes qw(gettimeofday sleep);

sub currentCalculator_Initialize($) {
my ($hash) = @_;

$hash->{GetFn}   = "currentCalculator_Get";
$hash->{SetFn}   = "currentCalculator_Set";
$hash->{DefFn}   = "currentCalculator_Define";
$hash->{UndefFn} = "currentCalculator_Undefine";
$hash->{NotifyFn} = "currentCalculator_NotifyFn";
}

#####################################

sub currentCalculator_Define($$) {
my ( $hash, $def ) = @_;

my $version = "0.1";

my @a = split( "[ \t][ \t]*", $def );
return "Usage: define <name> currentCalculator [device] [watt] [invterval]"
if ( @a < 4 || @a > 5 );

my $name   = $a[0];
my $device = $a[2];
my $watt   = $a[3];

my $interval = 60;
$interval = $a[4] if ( $interval < 60 );

$hash->{NAME}     = $name;
$hash->{DEVICE}   = $device;
$hash->{STATE}    = "Active";
$hash->{INTERVAL} = $interval;
$hash->{WATT}     = $watt;
 
  Log3 $name, 3, "[currentCalculator v".$version." initialisiert]";
 
return undef;
}

sub currentCalculator_Set() {}
sub currentCalculator_Get() {}
sub currentCalculator_Undefine($) {
my ($hash) = @_;
RemoveInternalTimer($hash->{NAME});

return undef;
}

sub currentCalculator_NotifyFn($$) {
my ( $hash, $dev ) = @_;

return if($dev->{NAME} ne $hash->{DEVICE});

my $name   = $hash->{NAME};
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

#----- Untoggle Fix-----#
if ( Value( $device ) eq "toggle" ) {
if ( OldValue( $device ) eq "off" ) {
fhem("set $device on");
}
else {
fhem("set $device off");
}
}

my $on = "";

if( Value($device) eq "on") {
if( $hash->{running} == 0)
{
currentCalculator_Run($hash);
}

}
elsif( Value($device) eq "off" ) {
if( $hash->{running} == 1)
{
$hash->{running} = 0;
RemoveInternalTimer($hash->{NAME});

my $on = ReadingsVal( $device, "on", "0" );
my $off = int( time() );
my $onLast = $off - $on;

currentCalculator_setReading( $device, "off", $off );

currentCalculator_Berechnen( $hash, $device, $watt );

currentCalculator_setReading( $device, "on", 0 );
currentCalculator_setReading( $device, "onNow", 0 );
currentCalculator_setReading( $device, "power", 0 );
currentCalculator_setReading( $device, "onLast", $onLast );
}
}
else {
Log3 $name, 3, "[currentCalculator] Kein on/off state";
}
return undef;
}

#-----     Stromverbrauch Run setzen     -----#
sub currentCalculator_Run($){
my ($hash) = @_;

my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

Log3 $device, 3, "[currentCalculator] cc_Run";

if( $hash->{running} <= 0 )
{
$hash->{running} = 1;
my $on = int( time() );

currentCalculator_setReading( $device, "on",    $on );
currentCalculator_setReading( $device, "power", $watt );
}

currentCalculator_Berechnen($hash,$device,$watt);

RemoveInternalTimer($hash->{NAME});
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "currentCalculator_Run",$hash, 0);
}

#-----     Stromverbrauch berechnen     -----#
sub currentCalculator_Berechnen($$$) {
my ($hash) = @_;
my $device = $hash->{DEVICE};
my $watt = $hash->{WATT};

my $on               = "";
my $now              = 0;
my $onNow            = 0;
my $consumptionLast  = 0;
my $onTotal          = 0;
my $consumptionTotal = 0;

Log3 $device, 3, "[currentCalculator] cc_Berechnen";

$on = ReadingsVal( $device, "on", "0" );
$now = int( time() );

$onNow = $now - $on;

$onTotal          = ReadingsVal( $device, "onTotal",          "0" );
$consumptionTotal = ReadingsVal( $device, "consumptionTotal", "0" );
$onTotal          = int( $onTotal + $onNow );

$consumptionLast  = $onNow * $watt / 1000 / 3600;
$consumptionTotal = $consumptionTotal + $consumptionLast;

$consumptionTotal = sprintf "%.2f", $consumptionTotal;

currentCalculator_setReading( $device, "on",      $on );
currentCalculator_setReading( $device, "onNow",  $onNow );
currentCalculator_setReading( $device, "onTotal", $onTotal );
currentCalculator_setReading( $device, "consumptionTotal", $consumptionTotal );

}

#-----     setReading     -----#

sub currentCalculator_setReading($$$) {
my $device       = shift;
my $readingsName = shift;
my $readingsWert = shift;

Log3 $device, 3, "[currentCalculator] cc_setReading";

readingsBeginUpdate($main::defs{$device});
readingsBulkUpdate( $main::defs{$device}, $readingsName, $readingsWert );
readingsEndUpdate( $main::defs{$device}, 1 );
}

1;


Log:
2013.12.30 12:16:11.645 3: FS20 set wzDeckenfluter off
2013.12.30 12:16:11.855 3: [currentCalculator] cc_setReading
2013.12.30 12:16:11.858 3: [currentCalculator] cc_Berechnen
2013.12.30 12:16:11.860 3: [currentCalculator] cc_setReading
2013.12.30 12:16:11.863 3: [currentCalculator] cc_setReading
2013.12.30 12:16:11.866 3: [currentCalculator] cc_setReading
2013.12.30 12:16:11.869 3: [currentCalculator] cc_setReading
2013.12.30 12:16:11.872 3: [currentCalculator] cc_setReading
2013.12.30 12:16:11.874 3: [currentCalculator] cc_setReading
2013.12.30 12:16:11.877 3: [currentCalculator] cc_setReading
2013.12.30 12:16:11.880 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.013 3: [currentCalculator] cc_Run
2013.12.30 12:17:05.014 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.260 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.263 3: [currentCalculator] cc_Berechnen
2013.12.30 12:17:05.265 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.268 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.272 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.275 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.279 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.282 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.285 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.289 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.348 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.620 3: [currentCalculator] cc_Berechnen
2013.12.30 12:17:05.622 3: [currentCalculator] cc_setReading
2013.12.30 12:17:05.875 3: [currentCalculator] cc_setReading
2013.12.30 12:17:06.130 3: [currentCalculator] cc_setReading
2013.12.30 12:17:06.392 3: [currentCalculator] cc_setReading


Grüße
Titel: Antw:Script in Modul "umwandeln"
Beitrag von: fhainz am 30 Dezember 2013, 14:28:12
Ich habs :D

Das viele copy & paste war schuld. Ich hab den timer mit InternalTimer(gettimeofday()+$hash->{INTERVAL}, "currentCalculator_Run",$hash, 0); gesetzt, aber mit RemoveInternalTimer($hash->{NAME}); entfernt. Nachdem ich das auf $hash abgeändert hab funktioniert's :D

Vielen vielen Dank für deine Hilfe und Geduld, alleine hätte ich das nie geschafft :)

Hättest du noch ein paar Tipps was am code selbst verbessern könnte? Oder passt das im großen und ganzen so?
z.B das readings setzen, da gibts ja noch andere Lösungen hab ich gesehen. Im pid Modul wird zB das reading mit $pid->{READINGS}{$name}{VAL} = $val; gesetzt. Ich mach das ganz anders, wie hier (http://forum.fhem.de/index.php/topic,13270.msg83082.html#msg83082) von MisterEltako beschrieben.


Grüße
Titel: Antw:Script in Modul &quot;umwandeln&quot;
Beitrag von: justme1968 am 30 Dezember 2013, 14:34:00
du solltest auf jeden fall die readings update funktionen verwenden. das sind die einzigen bei denen die event-on-change & Co gehen, bei denen user readings und notifys gehen. alles andere ist veraltet oder blödsinn :)

es gibt ein paar stellen die noch aufgeräumt werden können. du brauchst z.b. nichts an eine funktion zu übergeben das auch im
hash steckt. das erkenne von ein und aus könnte man verbessern. usw. aber da kommst du sicher voneinander drauf mit der zeit wenn du drüber nachdenkst :)

gruss
  andre