############################################## # $Id$ package main; use strict; use warnings; use POSIX; sub Utils_Initialize($$) { my ($hash) = @_; } sub time_str2num($) { my ($str) = @_; my @a; if($str) { @a = split("[T: -]", $str); return mktime($a[5],$a[4],$a[3],$a[2],$a[1]-1,$a[0]-1900,0,0,-1); } else { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); return mktime($sec, $min, $hour, $mday, $mon, $year, 0, 0, -1); } } sub min($@) { my ($min, @vars) = @_; for (@vars) { $min = $_ if $_ lt $min; } return $min; } sub max($@) { my ($max, @vars) = @_; for (@vars) { $max = $_ if $_ gt $max; } return $max; } sub minNum($@) { my ($min, @vars) = @_; for (@vars) { $min = $_ if $_ < $min; } return $min; } sub maxNum($@) { my ($max, @vars) = @_; for (@vars) { $max = $_ if $_ > $max; } return $max; } sub abstime2rel($) { my ($h,$m,$s) = split(":", shift); $m = 0 if(!$m); $s = 0 if(!$s); my $t1 = 3600*$h+60*$m+$s; my @now = localtime; my $t2 = 3600*$now[2]+60*$now[1]+$now[0]; my $diff = $t1-$t2; $diff += 86400 if($diff <= 0); return sprintf("%02d:%02d:%02d", $diff/3600, ($diff/60)%60, $diff%60); } sub defInfo($;$) { my ($search,$internal) = @_; $internal = 'DEF' unless defined($internal); my @ret; my @etDev = devspec2array($search); foreach my $d (@etDev) { next unless $d; push @ret, $defs{$d}{$internal}; } return @ret; } my ($SVG_lt, $SVG_ltstr); sub SVG_time_to_sec($) { my ($str) = @_; if(!$str) { return 0; } my ($y,$m,$d,$h,$mi,$s) = split("[-_:]", $str); $s = 0 if(!$s); $mi= 0 if(!$mi); $h = 0 if(!$h); $d = 1 if(!$d); $m = 1 if(!$m); if(!$SVG_ltstr || $SVG_ltstr ne "$y-$m-$d-$h") { # 2.5x faster $SVG_lt = mktime(0,0,$h,$d,$m-1,$y-1900,0,0,-1); $SVG_ltstr = "$y-$m-$d-$h"; } return $s+$mi*60+$SVG_lt; } ######## trim ##################################################### # What : cuts blankspaces from the beginning and end of a string # Call : { trim(" Hello ") } # Source: http://www.somacon.com/p114.php , # http://www.fhemwiki.de/wiki/TRIM-Funktion-Anfangs/EndLeerzeichen_aus_Strings_entfernen sub trim($) { my $string = shift; $string =~ s/^\s+//; $string =~ s/\s+$//; return $string; } ######## ltrim #################################################### # What : cuts blankspaces from the beginning of a string # Call : { ltrim(" Hello") } # Source: http://www.somacon.com/p114.php , # http://www.fhemwiki.de/wiki/TRIM-Funktion-Anfangs/EndLeerzeichen_aus_Strings_entfernensub ltrim($) sub ltrim($) { my $string = shift; $string =~ s/^\s+//; return $string; } ######## rtrim #################################################### # What : cuts blankspaces from the end of a string # Call : { rtrim("Hello ") } # Source: http://www.somacon.com/p114.php , # http://www.fhemwiki.de/wiki/TRIM-Funktion-Anfangs/EndLeerzeichen_aus_Strings_entfernensub ltrim($) sub rtrim($) { my $string = shift; $string =~ s/\s+$//; return $string; } ######## UntoggleDirect ########################################### # What : For devices paired directly, converts state 'toggle' into 'on' or 'off' # Call : { UntoggleDirect("myDevice") } # define untoggle_myDevice notify myDevice { UntoggleDirect("myDevice") } # Source: http://www.fhemwiki.de/wiki/FS20_Toggle_Events_auf_On/Off_umsetzen sub UntoggleDirect($) { my ($obj) = shift; Log 4, "UntoggleDirect($obj)"; if (Value($obj) eq "toggle"){ if (OldValue($obj) eq "off") { {fhem ("setstate ".$obj." on")} } else { {fhem ("setstate ".$obj." off")} } } else { {fhem "setstate ".$obj." ".Value($obj)} } } ######## UntoggleIndirect ######################################### # What : For devices paired indirectly, switches the target device 'on' or 'off' also when a 'toggle' was sent from the source device # Call : { UntoggleIndirect("mySensorDevice","myActorDevice","50%") } # define untoggle_mySensorDevice_myActorDevice notify mySensorDevice { UntoggleIndirect("mySensorDevice","myActorDevice","50%%") } # Source: http://www.fhemwiki.de/wiki/FS20_Toggle_Events_auf_On/Off_umsetzen sub UntoggleIndirect($$$) { my ($sender, $actor, $dimvalue) = @_; Log 4, "UntoggleIndirect($sender, $actor, $dimvalue)"; if (Value($sender) eq "toggle") { if (Value($actor) eq "off") {fhem ("set ".$actor." on")} else {fhem ("set ".$actor." off")} } ## workaround for dimming currently not working with indirect pairing ## (http://culfw.de/commandref.html: "TODO/Known BUGS - FS20 dim commands should not repeat.") elsif (Value($sender) eq "dimup") {fhem ("set ".$actor." dim100%")} elsif (Value($sender) eq "dimdown") {fhem ("set ".$actor." ".$dimvalue)} elsif (Value($sender) eq "dimupdown") { if (Value($actor) eq $dimvalue) {fhem ("set ".$actor." dim100%")} ## Heuristic above doesn't work if lamp was dimmed, then switched off, then switched on, because state is "on", but the lamp is actually dimmed. else {fhem ("set ".$actor." ".$dimvalue)} sleep 1; } ## end of workaround else {fhem ("set ".$actor." ".Value($sender))} return; } sub IsInt($) { defined $_[0] && $_[0] =~ /^[+-]?\d+$/; } # Small NC replacement: fhemNc("ip:port", "text", waitForReturn); sub fhemNc($$$) { my ($addr, $txt, $waitForReturn) = @_; my $client = IO::Socket::INET->new(PeerAddr => $addr); return "Can't connect to $addr\n" if(!$client); syswrite($client, $txt); return "" if(!$waitForReturn); my ($ret, $buf) = ("", ""); shutdown($client, 1); alarm(5); while(sysread($client, $buf, 256) > 0) { $ret .= $buf; } alarm(0); close($client); return $ret; } sub round($$) { my($v,$n) = @_; return sprintf("%.${n}f",$v); } 1; =pod =item helper =begin html