2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-30 05:57:08 +00:00

47_OBIS: Added attribute pollingMode

git-svn-id: https://svn.fhem.de/fhem/trunk@10963 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
icinger 2016-02-29 10:14:12 +00:00
parent 574e904c0e
commit 5a3682e7dd

View File

@ -42,9 +42,8 @@ sub OBIS_Initialize($)
$hash->{ParseFn} = "OBIS_Parse"; $hash->{ParseFn} = "OBIS_Parse";
$hash->{UndefFn} = "OBIS_Undef"; $hash->{UndefFn} = "OBIS_Undef";
$hash->{AttrFn} = "OBIS_Attr"; $hash->{AttrFn} = "OBIS_Attr";
$hash->{AttrList}= "do_not_notify:1,0 interval offset_feed offset_energy IODev channels alignTime ". $hash->{AttrList}= "do_not_notify:1,0 interval offset_feed offset_energy IODev channels alignTime pollingMode:on,off ".
$readingFnAttributes; $readingFnAttributes;
Log3 $hash,4,"OBIS - Initialize done...";
} }
##################################### #####################################
@ -55,7 +54,7 @@ sub OBIS_Define($$)
return 'wrong syntax: define <name> OBIS devicename@baudrate[,databits,parity,stopbits]|none [MeterType]' return 'wrong syntax: define <name> OBIS devicename@baudrate[,databits,parity,stopbits]|none [MeterType]'
if(@a < 3); if(@a < 3);
Log 3,Dumper(%readyfnlist);
DevIo_CloseDev($hash); DevIo_CloseDev($hash);
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
my $name = $a[0]; my $name = $a[0];
@ -86,29 +85,31 @@ sub OBIS_Define($$)
if ($baudrate==4800) {$hash->{helper}{SPEED}="4"} if ($baudrate==4800) {$hash->{helper}{SPEED}="4"}
if ($baudrate==9600) {$hash->{helper}{SPEED}="5"} if ($baudrate==9600) {$hash->{helper}{SPEED}="5"}
my %devs= ( my %devs= (
# Name, Init-String, repeat,2ndInit # Name, Init-String, interval, 2ndInit
"Unknown"=>["", -1, ""], "Unknown"=>["", -1, ""],
"MT681"=>[ "", -1,""],
# Voltcraft VSM 102
"VSM102"=> ["/?!".chr(13).chr(10), 600, chr(6)."0".$hash->{helper}{SPEED}."0".chr(13).chr(10)], "VSM102"=> ["/?!".chr(13).chr(10), 600, chr(6)."0".$hash->{helper}{SPEED}."0".chr(13).chr(10)],
# Landis & Gyr E110
"E110"=> ["/?!".chr(13).chr(10), 600, chr(6)."0".$hash->{helper}{SPEED}."0".chr(13).chr(10)], "E110"=> ["/?!".chr(13).chr(10), 600, chr(6)."0".$hash->{helper}{SPEED}."0".chr(13).chr(10)],
"Hager"=>["",60,""] "Hager"=> ["", 60, ""],
); );
Log3 $hash,4,"OBIS ($name) - Baudrate is $baudrate"; Log3 $hash,4,"OBIS ($name) - Baudrate is $baudrate";
if (!$devs{$type}) {return 'unknown meterType. Must be one of <nothing>, VSM102, E110, Hager'};
$devs{$type}[1] = $hash->{helper}{DEVICES}[1] // $devs{$type}[1];
$hash->{helper}{DEVICES} =$devs{$type}; $hash->{helper}{DEVICES} =$devs{$type};
$hash->{DevioText}="";
$hash->{helper}{TRIGGERTIME}=gettimeofday(); $hash->{helper}{TRIGGERTIME}=gettimeofday();
# Log 3,Dumper($hash->{helper}{DEVICES}); my $t=OBIS_adjustAlign($hash,AttrVal($name,"alignTime",undef),$hash->{helper}{DEVICES}[1]);
my $t=OBIS_adjustAlign($hash,AttrVal($name,"alignTime","00:00"),$hash->{helper}{DEVICES}[1]);
Log3 ($hash,4,"OBIS ($name) - Internal timer set to ".FmtDateTime($t)) if ($hash->{helper}{DEVICES}[1]>0); Log3 ($hash,4,"OBIS ($name) - Internal timer set to ".FmtDateTime($t)) if ($hash->{helper}{DEVICES}[1]>0);
# InternalTimer($t, "GetUpdate", $hash, 0) if ($hash->{helper}{DEVICES}[1]>0); InternalTimer($t, "GetUpdate", $hash, 0) if ($hash->{helper}{DEVICES}[1]>0);
InternalTimer(gettimeofday()+$hash->{helper}{DEVICES}[1], "GetUpdate", $hash, 0) if ($hash->{helper}{DEVICES}[1]>0);
$hash->{helper}{EoM}=-1; $hash->{helper}{EoM}=-1;
Log3 $hash,4,"OBIS ($name) - Opening device..."; Log3 $hash,4,"OBIS ($name) - Opening device...";
$hash->{helper}{FD}= DevIo_OpenDev($hash, 0, "OBIS_Init"); return DevIo_OpenDev($hash, 0, "OBIS_Init");
return undef; # my $fd;
# Log 3,"FD: $fd";
# $hash->{FD}= $fd;
# $hash->{helper}{FD2}=$hash->{FD};
# delete($readyfnlist{"$name.$dev"});
# $selectlist{"$name.$dev"} = $hash;
# return $hash->{FD};
} }
# Update-Routine # Update-Routine
@ -117,29 +118,30 @@ sub GetUpdate($)
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $type= $hash->{MeterType}; my $type= $hash->{MeterType};
RemoveInternalTimer($hash);
# Open dev # Open dev
# if (!$hash->{helper}{FD}) {$hash->{helper}{FD}= DevIo_OpenDev($hash, 0, "OBIS_Init"); # if (!$hash->{helper}{FD}) {$hash->{helper}{FD}= DevIo_OpenDev($hash, 0, "OBIS_Init");
# readingsSingleUpdate($hash, "state","opened",1); # readingsSingleUpdate($hash, "state","opened",1);
# } # }
my $t=OBIS_adjustAlign($hash,AttrVal($name,"alignTime","00:00"),$hash->{helper}{DEVICES}[1]); my $t=OBIS_adjustAlign($hash,AttrVal($name,"alignTime",undef),$hash->{helper}{DEVICES}[1]);
Log3 ($hash,4,"OBIS ($name) - Internal timer set to ".FmtDateTime($t)) if ($hash->{helper}{DEVICES}[1]>0); Log3 ($hash,4,"OBIS ($name) - Internal timer set to ".FmtDateTime($t)) if ($hash->{helper}{DEVICES}[1]>0);
# InternalTimer($t, "GetUpdate", $hash, 1) if ($hash->{helper}{DEVICES}[1]>0); InternalTimer($t, "GetUpdate", $hash, 1) if ($hash->{helper}{DEVICES}[1]>0);
InternalTimer(gettimeofday()+$hash->{helper}{DEVICES}[1], "GetUpdate", $hash, 0) if ($hash->{helper}{DEVICES}[1]>0); # InternalTimer(gettimeofday()+$hash->{helper}{DEVICES}[1], "GetUpdate", $hash, 0) if ($hash->{helper}{DEVICES}[1]>0);
$hash->{helper}{EoM}=-1; $hash->{helper}{EoM}=-1;
if (!exists $hash->{helper}{DEVICES}[1]) {return undef;} if ($hash->{helper}{DEVICES}[1] eq "") {return undef;}
DevIo_SimpleWrite($hash,$hash->{helper}{DEVICES}[0],undef) ; DevIo_SimpleWrite($hash,$hash->{helper}{DEVICES}[0],undef) ;
} }
sub OBIS_Init($) sub OBIS_Init($)
{ {
#nothing here yet #nothing here yet
my ($hash) = @_; # my ($hash) = @_;
my $name = $hash->{NAME}; # my $name = $hash->{NAME};
my $type= $hash->{MeterType}; # my $type= $hash->{MeterType};
my $dev= $hash->{DeviceName}; # my $dev= $hash->{DeviceName};
($dev, undef) = split("@", $dev); # ($dev, undef) = split("@", $dev);
if (!exists $hash->{helper}{DEVICES}[1]) {return undef;} # if ($hash->{helper}{DEVICES}[0] eq "") {return undef;}
DevIo_SimpleWrite($hash,$hash->{helper}{DEVICES}[0],undef) ; # DevIo_SimpleWrite($hash,$hash->{helper}{DEVICES}[0],undef) ;
return undef; return undef;
} }
##################################### #####################################
@ -157,7 +159,6 @@ sub OBIS_Read($)
{ {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $tn = TimeNow();
my $buf = DevIo_SimpleRead($hash); my $buf = DevIo_SimpleRead($hash);
if ($hash->{helper}{EoM}!=1 && $hash->{helper}{DEVICES}[1]>0) {OBIS_Parse($hash,$buf);} if ($hash->{helper}{EoM}!=1 && $hash->{helper}{DEVICES}[1]>0) {OBIS_Parse($hash,$buf);}
@ -250,13 +251,16 @@ sub OBIS_Parse($$)
sub OBIS_Ready($) sub OBIS_Ready($)
{ {
my ($hash) = @_; my ($hash) = @_;
return DevIo_OpenDev($hash, 1, "OBIS_Init") return DevIo_OpenDev($hash, 1, "OBIS_Init")
if($hash->{STATE} eq "disconnected"); if($hash->{STATE} eq "disconnected");
my $name = $hash->{NAME};
my $dev=$hash->{DeviceName};
# This is relevant for windows/USB only # This is relevant for windows/USB only
my $po = $hash->{USBDev}; my $po = $hash->{USBDev};
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status; my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags);
return if (!$po);
($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
return ($InBytes>0); return ($InBytes>0);
} }
@ -267,7 +271,19 @@ sub OBIS_Attr(@)
# $name is device name # $name is device name
# aName and aVal are Attribute name and value # aName and aVal are Attribute name and value
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dev=$hash->{DeviceName};
if ($cmd eq "del") {
if ($aName eq "channels") { $hash->{helper}{Channels}=undef;}
if ($aName eq "interval") {
RemoveInternalTimer($hash);
$hash->{helper}{DEVICES}[1]=0;
}
if ($aName eq "pollingMode") {
$hash->{FD}=$hash->{helper}{FD2};
delete($readyfnlist{"$name.$dev"});
$selectlist{"$name.$dev"} = $hash;
}
}
if ($cmd eq "set") { if ($cmd eq "set") {
if ($aName eq "channels") { if ($aName eq "channels") {
$hash->{helper}{Channels}=eval $aVal; $hash->{helper}{Channels}=eval $aVal;
@ -278,19 +294,36 @@ sub OBIS_Attr(@)
} }
if ($aName eq "interval") { if ($aName eq "interval") {
if ($aVal=~/^[1-9][0-9]*$/) { if ($aVal=~/^[1-9][0-9]*$/) {
$hash->{helper}{TRIGGERTIME}=gettimeofday();
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
$hash->{helper}{DEVICES}[1]=$aVal; $hash->{helper}{DEVICES}[1]=$aVal;
InternalTimer(gettimeofday()+2, "GetUpdate", $hash, 1) if ($aVal>0); # InternalTimer(gettimeofday()+2, "GetUpdate", $hash, 1) if ($aVal>0);
my $t=OBIS_adjustAlign($hash,AttrVal($name,"alignTime",undef),$hash->{helper}{DEVICES}[1]);
Log3 ($hash,4,"OBIS ($name) - Internal timer set to ".FmtDateTime($t)) if ($hash->{helper}{DEVICES}[1]>0);
InternalTimer($t, "GetUpdate", $hash, 0) if ($hash->{helper}{DEVICES}[1]>0);
} else { } else {
Log3 $name, 3, "OBIS ($name) - $name: attr interval must be a number -> $aVal"; return $name, 3, "OBIS ($name) - $name: attr interval must be a number -> $aVal";
} }
} }
if ($aName eq "alignTime") { if ($aName eq "alignTime") {
if ($hash->{helper}{DEVICES}[1]>0) {
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
my $t=OBIS_adjustAlign($hash,$aVal,$hash->{helper}{DEVICES}[1]); my $t=OBIS_adjustAlign($hash,$aVal,$hash->{helper}{DEVICES}[1]);
Log3 ($hash,4,"OBIS ($name) - Internal timer set to ".FmtDateTime($t)) if ($hash->{helper}{DEVICES}[1]>0); Log3 ($hash,4,"OBIS ($name) - Internal timer set to ".FmtDateTime($t));
InternalTimer($t, "GetUpdate", $hash, 1) if ($hash->{helper}{DEVICES}[1]>0); InternalTimer($t, "GetUpdate", $hash, 0);
} else {
return $name, 3, "OBIS ($name) - $name: attr alignTime is useless, if no interval is specified";
}
}
if ($aName eq "pollingMode")
{
if ($aVal eq "on") {
delete($selectlist{"$name.$dev"});
$readyfnlist{"$name.$dev"} = $hash;
} elsif ($aVal eq "off") {
delete($readyfnlist{"$name.$dev"});
$selectlist{"$name.$dev"} = $hash;
}
} }
} }
@ -300,24 +333,34 @@ sub OBIS_Attr(@)
sub OBIS_adjustAlign($$$) sub OBIS_adjustAlign($$$)
{ {
my($hash, $attrVal, $interval) = @_; my($hash, $attrVal, $interval) = @_;
return gettimeofday()+$interval;
my ($alErr, $alHr, $alMin, $alSec, undef) = GetTimeSpec($attrVal); if (!$attrVal) {return gettimeofday()+$interval;}
my ($alErr, $alHr, $alMin, $alSec, undef) = GetTimeSpec($attrVal); # "00:00"
return "$hash->{NAME} alignTime: $alErr" if($alErr); return "$hash->{NAME} alignTime: $alErr" if($alErr);
my $tspec=strftime("\%H:\%M:\%S", gmtime($interval)); my $tspec=strftime("\%H:\%M:\%S", gmtime($interval));
my (undef, $hr, $min, $sec, undef) = GetTimeSpec($tspec); my (undef, $hr, $min, $sec, undef) = GetTimeSpec($tspec);
my $now = time(); my $now = time();
my $step = ($hr*60+$min)*60+$sec;
my $alTime = ($alHr*60+$alMin)*60+$alSec-fhemTzOffset($now); my $alTime = ($alHr*60+$alMin)*60+$alSec-fhemTzOffset($now);
my $ttime = int($hash->{helper}{TRIGGERTIME}); my $ttime = int($hash->{helper}{TRIGGERTIME});
my $off = ($ttime % 86400) - 86400; my $off = ($ttime % 86400) - 86400;
if ($off >= $alTime) {
$ttime = gettimeofday();#-86400;
$off -= 86400;
}
Log 4,$alTime." - $ttime - $off - $alTime - $step- ".FmtDateTime($ttime % 86400)." - ".FmtDateTime($off)." - ".fhemTzOffset($now);
my $off2=$off;
while($off < $alTime) { while($off < $alTime) {
$off += $interval; $off += $step;
} }
$ttime += ($alTime-$off); $ttime += ($alTime-$off);
$ttime += $interval if($ttime < $now); $ttime += $step if($ttime < $now);
$hash->{NEXT} = FmtDateTime($ttime);
$hash->{helper}{TRIGGERTIME} = ($off2<=$alTime) ? $ttime : (gettimeofday());#-fhemTzOffset($now));
$hash->{helper}{TRIGGERTIME} = $ttime; return $hash->{helper}{TRIGGERTIME};
return $ttime;
} }
##################################### #####################################
@ -418,6 +461,11 @@ sub OBIS_adjustAlign($$$)
<br><br></li><li> <br><br></li><li>
<code>interval</code><br> <code>interval</code><br>
Abrufinterval der Daten. Abrufinterval der Daten.
</li><li>
<code>pollingMode</code><br>
Hiermit wird von Direktbenachrichtigung auf Polling umgestellt.
Bei Smartmetern, welche von selbst im Sekundentakt senden,
kann das zu einer spürbaren Senkung der Prozessorleistung führen.
</li> </li>
<br> <br>
</ul> </ul>