diff --git a/fhem/contrib/DS_Starter/60_Watches.pm b/fhem/contrib/DS_Starter/60_Watches.pm index 9912f249b..1b12633c9 100644 --- a/fhem/contrib/DS_Starter/60_Watches.pm +++ b/fhem/contrib/DS_Starter/60_Watches.pm @@ -33,7 +33,6 @@ use strict; use warnings; use Time::HiRes qw(time gettimeofday tv_interval); use GPUtils qw(GP_Import GP_Export); # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt -# use POSIX; eval "use FHEM::Meta;1" or my $modMetaAbsent = 1; ## no critic 'eval' # Run before module compilation @@ -72,6 +71,8 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "0.20.0" => "07.05.2020 asynchron read alarmTime reading, some fixes ", + "0.19.0" => "06.05.2020 alarm event creation for watch models 'Station' and 'Station' ", "0.18.0" => "06.05.2020 attr 'digitalTextTicker' deleted and switched to setter 'textTicker', default text switched to blank ", "0.17.0" => "05.05.2020 new attr 'digitalTextTicker', 'digitalTextDigitNumber' ", "0.16.0" => "04.05.2020 delete attr 'digitalDisplayText', new setter 'displayText', 'displayTextDel' ", @@ -189,7 +190,7 @@ sub Set { ## no critic 'compl $setlist .= "time " if($addp =~ /staticwatch/); $setlist .= "alarmHMSset alarmHMSdel:noArg reset:noArg resume:noArg start:noArg stop:noArg " if($addp =~ /stopwatch|countdownwatch/); $setlist .= "countDownInit " if($addp =~ /countdownwatch/); - # $setlist .= "alarmHMSset alarmHMSdel:noArg " if($addp =~ /\bwatch\b/); + $setlist .= "alarmHMSset alarmHMSdel:noArg " if($addp =~ /\bwatch\b/); $setlist .= "displayTextSet displayTextDel:noArg textTicker:on,off " if($addp eq "text"); if ($opt =~ /\bstart\b/) { @@ -211,8 +212,6 @@ sub Set { ## no critic 'compl my $at = sprintf("%02d",$prop).":".sprintf("%02d",$prop1).":".sprintf("%02d",$prop2); - delReadings ($name, "alarmTime"); - readingsBeginUpdate ($hash); readingsBulkUpdate ($hash, "alarmed", 0); readingsBulkUpdate ($hash, "alarmTime", $at); @@ -299,15 +298,15 @@ sub Attr { # $name is device name # aName and aVal are Attribute name and value - if ($cmd eq "set" && $hash->{MODEL} !~ /modern/i && $aName =~ /^modern.*/) { + if ($cmd eq "set" && $hash->{MODEL} !~ /modern/i && $aName =~ /^modern/) { return qq{"$aName" is only valid for Watches model "Modern"}; } - if ($cmd eq "set" && $hash->{MODEL} !~ /station/i && $aName =~ /^station.*/) { + if ($cmd eq "set" && $hash->{MODEL} !~ /station/i && $aName =~ /^station/) { return qq{"$aName" is only valid for Watches model "Station"}; } - if ($cmd eq "set" && $hash->{MODEL} !~ /digital/i && $aName =~ /^digital.*/) { + if ($cmd eq "set" && $hash->{MODEL} !~ /digital/i && $aName =~ /^digital/) { return qq{"$aName" is only valid for Watches model "Digital"}; } @@ -342,7 +341,7 @@ sub Attr { } if ($cmd eq "set") { - if ($aName eq "digitalTextDigitNumber" && $aVal !~ /^\d+$/x) { + if ($aName eq "digitalTextDigitNumber" && $aVal !~ /^[0-9]+$/x) { return qq{The value of "$aName" is not valid. Only integers are allowed !}; } } @@ -424,37 +423,35 @@ sub digitalWatch { my $adsd = AttrVal($d, "digitalSegmentDistance", 0.5); my $adda = AttrVal($d, "digitalDigitAngle", 9); my $adtdn = AttrVal($d, "digitalTextDigitNumber", 0); + my $tsou = AttrVal($d, "timeSource", "server"); my $deftxt = " "; - my $rdtt = ReadingsVal ($d, "displayTextTicker", "off"); - my $ddt = ReadingsVal ($d, "displayText", $deftxt); - my $alarm = " ".ReadingsVal($d, "alarmTime", "aa:bb:cc"); + my $rdtt = ReadingsVal ($d, "displayTextTicker", "off"); + my $ddt = ReadingsVal ($d, "displayText", $deftxt); + my $alarm = ReadingsVal ($d, "alarmTime", "aa:bb:cc"); my $ddp = "###:##:##"; # dummy my ($h,$m,$s,$txtc) = (0,0,0,0); my $forerun = ""; # init Vorlauf bei Laufschrift + if($addp !~ /text/) { + $ddt = "((hours_$d < 10) ? '0' : '') + hours_$d + ':' + + ((minutes_$d < 10) ? '0' : '') + minutes_$d + ':' + + ((seconds_$d < 10) ? '0' : '') + seconds_$d"; + } + if($addp eq "watch") { $ddp = "###:##:##"; - $ddt = "((hours < 10) ? ' 0' : ' ') + hours - + ':' + ((minutes < 10) ? '0' : '') + minutes - + ':' + ((seconds < 10) ? '0' : '') + seconds"; } elsif ($addp eq "stopwatch" || $addp eq "countdownwatch") { $alarmdef = "aa:bb:cc" if($addp eq "stopwatch"); # Stoppuhr bei Start 00:00:00 nicht Alerm auslösen $ddp = "###:##:##"; - $ddt = "((hours_$d < 10) ? ' 0' : ' ') + hours_$d - + ':' + ((minutes_$d < 10) ? '0' : '') + minutes_$d - + ':' + ((seconds_$d < 10) ? '0' : '') + seconds_$d"; } elsif ($addp eq "staticwatch") { $ddp = "###:##:##"; $h = ReadingsVal($d, "hour" , 0); $m = ReadingsVal($d, "minute", 0); $s = ReadingsVal($d, "second", 0); - $ddt = "((hours_$d < 10) ? ' 0' : ' ') + hours_$d - + ':' + ((minutes_$d < 10) ? '0' : '') + minutes_$d - + ':' + ((seconds_$d < 10) ? '0' : '') + seconds_$d"; } elsif ($addp eq "text") { $txtc = length($ddt); @@ -499,9 +496,10 @@ sub digitalWatch { var minutes_$d; var seconds_$d; var startDate_$d; - var value_$d = ' $deftxt'; // default Digitaltext initialisieren - var tlength_$d = '$txtc'; // Textlänge Digitaltext initialisieren - var tticker_$d = '$rdtt'; // Tickereinstellung initialisieren + var armtime0_$d = '$alarm'; // Alarmzeit initialisieren + var value_$d = ' $deftxt'; // default Digitaltext initialisieren + var tlength_$d = '$txtc'; // Textlänge Digitaltext initialisieren + var tticker_$d = '$rdtt'; // Tickereinstellung initialisieren function SegmentDisplay_$d(displayId_$d) { this.displayId_$d = displayId_$d; @@ -534,7 +532,6 @@ sub digitalWatch { var display_$d = new SegmentDisplay_$d('display_$d'); display_$d.pattern = '$ddp '; // Textschablone initialisieren display_$d.cornerType = 2; - // display_$d.displayType = 7; display_$d.displayAngle = $adda; // Zeichenwinkel: -30 - 30 (9) display_$d.digitHeight = $addh; // Zeichenhöhe: 5 - 50 (20) display_$d.digitWidth = $addw; // Zeichenbreite: 5 - 50 (12) @@ -1094,13 +1091,13 @@ sub digitalWatch { // Check ob Alarm ausgelöst werden soll und ggf. Alarmevent triggern function checkAndDoAlm (acttime) { lastalmtime = localStorage.getItem('lastalmtime_$d'); // letzte Alarmzeit laden - if ( (acttime == '$alarm' || acttime == ' $alarmdef') && acttime != lastalmtime ) { + if ( (acttime == armtime0_$d || acttime == '$alarmdef') && acttime != lastalmtime ) { command = '{ CommandSetReading(undef, \"$d alarmed '+acttime+'\") }'; url_$d = makeCommand(command); localStoreSetLastalm (acttime); // aktuelle Alarmzeit sichern - if(acttime == '$alarm') { + if(acttime == armtime0_$d) { \$.get(url_$d); } else { @@ -1119,20 +1116,33 @@ sub digitalWatch { function animate_$d() { var watchkind_$d = '$addp'; - if (watchkind_$d == 'watch') { - // aktueller Timestamp in Millisekunden - command = '{ int(time*1000) }'; - url_$d = makeCommand(command); - \$.get( url_$d, function (data) { - data = data.replace(/\\n/g, ''); - ct_$d = parseInt(data); return ct_$d; - } - ); - - var time = new Date(ct_$d); - var hours = time.getHours(); - var minutes = time.getMinutes(); - var seconds = time.getSeconds(); + if (watchkind_$d == 'watch') { + // Zeitsteuerung - aktueller Timestamp in Millisekunden + if ('$tsou' == 'server') { // Serverzeit + command = '{ int(time*1000) }'; + url_$d = makeCommand(command); + \$.get( url_$d, function (data) { + data = data.replace(/\\n/g, ''); + ct_$d = parseInt(data); + return ct_$d; + } + ); + + time_$d = new Date(ct_$d); + + } else { + time_$d = new Date(); // Clientzeit + } + + if (typeof ct_$d === 'undefined') { // wenn Zeit noch undef mit lokaler Zeit initialisieren -> springen Zeiger verhindern + time_$d = new Date(); + } else { + time_$d = new Date(ct_$d); + } + + var hours_$d = time_$d.getHours(); + var minutes_$d = time_$d.getMinutes(); + var seconds_$d = time_$d.getSeconds(); } if (watchkind_$d == 'staticwatch') { @@ -1141,10 +1151,8 @@ sub digitalWatch { var seconds_$d = '$s'; } - if (watchkind_$d == 'stopwatch') { - devName_$d = '$d'; - - command = '{ReadingsVal(\"'+devName_$d+'\",\"state\",\"\")}'; + if (watchkind_$d == 'stopwatch') { + command = '{ReadingsVal(\"$d\",\"state\",\"\")}'; // state Reading lesen url_$d = makeCommand(command); \$.get( url_$d, function (data) { state_$d = data.replace(/\\n/g, ''); @@ -1154,11 +1162,19 @@ sub digitalWatch { if (state_$d == 'started' || state_$d == 'resumed') { if (state_$d == 'started') { - localStoreSetLastalm ('NaN'); // letzte Alarmzeit zurücksetzen + localStoreSetLastalm ('NaN'); // letzte Alarmzeit zurücksetzen } + command = '{ReadingsVal(\"$d\",\"alarmTime\",\"+armtime0_$d+\")}'; // alarmTime Reading lesen + url_$d = makeCommand(command); + \$.get( url_$d, function (data) { + armtime0_$d = data.replace(/\\n/g, ''); + return armtime0_$d; + } + ); + // == Startzeit == - command = '{ReadingsNum(\"'+devName_$d+'\",\"starttime\", 0)}'; + command = '{ReadingsNum(\"$d\",\"starttime\", 0)}'; url_$d = makeCommand(command); \$.get( url_$d, function (data) { data = data.replace(/\\n/g, ''); @@ -1169,17 +1185,8 @@ sub digitalWatch { startDate_$d = new Date(st_$d); - // aktueller Timestamp in Millisekunden - command = '{ int(time*1000) }'; - url_$d = makeCommand(command); - \$.get( url_$d, function (data) { - data = data.replace(/\\n/g, ''); - ct_$d = parseInt(data); - return ct_$d; - } - ); - - currDate_$d = new Date(ct_$d); + // aktueller Timestamp in Millisekunden + currDate_$d = new Date(); elapsesec_$d = ((currDate_$d.getTime() - startDate_$d.getTime()))/1000; // vergangene Millisekunden in Sekunden if (state_$d == 'resumed') { @@ -1218,10 +1225,9 @@ sub digitalWatch { } } - if (watchkind_$d == 'countdownwatch') { - devName_$d = '$d'; + if (watchkind_$d == 'countdownwatch') { - command = '{ReadingsVal(\"'+devName_$d+'\",\"state\",\"\")}'; + command = '{ReadingsVal(\"$d\",\"state\",\"\")}'; // state Reading lesen url_$d = makeCommand(command); \$.get( url_$d, function (data) { state_$d = data.replace(/\\n/g, ''); @@ -1231,11 +1237,19 @@ sub digitalWatch { if (state_$d == 'started' || state_$d == 'resumed') { if (state_$d == 'started') { - localStoreSetLastalm ('NaN'); // letzte Alarmzeit zurücksetzen + localStoreSetLastalm ('NaN'); // letzte Alarmzeit zurücksetzen } + command = '{ReadingsVal(\"$d\",\"alarmTime\",\"+armtime0_$d+\")}'; // alarmTime Reading lesen + url_$d = makeCommand(command); + \$.get( url_$d, function (data) { + armtime0_$d = data.replace(/\\n/g, ''); + return armtime0_$d; + } + ); + // == Ermittlung Countdown Startwert == - command = '{ReadingsNum(\"'+devName_$d+'\",\"countInitVal\", 0)}'; + command = '{ReadingsNum(\"$d\",\"countInitVal\", 0)}'; url_$d = makeCommand(command); \$.get( url_$d, function (data) { data = data.replace(/\\n/g, ''); @@ -1251,7 +1265,7 @@ sub digitalWatch { } // == Ermittlung vergangene Sekunden == - command = '{ReadingsNum(\"'+devName_$d+'\",\"starttime\", 0)}'; + command = '{ReadingsNum(\"$d\",\"starttime\", 0)}'; url_$d = makeCommand(command); \$.get( url_$d, function (data) { data = data.replace(/\\n/g, ''); @@ -1262,17 +1276,8 @@ sub digitalWatch { startDate_$d = new Date(st_$d); - // aktueller Timestamp in Millisekunden - command = '{ int(time*1000) }'; - url_$d = makeCommand(command); - \$.get( url_$d, function (data) { - data = data.replace(/\\n/g, ''); - ct_$d = parseInt(data); - return ct_$d; - } - ); - - currDate_$d = new Date(ct_$d); + // aktueller Timestamp in Millisekunden + currDate_$d = new Date(); elapsesec_$d = ((currDate_$d.getTime() - startDate_$d.getTime()))/1000; // vergangene Millisekunden in Sekunden umrechnen // == Countdown errechnen == @@ -1354,7 +1359,7 @@ sub digitalWatch { ); } else { - value_$d = $ddt; + value_$d = ' '+$ddt; if(value_$d == ' undefined:undefined:undefined' || value_$d == ' NaN:NaN:NaN') { value_$d = ' : : '; @@ -1389,6 +1394,8 @@ sub stationWatch { my $sbody = AttrVal($d,"stationBody","Round")."Body"; my $hattr = AttrVal($d,"htmlattr","width='150' height='150'"); my $tsou = AttrVal($d,"timeSource","server"); + + my $alarm = ReadingsVal($d, "alarmTime", "aa:bb:cc"); return " @@ -1399,27 +1406,8 @@ sub stationWatch {