From 320e33c6df2c91b248ec28a6e885940d246cea23 Mon Sep 17 00:00:00 2001 From: pahenning Date: Thu, 4 Apr 2013 03:48:29 +0000 Subject: [PATCH] git-svn-id: https://svn.fhem.de/fhem/trunk@3030 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/21_OWAD.pm | 110 +++++--- fhem/FHEM/21_OWCOUNT.pm | 546 ++++++++++++++++++++++----------------- fhem/FHEM/21_OWID.pm | 13 +- fhem/FHEM/21_OWLCD.pm | 6 +- fhem/FHEM/21_OWMULTI.pm | 174 +++++++------ fhem/FHEM/21_OWSWITCH.pm | 206 ++++++++------- fhem/FHEM/21_OWTHERM.pm | 49 +++- 7 files changed, 643 insertions(+), 461 deletions(-) diff --git a/fhem/FHEM/21_OWAD.pm b/fhem/FHEM/21_OWAD.pm index b0d348f5f..cd0d5bdf5 100644 --- a/fhem/FHEM/21_OWAD.pm +++ b/fhem/FHEM/21_OWAD.pm @@ -27,6 +27,7 @@ # get reading => measurement for all channels # get alarm => alarm measurement settings for all channels # get status => alarm and i/o status for all channels +# get version => OWX version number # # set interval => set period for measurement # @@ -74,12 +75,13 @@ use strict; use warnings; sub Log($$); +my $owx_version="3.21"; +#-- fixed raw channel name, flexible channel name +my @owg_fixed = ("A","B","C","D"); +my @owg_channel = ("A","B","C","D"); #-- value globals my @owg_status; my $owg_state; -#-- channel name - fixed is the first array, variable the second -my @owg_fixed = ("A","B","C","D"); -my @owg_channel = ("A","B","C","D"); #-- channel values - always the raw values from the device my @owg_val=("","","",""); #-- channel mode - fixed for now @@ -102,6 +104,7 @@ my %gets = ( "reading" => "", "alarm" => "", "status" => "", + "version" => "" ); my %sets = ( @@ -261,6 +264,49 @@ sub OWAD_Define ($$) { return undef; } +######################################################################################## +# +# OWAD_ChannelNames - find the real channel names +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWAD_ChannelNames($) { + my ($hash) = @_; + + my $name = $hash->{NAME}; + my $state = $hash->{READINGS}{"state"}{VAL}; + + my ($cname,@cnama,$unit,@unarr); + + for (my $i=0;$i" + if( $state eq "defined"); + push(@cnama,"unknown"); + } + $owg_channel[$i]=$cnama[0]; + + #-- unit + $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "Volt|V"; + @unarr= split(/\|/,$unit); + if( int(@unarr)!=2 ){ + Log 1, "OWAD: Incomplete channel unit specification $unit. Better use $unit|" + if( $state eq "defined"); + push(@unarr,""); + } + + #-- put into readings + $hash->{READINGS}{$owg_channel[$i]}{TYPE} = $cnama[1]; + $hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unarr[0]; + $hash->{READINGS}{$owg_channel[$i]}{UNITABBR} = $unarr[1]; + } +} + ######################################################################################## # # OWAD_InitializeDevice - delayed setting of initial readings and channel names @@ -272,35 +318,14 @@ sub OWAD_Define ($$) { sub OWAD_InitializeDevice($) { my ($hash) = @_; - my $name = $hash->{NAME}; + my $name = $hash->{NAME}; my $interface = $hash->{IODev}->{TYPE}; #-- Initial readings @owg_val = ("","","",""); - #-- Set channel names, channel units and alarm values + #-- Initial alarm values for( my $i=0;$i"; - push(@cnama,"unknown"); - } - - #-- unit - my $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "Volt|V"; - my @unarr= split(/\|/,$unit); - if( int(@unarr)!=2 ){ - Log 1, "OWAD: Incomplete channel unit specification $unit. Better use $unit|"; - push(@unarr,""); - } - - #-- put into readings - $owg_channel[$i] = $cnama[0]; - $hash->{READINGS}{"$owg_channel[$i]"}{TYPE} = $cnama[1]; - $hash->{READINGS}{"$owg_channel[$i]"}{UNIT} = $unarr[0]; - $hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR} = $unarr[1]; $hash->{ERRCOUNT} = 0; #-- alarm enabling @@ -363,6 +388,7 @@ sub OWAD_FormatValues($) { my ($offset,$factor,$vval,$vlow,$vhigh,$vfunc,$ret); my $vfuncall = ""; my $svalue = ""; + #-- insert initial values for( my $k=0;$k{READINGS}{"state"}{VAL} eq "defined"); - + #-- put into READINGS readingsBeginUpdate($hash); #-- formats for output for (my $i=0;$i{tempf}{"$owg_fixed[$i]"}{function} = $vfunc; + $hash->{tempf}{$owg_fixed[$i]}{function} = $vfunc; #-- replace by proper values (VA -> $owg_val[0] etc.) + # careful: how to prevent {VAL} from being replaced ? for( my $k=0;$k{READINGS}{$owg_channel[$i]}{UNITABBR}); #-- Test for alarm condition $alarm = "none"; @@ -548,6 +574,11 @@ sub OWAD_Get($@) { return "$name.interval => $value"; } + #-- get version + if( $a[1] eq "version") { + return "$name.version => $owx_version"; + } + #-- reset presence $hash->{PRESENT} = 0; @@ -757,11 +788,12 @@ sub OWAD_Set($@) { #-- define vars my $ret = undef; - my $channel = undef; + my $channon = undef; my $channo = undef; my $factor; my $offset; my $condx; + my $name = $hash->{NAME}; my $model = $hash->{OW_MODEL}; @@ -779,11 +811,11 @@ sub OWAD_Set($@) { #-- find out which channel we have my $tc =$key; - if( $tc =~ s/(.*)(Alarm|Low|High)/$channel=$1/se ) { + if( $tc =~ s/(.*)(Alarm|Low|High)/$channon=$1/se ) { for (my $i=0;$i midnight => todays starting value for counter # get counter => value for counter # get counters => values for both counters +# get version => OWX version number # # set interval => set query interval for measurement # set memory => 32 byte string into page 0..13 # set midnight => todays starting value for counter # # Additional attributes are defined in fhem.cfg, in some cases per channel, where =A,B -# Note: attributes are read only during initialization procedure - later changes are not used. # # attr LogM = device name (not file name) of monthly log file # attr Name | = name for the channel | a type description for the measured value # attr Unit | = unit of measurement for this channel | its abbreviation +# attr Rate | = name for the channel ratw | a type description for the measured value # attr Offset = offset added to the reading in this channel # attr Factor = factor multiplied to (reading+offset) in this channel # attr Mode = counting mode = normal(default) or daily @@ -52,7 +53,7 @@ # after each interval : / / : / / # example: 2012-07-30_00:07:55 OWX_C Taste: 17.03 p 28.1 p/h B: 7.0 cts 0.0 cts/min # after midnight : : -# example: 2012-07-30_00:00:57 OWX_C D_29: 2012-7-29_23:59:59 Taste: 110.0 p, B: 7.0 cts +# example: 2012-07-30_00:00:57 OWX_C D29: 2012-7-29_23:59:59 Taste: 110.0 p, B: 7.0 cts ######################################################################################## # # This programm is free software; you can redistribute it and/or modify @@ -78,10 +79,12 @@ use strict; use warnings; sub Log($$); -#-- channel name - fixed is the first array, variable the second -my @owg_fixed = ("A","B"); -my @owg_channel; -my @owg_rate; +my $owx_version="3.21"; +#-- fixed raw channel name, flexible channel name +my @owg_fixed = ("A","B"); +my @owg_channel = ("A","B"); +my @owg_rate = ("A_rate","B_rate"); + #-- channel values - always the raw values from the device my @owg_val; my @owg_midnight; @@ -94,7 +97,9 @@ my %gets = ( "memory" => "", "midnight" => "", "counter" => "", - "counters" => "" + "counters" => "", + "month" => "", + "version" => "" ); my %sets = ( @@ -108,7 +113,6 @@ my %updates = ( "counter" => "" ); - ######################################################################################## # # The following subroutines are independent of the bus interface @@ -136,6 +140,7 @@ sub OWCOUNT_Initialize ($) { $readingFnAttributes; for( my $i=0;$i{IODev}=$attr{$name}{"IODev"} if( defined($attr{$name}{"IODev"}) ); AssignIoPort($hash); - if( (!defined($hash->{IODev}->{NAME})) || (!defined($hash->{IODev})) ){ + if( (!defined($hash->{IODev}->{NAME})) || (!defined($hash->{IODev})) ){ return "OWSWITCH: Warning, no 1-Wire I/O device found for $name."; } - - - - #if( $hash->{IODev}->{PRESENT} != 1 ){ - # return "OWSWITCH: Warning, 1-Wire I/O device ".$hash->{IODev}->{NAME}." not present for $name."; - #} + $modules{OWCOUNT}{defptr}{$id} = $hash; #-- readingsSingleUpdate($hash,"state","defined",1); Log 3, "OWCOUNT: Device $name defined."; - - #-- Initialization reading according to interface type - my $interface= $hash->{IODev}->{TYPE}; - - #-- Start timer for initialization in a few seconds - InternalTimer(time()+5, "OWCOUNT_InitializeDevice", $hash, 0); #-- Start timer for updates - InternalTimer(time()+5+$hash->{INTERVAL}, "OWCOUNT_GetValues", $hash, 0); + InternalTimer(time()+10, "OWCOUNT_GetValues", $hash, 0); return undef; } +######################################################################################## +# +# OWCOUNT_ChannelNames - find the real channel names +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWCOUNT_ChannelNames($) { + my ($hash) = @_; + + my $name = $hash->{NAME}; + my $state = $hash->{READINGS}{"state"}{VAL}; + + my ($cname,@cnama,$unit,@unarr,$runit,$period); + + for (my $i=0;$i" + if( $state eq "defined"); + push(@cnama,"unknown"); + } + #-- unit + $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "counts|cts"; + @unarr= split(/\|/,$unit); + if( int(@unarr)!=2 ){ + Log 1, "OWCOUNT: Incomplete channel unit specification $unit. Better use $unit|" + if( $state eq "defined"); + push(@unarr,""); + } + + #-- put into readings + $owg_channel[$i]=$cnama[0]; + $hash->{READINGS}{$owg_channel[$i]}{TYPE} = $cnama[1]; + $hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unarr[0]; + $hash->{READINGS}{$owg_channel[$i]}{UNITABBR} = $unarr[1]; + + $period = defined($attr{$name}{$owg_fixed[$i]."Period"}) ? $attr{$name}{$owg_fixed[$i]."Period"} : "hour"; + #-- put into readings + $hash->{READINGS}{$owg_channel[$i]}{PERIOD} = $period; + + #-- rate + $cname = defined($attr{$name}{$owg_fixed[$i]."Rate"}) ? $attr{$name}{$owg_fixed[$i]."Rate"} : $cnama[0]."_rate|".$cnama[1]."_rate"; + @cnama = split(/\|/,$cname); + if( int(@cnama)!=2){ + Log 1, "OWCOUNT: Incomplete rate name specification $cname. Better use $cname|" + if( $state eq "defined"); + push(@cnama,"unknown"); + } + + #-- rate unit + my $runit = ""; + if( $period eq "hour" ){ + $runit = "/h"; + }elsif( $period eq "minute" ){ + $runit = "/min"; + } else { + $runit = "/s"; + } + #-- put into readings + $owg_rate[$i]=$cnama[0]; + $hash->{READINGS}{$owg_rate[$i]}{TYPE} = $cnama[1]; + $hash->{READINGS}{$owg_rate[$i]}{UNIT} = $unarr[0].$runit; + $hash->{READINGS}{$owg_rate[$i]}{UNITABBR} = $unarr[1].$runit; + + #-- some special cases + # Energy/Power + $hash->{READINGS}{$owg_rate[$i]}{UNIT} = "kW" + if ($unarr[0].$runit eq "kWh/h" ); + $hash->{READINGS}{$owg_rate[$i]}{UNITABBR} = "kW" + if ($unarr[1].$runit eq "kWh/h" ); + } +} + ######################################################################################## # # OWCOUNT_InitializeDevice - delayed setting of initial readings and channel names @@ -257,79 +328,15 @@ sub OWCOUNT_InitializeDevice($) { my $name = $hash->{NAME}; $hash->{PRESENT} = 0; - - #-- Set channel names, channel units and alarm values + + #-- initial values for( my $i=0;$i"; - push(@cnama,"unknown"); - } - - #-- unit - my $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "counts|cts"; - my @unarr= split(/\|/,$unit); - if( int(@unarr)!=2 ){ - Log 1, "OWCOUNT: Incomplete channel unit specification $unit. Better use |$unit"; - push(@unarr,""); - } - - #-- rate unit - my $period = defined($attr{$name}{$owg_fixed[$i]."Period"}) ? $attr{$name}{$owg_fixed[$i]."Period"} : "hour"; - - #-- offset and scale factor - my $offset = defined($attr{$name}{$owg_fixed[$i]."Offset"}) ? $attr{$name}{$owg_fixed[$i]."Offset"} : 0; - my $factor = defined($attr{$name}{$owg_fixed[$i]."Factor"}) ? $attr{$name}{$owg_fixed[$i]."Factor"} : 1; - #-- put into readings - $owg_channel[$i] = $cnama[0]; - $hash->{READINGS}{"$owg_channel[$i]"}{TYPE} = $cnama[1]; - $hash->{READINGS}{"$owg_channel[$i]"}{UNIT} = $unarr[0]; - $hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR} = $unarr[1]; - $hash->{READINGS}{"$owg_channel[$i]"}{PERIOD} = $period; - $hash->{READINGS}{"$owg_channel[$i]"}{OFFSET} = $offset; - $hash->{READINGS}{"$owg_channel[$i]"}{FACTOR} = $factor; - - $owg_rate[$i] = $cnama[0]."_rate"; - my $runit = ""; - if( $period eq "hour" ){ - $runit = "/h"; - }elsif( $period eq "minute" ){ - $runit = "/min"; - } else { - $runit = "/s"; - } - $hash->{READINGS}{"$owg_rate[$i]"}{TYPE} = $cnama[1]."_rate"; - $hash->{READINGS}{"$owg_rate[$i]"}{UNIT} = $unarr[0].$runit; - $hash->{READINGS}{"$owg_rate[$i]"}{UNITABBR} = $unarr[1].$runit; - #-- some special cases - # Energy/Power - $hash->{READINGS}{"$owg_rate[$i]"}{UNIT} = "kW" - if ($unarr[0].$runit eq "kWh/h" ); - $hash->{READINGS}{"$owg_rate[$i]"}{UNITABBR} = "kW" - if ($unarr[1].$runit eq "kWh/h" ); + $owg_midnight[$i] = ""; } - #-- set status according to interface type - my $interface= $hash->{IODev}->{TYPE}; - - #-- OWX interface - if( !defined($interface) ){ - return "OWCOUNT: Interface missing"; - } elsif( $interface eq "OWX" ){ - #-- OWFS interface - #}elsif( $interface eq "OWFS" ){ - # $ret = OWFSAD_GetPage($hash,"reading"); - #-- Unknown interface - }else{ - return "OWCOUNT: InitializeDevice with wrong IODev type $interface"; - } - #-- Initialize all the display stuff - OWCOUNT_FormatValues($hash); + return undef; } ######################################################################################## @@ -344,70 +351,93 @@ sub OWCOUNT_FormatValues($) { my ($hash) = @_; my $name = $hash->{NAME}; - my ($offset,$factor,$period,$unit,$runit,$midnight,$vval,$vrate); + my ($offset,$factor,$period,$unit,$runit,$vval,$vrate); my ($svalue,$dvalue,$mvalue) = ("","",""); my $galarm = 0; - + my $tn = TimeNow(); my ($sec, $min, $hour, $day, $month, $year, $wday,$yday,$isdst) = localtime(time); my ($seco,$mino,$houro,$dayo,$montho,$yearo,$dayrest); - my ($dt,$dv,$dval,$delt,$delf); + my ($daily, $dt,$dval,$dval2,$deltim,$delt,$delf); my $daybreak = 0; my $monthbreak = 0; my $present = $hash->{PRESENT}; + #-- no change in any value if invalid reading + #for (my $i=0;$i{READINGS}{"state"}{VAL} eq "defined"); + + #-- Check, whether we have a new day at the next reading + $deltim = $hour*60.0+$min+$sec/60.0 - (1440 - $hash->{INTERVAL}/60.0); + if( $deltim>=0 ){ + $daybreak = 1; + $monthbreak = 0; + #-- Timer data from tomorrow + my ($secn,$minn,$hourn,$dayn,$monthn,$yearn,$wdayn,$ydayn,$isdstn) = localtime(time() + $hash->{INTERVAL} + 3600); + #-- Check, whether we have a new month + if( $dayn == 1 ){ + $monthbreak = 1; + } + } + #-- put into READINGS readingsBeginUpdate($hash); #-- formats for output for (my $i=0;$i{READINGS}{"$owg_channel[$i]"}{OFFSET}; - $factor = $hash->{READINGS}{"$owg_channel[$i]"}{FACTOR}; - $unit = $hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR}; - $period = $hash->{READINGS}{"$owg_channel[$i]"}{PERIOD}; - $runit = $hash->{READINGS}{"$owg_rate[$i]"}{UNITABBR}; + #-- offset and scale factor + $offset = defined($attr{$name}{$owg_fixed[$i]."Offset"}) ? $attr{$name}{$owg_fixed[$i]."Offset"} : 0; + $factor = defined($attr{$name}{$owg_fixed[$i]."Factor"}) ? $attr{$name}{$owg_fixed[$i]."Factor"} : 1; + + #-- put into READINGS + $hash->{READINGS}{$owg_channel[$i]}{OFFSET} = $offset; + $hash->{READINGS}{$owg_channel[$i]}{FACTOR} = $factor; + + $unit = $hash->{READINGS}{$owg_channel[$i]}{UNITABBR}; + $period = $hash->{READINGS}{$owg_channel[$i]}{PERIOD}; + $runit = $hash->{READINGS}{$owg_rate[$i]}{UNITABBR}; #-- skip some things if undefined if( $owg_val[$i] eq ""){ $svalue .= $owg_channel[$i].": ???"; }else{ #-- only if attribute value mode=daily, take the midnight value from memory - if( defined($attr{$name}{$owg_fixed[$i]."Mode"} )){ - if( $attr{$name}{$owg_fixed[$i]."Mode"} eq "daily"){ - $midnight = $owg_midnight[$i]; - #-- parse float from midnight - $midnight =~ /([\d\.]+)/; - $midnight = 0.0 if(!(defined($midnight))); - } else { - $midnight = 0.0; - } - } else { - $midnight = 0.0; - } - - #-- correct values for proper offset, factor - # careful: midnight value has not been corrected so far ! - #-- 1 decimal - if( $factor == 1.0 ){ - $vval = int(($owg_val[$i] + $offset - $midnight)*10)/10; - #-- 3 decimals + if( $daily == 1){ + $vval = int( (($owg_val[$i] + $offset)*$factor - $owg_midnight[$i])*100)/100; } else { - $vval = int((($owg_val[$i] + $offset)*$factor - $midnight)*1000)/1000; + $vval = int( ($owg_val[$i] + $offset)*$factor*100)/100; } - - #-- get the old values - my $oldval = $hash->{READINGS}{"$owg_channel[$i]"}{VAL}; - my $oldtim = $hash->{READINGS}{"$owg_channel[$i]"}{TIME}; + + #-- rate calculation: get the old values + my $oldval = $hash->{READINGS}{$owg_channel[$i]}{VAL}; + my $oldtim = $hash->{READINGS}{$owg_channel[$i]}{TIME}; $oldtim = "" if(!defined($oldtim)); #-- safeguard against the case where no previous measurement if( length($oldtim) > 0 ){ + #-- correct counter wraparound since last reading + if( $vval < $oldval) { + $oldval -= 65536*(65536*$factor); + } + #-- previous measurement time ($yearo,$montho,$dayrest) = split(/-/,$oldtim); $dayo = substr($dayrest,0,2); @@ -416,38 +446,7 @@ sub OWCOUNT_FormatValues($) { #-- time dfifference to previous measurement and to midnight $delt = ($hour-$houro)*3600 + ($min-$mino)*60 + ($sec-$seco); $delf = $hour *3600 + $min *60 + $sec - 86400; - if( ($delf+$hash->{INTERVAL}) >= 0 ){ - $daybreak = 1; - #-- Timer data from tomorrow - my ($secn,$minn,$hourn,$dayn,$monthn,$yearn,$wdayn,$ydayn,$isdstn) = localtime(time() + 24*60*60); - #-- Check, whether we have a new month - if( (($delf+$hash->{INTERVAL}) > 0) && ($dayn == 1) ){ - $monthbreak =1; - } - } - - #-- correct $vval for wraparound of 32 bit counter - if( ($vval < $oldval) && ($daybreak==0) && ($present==1) ){ - Log 1,"OWCOUNT TODO: Counter wraparound"; - } - - if( $daybreak==1 ){ - #-- linear extrapolation - $dt = -$delf/$delt; - $dv = ($vval-$oldval)*$dt; - $dval = $vval+$dv; - - #-- in any mode store the interpolated value in the midnight store - OWXCOUNT_SetPage($hash,14+$i,sprintf("%f",$dval)); - #-- string buildup for monthly logging - $dvalue .= sprintf( "%s: %5.1f %s", $owg_channel[$i], $dval,$unit); - if( $day<$dayo ){ - $monthbreak = 1; - Log 1, "OWCOUNT: Change of month"; - #-- string buildup for yearly logging - $mvalue .= sprintf( "%s: %5.1f %s", $owg_channel[$i], $dval,$unit); - } - } + #-- rate if( ($delt > 0.0) && $present ){ $vrate = ($vval-$oldval)/$delt; @@ -460,42 +459,59 @@ sub OWCOUNT_FormatValues($) { }elsif( $period eq "minute" ){ $vrate*=60; } - $vrate = int($vrate * 1000)/1000; - - if( !defined($runit) ){ - Log 1,"OWCOUNT: Error in rate unit definition. i=$i, owg_rate[i]=".$owg_rate[$i]; - $runit = "ERR"; - } + $vrate = int($vrate * 100)/100; + + #--midnight extrapolation only possible if previous measurement + if( $daybreak==1 ){ + #-- linear extrapolation + $dt = -$delf/$delt; + $dval = int(($vval+($vval-$oldval)*$dt)*100)/100; + + if( $daily == 1 ){ + $dval2 = $dval+$owg_midnight[$i]; + } else { + $dval2 = $dval; + } + + #-- in any mode store the interpolated value in the midnight store + OWXCOUNT_SetPage($hash,14+$i,sprintf("%f",$dval2)); + #-- string buildup for monthly and yearly logging + $dvalue .= sprintf( " %s: %5.1f %s", $owg_channel[$i], $dval,$unit); + $mvalue .= sprintf( " %s: %%5.1f %s", $owg_channel[$i], $unit); + } #-- end daybreak #-- string buildup for return value and STATE #-- 1 decimal if( $factor == 1.0 ){ - $svalue .= sprintf( "%s: %5.1f %s / %5.2f %s", $owg_channel[$i], $vval,$unit,$vrate,$runit); + $svalue .= sprintf( "%s: %5.1f %s %s: %5.2f %s", $owg_channel[$i], $vval,$unit,$owg_rate[$i],$vrate,$runit); #-- 3 decimals } else { - $svalue .= sprintf( "%s: %5.3f %s / %5.2f %s", $owg_channel[$i], $vval,$unit,$vrate,$runit); + $svalue .= sprintf( "%s: %5.3f %s %s: %5.2f %s", $owg_channel[$i], $vval,$unit,$owg_rate[$i],$vrate,$runit); } } - readingsBulkUpdate($hash,"$owg_channel[$i]",$vval); - readingsBulkUpdate($hash,"$owg_rate[$i]",$vrate); + readingsBulkUpdate($hash,$owg_channel[$i],$vval); + readingsBulkUpdate($hash,$owg_rate[$i],$vrate); } #-- insert space if( $i[1]; + my $total1 = @monthv[1]->[1]; + $dvalue = sprintf("D%02d ",$day).$dvalue; readingsBulkUpdate($hash,"day",$dvalue); if( $monthbreak == 1){ - $mvalue = sprintf("M_%02d SOME VALUE",$month); + $mvalue = sprintf("M%02d ",$month+1).$mvalue; + $mvalue = sprintf($mvalue,$total0,$total1); readingsBulkUpdate($hash,"month",$mvalue); - Log 1,$name." has monthbreak ".$mvalue; } } @@ -523,8 +539,7 @@ sub OWCOUNT_Get($@) { my $value = undef; my $ret = ""; my $page; - my $channo = undef; - my $channel; + my ($unit,$daily); #-- check syntax return "OWCOUNT: Get argument is missing @a" @@ -555,9 +570,44 @@ sub OWCOUNT_Get($@) { return "$name.interval => $value"; } + #-- get version + if( $a[1] eq "version") { + return "$name.version => $owx_version"; + } + #-- reset presence - #-- TODO: THIS IS TOO STRONG !!! - #$hash->{PRESENT} = 0; + $hash->{PRESENT} = 0; + + #-- get channel names + OWCOUNT_ChannelNames($hash); + + #-- get month + if($a[1] eq "month") { + $value="$name.month =>\n"; + my @month2 = OWCOUNT_GetMonth($hash); + #-- error case + if( int(@month2) == 1 ){ + return $month2[0]; + } + #-- 3 entries for each day + for(my $i=0;$i{READINGS}{$owg_channel[$i]}{UNITABBR}; + #-- mode = daily ? + $daily = 0; + if( defined($attr{$name}{$owg_fixed[$i]."Mode"} )){ + if( $attr{$name}{$owg_fixed[$i]."Mode"} eq "daily"){ + $daily = 1; + } + } + if( $daily==1){ + $value .= $owg_channel[$i]." monthly sum ".$month2[$i]->[1]." ".$unit. + " (average ".$month2[$i]->[2]." ".$unit."/d)\n"; + }else{ + $value .= $owg_channel[$i]." last midnight ".$month2[$i]->[1]." ".$unit."\n"; + } + } + return $value; + } #-- get memory page/counter according to interface type my $interface= $hash->{IODev}->{TYPE}; @@ -565,14 +615,14 @@ sub OWCOUNT_Get($@) { #-- check syntax for getting memory page 0..13 or midnight A/B if( ($reading eq "memory") || ($reading eq "midnight") ){ if( $reading eq "memory" ){ - return "OWCOUNT: set needs parameter when reading memory: " + return "OWCOUNT: get needs parameter when reading memory: " if( int(@a)<2 ); $page=int($a[2]); if( ($page<0) || ($page>13) ){ return "OWXCOUNT: Wrong memory page requested"; } }else{ - return "OWCOUNT: set needs parameter when reading midnight: " + return "OWCOUNT: get needs parameter when reading midnight: " if( int(@a)<2 ); #-- find out which channel we have if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){ @@ -644,8 +694,7 @@ sub OWCOUNT_Get($@) { return "OWCOUNT: Could not get values from device $name"; } $hash->{PRESENT} = 1; - return "OWCOUNT: $name.$reading => ".OWCOUNT_FormatValues($hash); - + return "OWCOUNT: $name.$reading => ".OWCOUNT_FormatValues($hash); } ######################################################################################## @@ -666,54 +715,67 @@ sub OWCOUNT_GetMonth($) { my $val; my @month = (); my @month2 = (); - my @channel; - my ($total,$total2,$deltim,$av); - + my @mchannel; + my ($total,$total2,$daily,$deltim,$av); + #-- Check current logfile my $ln = $attr{$name}{"LogM"}; if( !(defined($ln))){ Log 1,"OWCOUNT_GetMonth: Attribute LogM is missing"; return undef; - } else { - my $lf = $defs{$ln}{currentlogfile}; - my $ret = open(OWXFILE, "< $lf" ); - if( $ret) { - while( ){ - #-- line looks as - # 2013-02-09_23:59:31 day D_09 : 180.0 cts : 180.0 cts etc. - my $line = $_; - chomp($line); - if ( $line =~ m/$regexp/i){ - my @linarr = split(' ',$line); - my $day = $linarr[3]; - $day =~ s/D_0+//; - @channel = (); - for (my $i=0;$i ){ + #-- line looks as + # 2013-02-09_23:59:31 day: D09 : 180.0 : 180.0 etc. + my $line = $_; + chomp($line); + if ( $line =~ m/$regexp/i){ + my @linarr = split(' ',$line); + my $day = $linarr[3]; + $day =~ s/D_0+//; + @mchannel = (); + for (my $i=0;$i{READINGS}{"$owg_channel[$i]"}{VAL}))/100; - my $av = int(100*$total2/(int(@month)+$deltim))/100; - - push(@month2,[($total,$total2,$av)]); } - return @month2; + #-- add data from current day also for non-summed mode + $total = int($total*100)/100; + $total2 = int(100*($total+$hash->{READINGS}{$owg_channel[$i]}{VAL}))/100; + #-- number of days so far, including the present day + my ($sec,$min,$hour,$day,$month,$year,$wday,$yday,$isdst) = localtime(time); + my $deltim = int(@month)+($hour+$min/60.0 + $sec/3600.0)/24.0; + my $av = int(100*$total2/$deltim)/100; + #-- output format + push(@month2,[($total,$total2,$av)]); } + return @month2; } ####################################################################################### @@ -731,8 +793,6 @@ sub OWCOUNT_GetValues($) { my $model = $hash->{OW_MODEL}; my $value = ""; my $ret = ""; - my $offset; - my $factor; #-- define warnings my $warn = "none"; @@ -742,7 +802,7 @@ sub OWCOUNT_GetValues($) { RemoveInternalTimer($hash); InternalTimer(time()+$hash->{INTERVAL}, "OWCOUNT_GetValues", $hash, 1); - #-- reset presence - maybe this is too strong + #-- reset presence - $hash->{PRESENT} = 0; #-- Get readings according to interface type @@ -802,11 +862,10 @@ sub OWCOUNT_Set($@) { my $ret = undef; my $page; my $data; - my $channo = undef; - my $channel; my $name = $hash->{NAME}; my $model = $hash->{OW_MODEL}; - + my ($cname,@cnama,@channel); + #-- set new timer interval if($key eq "interval") { # check value @@ -819,6 +878,9 @@ sub OWCOUNT_Set($@) { return undef; } + #-- get channel names + OWCOUNT_ChannelNames($hash); + #-- set memory page/counter according to interface type my $interface= $hash->{IODev}->{TYPE}; @@ -922,7 +984,7 @@ sub OWFSCOUNT_GetPage($$) { if( ($page<0) || ($page>15) ){ return "OWXCOUNT: Wrong memory page requested"; } - #-- get values - or shoud we rather get the uncached ones ? + #-- get values - or shoud we rather get the uncached ones ? if( $page == 14) { $vval = OWServer_Read($master,"/$owx_add/counters.A"); $owg_str = OWServer_Read($master,"/$owx_add/pages/page.14"); @@ -934,6 +996,10 @@ sub OWFSCOUNT_GetPage($$) { if( ($vval eq "") || ($owg_str eq "") ); $owg_val[0] = $vval; + #-- parse float from midnight + $owg_str =~ /([\d\.]+)/; + $owg_str = int($owg_str*100)/100; + $owg_str = 0.0 if(!(defined($owg_str))); $owg_midnight[0] = $owg_str; }elsif( $page == 15) { @@ -947,6 +1013,10 @@ sub OWFSCOUNT_GetPage($$) { if( ($vval eq "") || ($owg_str eq "") ); $owg_val[1] = $vval; + #-- parse float from midnight + $owg_str =~ /([\d\.]+)/; + $owg_str = int($owg_str*100)/100; + $owg_str = 0.0 if(!(defined($owg_str))); $owg_midnight[1] = $owg_str; }else { $owg_str = OWServer_Read($master,"/$owx_add/pages/page.".$page); @@ -1066,14 +1136,21 @@ sub OWXCOUNT_GetPage($$) { return "OWXCOUNT: Device $owx_dev returns invalid data"; } - #-- first ignore memory and only use counter (Fehler gefunden von jamesgo) my $value = (ord($data[3])<<24) + (ord($data[2])<<16) +(ord($data[1])<<8) + ord($data[0]); if( $page == 14) { $owg_val[0] = $value; + #-- parse float from midnight + $owg_str =~ /([\d\.]+)/; + $owg_str = int($owg_str*100)/100; + $owg_str = 0.0 if(!(defined($owg_str))); $owg_midnight[0] = $owg_str; }elsif( $page == 15) { $owg_val[1] = $value; + #-- parse float from midnight + $owg_str =~ /([\d\.]+)/; + $owg_str = int($owg_str*100)/100; + $owg_str = 0.0 if(!(defined($owg_str))); $owg_midnight[1] = $owg_str; } @@ -1158,13 +1235,17 @@ sub OWXCOUNT_SetPage($$$) { (prerequisite: Add this module's name to the list of clients in OWServer). Please define an OWX device or OWServer device first.


Example


- define OWX_C OWCOUNT DS2423 CE780F000000 300 + define OWC OWCOUNT 1D.CE780F000000 60
- attr OWX_C AName Water|volume + attr OWC AName Energie|energy
- attr OWX_C AUnit liters|l + attr OWC AUnit kWh|kWh
- attr OWX_CAMode daily + attr OWC APeriod hour +
+ attr OWC ARate Leistung|power +
+ attr OWX_AMode daily

@@ -1240,10 +1321,10 @@ sub OWXCOUNT_SetPage($$$) {

Attributes

+

For each of the following attributes, the channel identification A,B may be used.

  • attr <name> <channel>Name @@ -1252,6 +1333,9 @@ sub OWXCOUNT_SetPage($$$) {
  • attr <name> <channel>Unit <string>|<string>
    unit of measurement for this channel | its abbreviation.
  • +
  • attr <name> <channel>Rate + <string>|<string> +
    name for the channel rate | a type description for the measured value.
  • attr <name> <channel>Offset <float>
    offset added to the reading in this channel.
  • diff --git a/fhem/FHEM/21_OWID.pm b/fhem/FHEM/21_OWID.pm index 2c9342330..09f3aca07 100644 --- a/fhem/FHEM/21_OWID.pm +++ b/fhem/FHEM/21_OWID.pm @@ -24,6 +24,7 @@ # # get id => FAM_ID.ROM_ID.CRC # get present => 1 if device present, 0 if not +# get version => OWX version number # # ######################################################################################## @@ -51,11 +52,13 @@ use strict; use warnings; sub Log($$); +my $owx_version="3.21"; #-- declare variables my %gets = ( "present" => "", "interval" => "", - "id" => "" + "id" => "", + "version" => "" ); my %sets = ( "interval" => "" @@ -224,7 +227,7 @@ sub OWID_Get($@) { return "$name.id => $value"; } - #-- get interval + #-- get interval if($a[1] eq "interval") { $value = $hash->{INTERVAL}; return "$name.interval => $value"; @@ -243,6 +246,12 @@ sub OWID_Get($@) { } return "$name.present => $value"; } + + #-- get version + if( $a[1] eq "version") { + return "$name.version => $owx_version"; + } + } diff --git a/fhem/FHEM/21_OWLCD.pm b/fhem/FHEM/21_OWLCD.pm index c40e15953..61b75c3be 100644 --- a/fhem/FHEM/21_OWLCD.pm +++ b/fhem/FHEM/21_OWLCD.pm @@ -23,6 +23,7 @@ # get counter => four values (16 Bit) of the gpio counter # get version => firmware version of the LCD adapter # get memory => get one of the internal memory pages 0..6 +# get version => OWX version number # # set alert red|yellow|beep|none => set one of the alert states (gpio pins) # set icon on|off|blink => set one of the icons 0..14 @@ -61,6 +62,7 @@ use strict; use warnings; sub Log($$); +my $owx_version="3.21"; #-- controller may be HD44780 or KS0073 # these values have to be changed for different display # geometries or memory maps @@ -77,7 +79,7 @@ my %gets = ( "memory" => "", "gpio" => "", "counter" => "", - "version" => "", + "version" => "" #"register" => "", #"data" => "" ); @@ -253,7 +255,7 @@ sub OWLCD_Get($@) { #-- get version if($a[1] eq "version") { $value = OWXLCD_Get($hash,"version"); - return "$name.version => $value"; + return "$name.version => $owx_version (LCD firmware $value)"; } #-- get EEPROM content diff --git a/fhem/FHEM/21_OWMULTI.pm b/fhem/FHEM/21_OWMULTI.pm index bd3c0a5bc..44a390e01 100644 --- a/fhem/FHEM/21_OWMULTI.pm +++ b/fhem/FHEM/21_OWMULTI.pm @@ -28,6 +28,7 @@ # get temperature => temperature measurement # get VDD => supply voltage measurement # get V|raw => raw external voltage measurement +# get version => OWX version number # # set interval => set period for measurement # @@ -68,6 +69,7 @@ use strict; use warnings; sub Log($$); +my $owx_version="3.21"; #-- temperature and voltage globals - always the raw values from the device my $owg_temp; my $owg_volt; @@ -81,8 +83,9 @@ my %gets = ( "reading" => "", "temperature" => "", "VDD" => "", - "V" => "", + "VAD" => "", "raw" => "", + "version" => "" ); my %sets = ( @@ -210,80 +213,55 @@ sub OWMULTI_Define ($$) { readingsSingleUpdate($hash,"state","defined",1); Log 3, "OWMULTI: Device $name defined."; - #-- Start timer for initialization in a few seconds - InternalTimer(time()+10, "OWMULTI_InitializeDevice", $hash, 0); - #-- Start timer for updates - InternalTimer(time()+10+$hash->{INTERVAL}, "OWMULTI_GetValues", $hash, 0); + InternalTimer(time()+10, "OWMULTI_GetValues", $hash, 0); return undef; } ######################################################################################## # -# OWMULTI_InitializeDevice - delayed setting of initial readings and channel names +# OWMULTI_ChannelNames - find the real channel names # # Parameter hash = hash of device addressed # ######################################################################################## -sub OWMULTI_InitializeDevice($) { +sub OWMULTI_ChannelNames($) { my ($hash) = @_; my $name = $hash->{NAME}; - my @args; - - #-- unit attribute defined ? - $hash->{READINGS}{"temperature"}{UNIT} = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : "Celsius"; - $hash->{READINGS}{"temperature"}{TYPE} = "temperature"; - - #-- Initial readings - $owg_temp = ""; - $owg_volt = ""; - $owg_vdd = ""; + my $state = $hash->{READINGS}{"state"}{VAL}; + + my ($cname,@cnama,$unit,@unarr); + my ($tunit,$toffset,$tfactor,$tabbr,$vfunc); + #-- Set channel name, channel unit for voltage channel - my $cname = defined($attr{$name}{"VName"}) ? $attr{$name}{"VName"} : "voltage|voltage"; - my @cnama = split(/\|/,$cname); + $cname = defined($attr{$name}{"VName"}) ? $attr{$name}{"VName"} : "voltage|voltage"; + @cnama = split(/\|/,$cname); if( int(@cnama)!=2){ - Log 1, "OWMULTI: Incomplete channel name specification $cname. Better use $cname|"; + Log 1, "OWMULTI: Incomplete channel name specification $cname. Better use $cname|" + if( $state eq "defined"); push(@cnama,"unknown"); } #-- unit - my $unit = defined($attr{$name}{"VUnit"}) ? $attr{$name}{"VUnit"} : "Volt|V"; - my @unarr= split(/\|/,$unit); + $unit = defined($attr{$name}{"VUnit"}) ? $attr{$name}{"VUnit"} : "Volt|V"; + @unarr= split(/\|/,$unit); if( int(@unarr)!=2 ){ - Log 1, "OWMULTI: Incomplete channel unit specification $unit. Better use $unit|"; + Log 1, "OWMULTI: Incomplete channel unit specification $unit. Better use $unit|" + if( $state eq "defined"); push(@unarr,""); } #-- put into readings $owg_channel = $cnama[0]; - $hash->{READINGS}{"$owg_channel"}{TYPE} = $cnama[1]; - $hash->{READINGS}{"$owg_channel"}{UNIT} = $unarr[0]; - $hash->{READINGS}{"$owg_channel"}{UNITABBR} = $unarr[1]; + $hash->{READINGS}{$owg_channel}{TYPE} = $cnama[1]; + $hash->{READINGS}{$owg_channel}{UNIT} = $unarr[0]; + $hash->{READINGS}{$owg_channel}{UNITABBR} = $unarr[1]; - #-- Initialize all the display stuff - OWMULTI_FormatValues($hash); - -} - -######################################################################################## -# -# OWMULTI_FormatValues - put together various format strings -# -# Parameter hash = hash of device addressed, fs = format string -# -######################################################################################## - -sub OWMULTI_FormatValues($) { - my ($hash) = @_; - - my $name = $hash->{NAME}; - my ($tunit,$toffset,$tfactor,$tabbr,$tval,$vfunc,$vval); - my $svalue = ""; - - #-- attributes defined ? + #-- temperature scale + $hash->{READINGS}{"temperature"}{UNIT} = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : "Celsius"; $tunit = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : $hash->{READINGS}{"temperature"}{UNIT}; $toffset = defined($attr{$name}{"tempOffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ; $tfactor = 1.0; @@ -301,21 +279,64 @@ sub OWMULTI_FormatValues($) { $tabbr="?"; Log 1, "OWMULTI_FormatValues: unknown unit $tunit"; } + #-- these values are rather complex to obtain, therefore save them in the hash + $hash->{READINGS}{"temperature"}{TYPE} = "temperature"; $hash->{READINGS}{"temperature"}{UNIT} = $tunit; $hash->{READINGS}{"temperature"}{UNITABBR} = $tabbr; $hash->{tempf}{offset} = $toffset; $hash->{tempf}{factor} = $tfactor; +} + +######################################################################################## +# +# OWMULTI_InitializeDevice - delayed setting of initial readings and channel names +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWMULTI_InitializeDevice($) { + my ($hash) = @_; + + my $name = $hash->{NAME}; + + #-- Initial readings + $owg_temp = ""; + $owg_volt = ""; + $owg_vdd = ""; + +} + +######################################################################################## +# +# OWMULTI_FormatValues - put together various format strings +# +# Parameter hash = hash of device addressed, fs = format string +# +######################################################################################## + +sub OWMULTI_FormatValues($) { + my ($hash) = @_; + + my $name = $hash->{NAME}; + my ($toffset,$tfactor,$tval,$vfunc,$vval); + my $svalue = ""; #-- no change in any value if invalid reading - return if( $owg_temp eq ""); + return if( ($owg_temp eq "") || ($owg_vdd == 0) ); + + #-- obtain channel names + OWMULTI_ChannelNames($hash); + + #-- check if device needs to be initialized + OWMULTI_InitializeDevice($hash) + if( $hash->{READINGS}{"state"}{VAL} eq "defined"); #-- correct values for proper offset, factor - $tval = ($owg_temp + $toffset)*$tfactor; - - my $cname = defined($attr{$name}{"VName"}) ? $attr{$name}{"VName"} : "voltage|voltage"; - my @cnama = split(/\|/,$cname); - $owg_channel=$cnama[0]; + $toffset = $hash->{tempf}{offset}; + $tfactor = $hash->{tempf}{factor}; + $tval = ($owg_temp + $toffset)*$tfactor; #-- attribute VFunction defined ? $vfunc = defined($attr{$name}{"VFunction"}) ? $attr{$name}{"VFunction"} : "V"; @@ -338,11 +359,11 @@ sub OWMULTI_FormatValues($) { } #-- string buildup for return value, STATE - $svalue .= sprintf( "%s: %5.2f %s (T: %5.2f %s)", $owg_channel, $vval,$hash->{READINGS}{"$owg_channel"}{UNITABBR},$tval,$tabbr); + $svalue .= sprintf( "%s: %5.2f %s (T: %5.2f %s)", $owg_channel, $vval,$hash->{READINGS}{$owg_channel}{UNITABBR},$tval,$hash->{READINGS}{"temperature"}{UNITABBR}); #-- put into READINGS readingsBeginUpdate($hash); - readingsBulkUpdate($hash,"$owg_channel",$vval); + readingsBulkUpdate($hash,$owg_channel,$vval); readingsBulkUpdate($hash,"VDD",$owg_vdd); readingsBulkUpdate($hash,"temperature",$tval); @@ -407,6 +428,11 @@ sub OWMULTI_Get($@) { return "$name.interval => $value"; } + #-- get version + if( $a[1] eq "version") { + return "$name.version => $owx_version"; + } + #-- reset presence $hash->{PRESENT} = 0; @@ -427,12 +453,16 @@ sub OWMULTI_Get($@) { return "OWMULTI: Could not get values from device $name, reason $ret"; } $hash->{PRESENT} = 1; - OWMULTI_FormatValues($hash); #-- return the special reading if ($reading eq "reading") { - return "OWMULTI: $name.reading => ". - $hash->{READINGS}{"$owg_channel"}{VAL}; + return "OWMULTI: $name.reading => ".OWMULTI_FormatValues($hash); + } + + #-- return the special reading + if ($reading eq "VAD") { + return "OWMULTI: $name.VAD => ". + $hash->{READINGS}{$owg_channel}{VAL}; } if ($reading eq "temperature") { return "OWMULTI: $name.temperature => ". @@ -442,7 +472,7 @@ sub OWMULTI_Get($@) { return "OWMULTI: $name.VDD => ". $hash->{READINGS}{"VDD"}{VAL}; } - if ( ($reading eq "V")|($reading eq "raw")) { + if ( $reading eq "raw") { return "OWMULTI: $name.V => ". $owg_volt; } @@ -483,14 +513,12 @@ sub OWMULTI_GetValues($@) { }elsif( $interface eq "OWServer" ){ $ret = OWFSMULTI_GetValues($hash); }else{ - Log 3, "OWMULTI: GetValues with wrong IODev type $interface"; - return 1; + return "OWMULTI: GetValues with wrong IODev type $interface"; } #-- process results if( defined($ret) ){ - Log 3, "OWMULTI: Could not get values from device $name, reason $ret"; - return 1; + return "OWMULTI: Could not get values from device $name, reason $ret"; } $hash->{PRESENT} = 1; @@ -825,10 +853,6 @@ sub OWXMULTI_GetValues($) { $owg_volt = ($msb*256+ $lsb)/100; return undef; - - #} else { - # return "OWXMULTI: Unknown device family $hash->{OW_FAMILY}\n"; - #} } ####################################################################################### @@ -886,8 +910,8 @@ sub OWXMULTI_SetValues($@) {

    FHEM module to commmunicate with 1-Wire multi-sensors, currently the DS2438 smart battery monitor

    This 1-Wire module works with the OWX interface module or with the OWServer interface module (prerequisite: Add this module's name to the list of clients in OWServer). - Please define an OWX device or OWServer device first.

    -

    Example

    + Please define an OWX device or OWServer device first.

    +

    Example

    define OWX_M OWMULTI 7C5034010000 45
    @@ -896,14 +920,13 @@ sub OWXMULTI_SetValues($@) { attr OWX_M VUnit percent|%
    attr OWX_M VFunction (161.29 * V / VDD - 25.8065)/(1.0546 - 0.00216 * T) -
    -


    +

    Define

    define <name> OWMULTI [<model>] <id> [<interval>] or
    define <name> OWMULTI <fam>.<id> [<interval>] -

    Define a 1-Wire multi-sensor

    +

    Define a 1-Wire multi-sensor

    • [<model>]
      Defines the sensor model (and thus 1-Wire family @@ -925,7 +948,6 @@ sub OWXMULTI_SetValues($@) { <interval>
      Measurement interval in seconds. The default is 300 seconds.
    -

    Set

      @@ -933,7 +955,6 @@ sub OWXMULTI_SetValues($@) { set <name> interval <int>
      Measurement interval in seconds. The default is 300 seconds.
    -

    Get

      @@ -948,7 +969,9 @@ sub OWXMULTI_SetValues($@) { get <name> interval
      Returns measurement interval in seconds.
    • - get <name> reading
      Obtain the measurement value from + get <name> reading
      Obtain the measurement values
    • +
    • + get <name> VAD
      Obtain the measurement value from VFunction.
    • get <name> temperature
      Obtain the temperature value.
    • @@ -958,7 +981,6 @@ sub OWXMULTI_SetValues($@) { get <name> V or get <name> raw
      Obtain the raw external voltage measurement.
    -

    Attributes

      diff --git a/fhem/FHEM/21_OWSWITCH.pm b/fhem/FHEM/21_OWSWITCH.pm index 2d7222277..6d74c5797 100644 --- a/fhem/FHEM/21_OWSWITCH.pm +++ b/fhem/FHEM/21_OWSWITCH.pm @@ -30,6 +30,7 @@ # state of 1 = OFF therefore corresponds to an output state of 1 = OFF, but a measured # state of 0 = ON can also be due to an external shortening of the output. # get gpio => values for channels +# get version => OWX version number # # set interval => set period for measurement # set output on|off|on-for-timer |on-for-timer @@ -74,9 +75,11 @@ use strict; use warnings; sub Log($$); -#-- channel name - fixed is the first array, variable the second -my @owg_fixed = ("A","B","C","D","E","F","G","H"); -my @owg_channel; +my $owx_version="3.21"; +#-- fixed raw channel name, flexible channel name +my @owg_fixed = ("A","B","C","D","E","F","G","H"); +my @owg_channel = ("A","B","C","D","E","F","G","H"); + #-- channel values - always the raw input resp. output values from the device my @owg_val; my @owg_vax; @@ -86,7 +89,8 @@ my %gets = ( "present" => "", "interval" => "", "input" => "", - "gpio" => "" + "gpio" => "", + "version" => "" ); my %sets = ( @@ -133,7 +137,7 @@ sub OWSWITCH_Initialize ($) { "stateS ". $readingFnAttributes; - #-- correct list of attributes + #-- initial list of attributes for( my $i=0;$i<8;$i++ ){ $attlist .= " ".$owg_fixed[$i]."Name"; $attlist .= " ".$owg_fixed[$i]."Unit"; @@ -185,15 +189,12 @@ sub OWSWITCH_Define ($$) { if(int(@a)>=4) { $interval = $a[3]; } if( $fam eq "3A" ){ $model = "DS2413"; - @owg_fixed = ("A","B"); CommandAttr (undef,"$name model DS2413"); }elsif( $fam eq "12" ){ $model = "DS2406"; - @owg_fixed = ("A","B"); CommandAttr (undef,"$name model DS2406"); }elsif( $fam eq "29" ){ $model = "DS2408"; - @owg_fixed = ("A","B","C","D","E","F","G","H"); CommandAttr (undef,"$name model DS2408"); }else{ return "OWSWITCH: Wrong 1-Wire device family $fam"; @@ -205,15 +206,12 @@ sub OWSWITCH_Define ($$) { if(int(@a)>=5) { $interval = $a[4]; } if( $model eq "DS2413" ){ $fam = "3A"; - @owg_fixed = ("A","B"); CommandAttr (undef,"$name model DS2413"); }elsif( $model eq "DS2406" ){ $fam = "12"; - @owg_fixed = ("A","B"); CommandAttr (undef,"$name model DS2406"); }elsif( $model eq "DS2408" ){ $fam = "29"; - @owg_fixed = ("A","B","C","D","E","F","G","H"); CommandAttr (undef,"$name model DS2408"); }else{ return "OWSWITCH: Wrong 1-Wire device model $model"; @@ -221,7 +219,7 @@ sub OWSWITCH_Define ($$) { } else { return "OWSWITCH: $a[0] ID $a[2] invalid, specify a 12 or 2.12 digit value"; } - + #-- determine CRC Code - only if this is a direct interface $crc = defined($hash->{IODev}->{INTERFACE}) ? sprintf("%02x",OWX_CRC($fam.".".$id."00")) : "00"; @@ -244,19 +242,57 @@ sub OWSWITCH_Define ($$) { #-- readingsSingleUpdate($hash,"state","defined",1); Log 3, "OWSWITCH: Device $name defined."; - - #-- Initialization reading according to interface type - my $interface= $hash->{IODev}->{TYPE}; - - #-- Start timer for initialization in a few seconds - InternalTimer(time()+10, "OWSWITCH_InitializeDevice", $hash, 0); #-- Start timer for updates - InternalTimer(time()+10+$hash->{INTERVAL}, "OWSWITCH_GetValues", $hash, 0); + InternalTimer(time()+10, "OWSWITCH_GetValues", $hash, 0); return undef; } +######################################################################################## +# +# OWSWITCH_ChannelNames - find the real channel names +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWSWITCH_ChannelNames($) { + my ($hash) = @_; + + my $name = $hash->{NAME}; + my $state = $hash->{READINGS}{"state"}{VAL}; + + my ($cname,@cnama,$unit,@unarr); + + for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ + #-- name + $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : $owg_fixed[$i]."|onoff"; + @cnama = split(/\|/,$cname); + if( int(@cnama)!=2){ + Log 1, "OWSWITCH: Incomplete channel name specification $cname. Better use $cname|" + if( $state eq "defined"); + push(@cnama,"unknown"); + } + #-- put into readings + $owg_channel[$i] = $cnama[0]; + $hash->{READINGS}{$owg_channel[$i]}{TYPE} = $cnama[1]; + + #-- unit + my $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "ON|OFF"; + my @unarr= split(/\|/,$unit); + if( int(@unarr)!=2 ){ + Log 1, "OWSWITCH: Wrong channel unit specification $unit, replaced by ON|OFF" + if( $state eq "defined"); + $unit="ON|OFF"; + } + + #-- put into readings + $hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unit; + $hash->{READINGS}{$owg_channel[$i]}{UNITABBR} = $unit; + } +} + ######################################################################################## # # OWSWITCH_InitializeDevice - delayed setting of initial readings and channel names @@ -266,55 +302,16 @@ sub OWSWITCH_Define ($$) { ######################################################################################## sub OWSWITCH_InitializeDevice($) { + my ($hash) = @_; - my $name = $hash->{NAME}; - - #-- Set channel names, channel units + + #-- Initial readings for( my $i=0;$i<$cnumber{$attr{$name}{"model"}} ;$i++) { #-- Initial readings ERR $owg_val[$i] = 1; $owg_vax[$i] = 0; - #-- name - my $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : $owg_fixed[$i]."|onoff"; - my @cnama = split(/\|/,$cname); - if( int(@cnama)!=2){ - Log 1, "OWSWITCH: Incomplete channel name specification $cname. Better use $cname|"; - push(@cnama,"unknown"); - } - - #-- unit - my $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "ON|OFF"; - my @unarr= split(/\|/,$unit); - if( int(@unarr)!=2 ){ - Log 1, "OWSWITCH: Wrong channel unit specification $unit, replaced by ON|OFF"; - $unit="ON|OFF"; - } - - #-- put into readings - $owg_channel[$i] = $cnama[0]; - $hash->{READINGS}{"$owg_channel[$i]"}{TYPE} = $cnama[1]; - $hash->{READINGS}{"$owg_channel[$i]"}{UNIT} = $unit; - $hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR} = $unit; } - - #-- set status according to interface type - my $interface= $hash->{IODev}->{TYPE}; - - #-- OWX interface - if( !defined($interface) ){ - return "OWSWITCH: Interface missing"; - } elsif( $interface eq "OWX" ){ - #-- OWFS interface - #}elsif( $interface eq "OWFS" ){ - # $ret = OWFSAD_GetPage($hash,"reading"); - #-- Unknown interface - }else{ - return "OWSWITCH: InitializeDevice with wrong IODev type $interface"; - } - - #-- Initialize all the display stuff - OWSWITCH_FormatValues($hash); } ######################################################################################## @@ -329,20 +326,24 @@ sub OWSWITCH_FormatValues($) { my ($hash) = @_; my $name = $hash->{NAME}; - my ($offset,$factor,$vval,$vvax,$vstr,$cname,$unit,@unarr,@cnama,$valid); + my ($offset,$factor,$vval,$vvax,$vstr,@unarr,$valid); my $svalue = ""; #-- external shortening signature my $sname = defined($attr{$name}{"stateS"}) ? $attr{$name}{"stateS"} : "☇"; + #-- obtain channel names + OWSWITCH_ChannelNames($hash); + + #-- check if device needs to be initialized + OWSWITCH_InitializeDevice($hash) + if( $hash->{READINGS}{"state"}{VAL} eq "defined"); + #-- put into READINGS readingsBeginUpdate($hash); #-- formats for output for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ - $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : $owg_fixed[$i]; - @cnama = split(/\|/,$cname); - $owg_channel[$i]=$cnama[0]; #-- input state is 0 = ON or 1 = OFF $vval = $owg_val[$i]; @@ -350,8 +351,7 @@ sub OWSWITCH_FormatValues($) { $vvax = $owg_vax[$i]; #-- string buildup for return value and STATE - $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "ON|OFF"; - @unarr= split(/\|/,$unit); + @unarr= split(/\|/,$hash->{READINGS}{$owg_channel[$i]}{UNIT}); $vstr = $unarr[$vval]; #-- put into readings only when valid @@ -359,7 +359,7 @@ sub OWSWITCH_FormatValues($) { $vstr ="???" }else{ $vstr.= $sname if( ($vval == 0) && ($vvax == 1) ); - readingsBulkUpdate($hash,"$owg_channel[$i]",$vstr); + readingsBulkUpdate($hash,$owg_channel[$i],$vstr); } $svalue .= sprintf( "%s: %s" , $owg_channel[$i], $vstr); @@ -367,7 +367,6 @@ sub OWSWITCH_FormatValues($) { if( $i<($cnumber{$attr{$name}{"model"}}-1) ){ $svalue .= " "; } - } #-- STATE @@ -393,9 +392,7 @@ sub OWSWITCH_Get($@) { my $model = $hash->{OW_MODEL}; my ($value,$value2,$value3) = (undef,undef,undef); my $ret = ""; - my $offset; - my $factor; - my $page; + my ($offset,$factor,$page,$cname,@cnama,@channel); #-- check syntax return "OWSWITCH: Get argument is missing @a" @@ -426,14 +423,21 @@ sub OWSWITCH_Get($@) { return "$name.interval => $value"; } + #-- get version + if( $a[1] eq "version") { + return "$name.version => $owx_version"; + } + #-- reset presence $hash->{PRESENT} = 0; + #-- get channel names + OWSWITCH_ChannelNames($hash); + #-- get values according to interface type my $interface= $hash->{IODev}->{TYPE}; #-- get single state - # TODO: WAS passiert, wenn channel name noch falsch ist ? if( $reading eq "input" ){ return "OWSWITCH: get needs parameter when reading input: " if( int(@a)<2 ); @@ -451,17 +455,16 @@ sub OWSWITCH_Get($@) { if( $interface eq "OWX" ){ $ret = OWXSWITCH_GetState($hash); #-- OWFS interface - #}elsif( $interface eq "OWFS" ){ - # $ret = OWFSSWITCH_GetPage($hash,"reading"); + }elsif( $interface eq "OWFS" ){ + $ret = OWFSSWITCH_GetState($hash); #-- Unknown interface }else{ return "OWSWITCH: Get with wrong IODev type $interface"; } #-- process results OWSWITCH_FormatValues($hash); - my @states = split(/,/,$hash->{STATE}); - - return $a[2]." = ".$states[$fnd]; + $hash->{PRESENT} = 1; + return $name.".".$a[2]." => ".$hash->{READINGS}{$owg_channel[$fnd]}{VAL}; #-- get all states }elsif( $reading eq "gpio" ){ @@ -475,14 +478,13 @@ sub OWSWITCH_Get($@) { }else{ return "OWSWITCH: Get with wrong IODev type $interface"; } + #-- process results + if( defined($ret) ){ + return "OWSWITCH: Could not get values from device $name, reason $ret"; + } + $hash->{PRESENT} = 1; + return "OWSWITCH: $name.$reading => ".OWSWITCH_FormatValues($hash); } - #-- process results - if( defined($ret) ){ - return "OWSWITCH: Could not get values from device $name, reason $ret"; - } - $hash->{PRESENT} = 1; - return "OWSWITCH: $name.$reading => ".OWSWITCH_FormatValues($hash); - } ####################################################################################### @@ -558,6 +560,11 @@ sub OWSWITCH_Set($@) { my $key = $a[1]; my $value = $a[2]; + my $name = $hash->{NAME}; + my $model = $hash->{OW_MODEL}; + + my ($ret,$cname,@cnama,@channel); + #-- for the selector: which values are possible if (@a == 2){ my $newkeys = join(" ", sort keys %sets); @@ -569,20 +576,12 @@ sub OWSWITCH_Set($@) { return "OWSWITCH: Set with unknown argument $a[1]"; } - #-- define vars - my $ret = undef; - my $channel = undef; - my $channo = undef; - my $condx; - my $name = $hash->{NAME}; - my $model = $hash->{OW_MODEL}; - #-- reset the device if($key eq "init") { - return "OWCOUNT: init needs parameter 'yes'" + return "OWSWITCH: init needs parameter 'yes'" if($value ne "yes"); OWSWITCH_InitializeDevice($hash); - return "OWCOUNT: Re-initialized device"; + return "OWSWITCH: Re-initialized device $name"; } #-- set new timer interval @@ -596,18 +595,21 @@ sub OWSWITCH_Set($@) { InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWSWITCH_GetValues", $hash, 1); return undef; } + + #-- obtain channel names + OWSWITCH_ChannelNames($hash); #-- Set readings according to interface type my $interface= $hash->{IODev}->{TYPE}; #-- set single state - # TODO: WAS passiert, wenn channel name noch falsch ist ? if( $key eq "output" ){ return "OWSWITCH: get needs parameter when writing output: " if( int(@a)<2 ); #-- find out which channel we have my $fnd=undef; for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ + Log 1," testing $a[2] against $owg_channel[$i] and $owg_fixed[$i]"; if( ($a[2] eq $owg_channel[$i]) || ($a[2] eq $owg_fixed[$i]) ){ $fnd=$i; last; @@ -724,8 +726,6 @@ sub OWSWITCH_Undef ($) { # # Prefix = OWFSSWITCH # -######################################################################################## - ######################################################################################## # # OWFSSWITCH_GetState - Get gpio ports from device @@ -1103,23 +1103,21 @@ sub OWXSWITCH_SetState($$) {

      FHEM module to commmunicate with 1-Wire Programmable Switches

      This 1-Wire module works with the OWX interface module or with the OWServer interface module (prerequisite: Add this module's name to the list of clients in OWServer). - Please define an OWX device or OWServer device first.

      -

      Example

      + Please define an OWX device or OWServer device first.

      +

      Example

      define OWX_S OWSWITCH DS2413 B5D502000000 60
      attr OWX_S AName Lampe|light
      attr OWX_S AUnit AN|AUS -

      -

      Define

      define <name> OWSWITCH [<model>] <id> [<interval>] or
      define <name> OWSWITCH <fam>.<id> [<interval>] -

      Define a 1-Wire switch.

      +

      Define a 1-Wire switch.

      • [<model>]
        Defines the switch model (and thus 1-Wire family @@ -1162,7 +1160,6 @@ sub OWXSWITCH_SetState($$) {
      • set <name> init yes
        Re-initialize the device
      -

      Get

        @@ -1186,7 +1183,6 @@ sub OWXSWITCH_SetState($$) {
      • get <name> gpio
        Obtain state of all channels
      -

      Attributes

      For each of the following attributes, the channel identification A,B,... may be used.
        diff --git a/fhem/FHEM/21_OWTHERM.pm b/fhem/FHEM/21_OWTHERM.pm index 9561a07bb..3c176a12f 100755 --- a/fhem/FHEM/21_OWTHERM.pm +++ b/fhem/FHEM/21_OWTHERM.pm @@ -29,6 +29,7 @@ # get interval => query interval # get temperature => temperature measurement # get alarm => alarm temperature settings +# get version => OWX version number # # set interval => set period for measurement # set tempLow => lower alarm temperature setting @@ -40,6 +41,9 @@ # attr stateAH "" = character string for denoting high alarm condition, default is up triangle # attr tempOffset = temperature offset in degree Celsius added to the raw temperature reading # attr tempUnit = unit of measurement, e.g. Celsius/Kelvin/Fahrenheit or C/K/F, default is Celsius +# attr tempConv onkick|onread = determines, whether a temperature measurement will happen when "kicked" +# through the OWX backend module (all temperature sensors at the same time), or on +# reading the sensor (1 second waiting time). # attr tempLow = value for low alarm # attr tempHigh = value for high alarm # @@ -68,6 +72,7 @@ use strict; use warnings; sub Log($$); +my $owx_version="3.21"; #-- temperature globals - always the raw values from/for the device my $owg_temp = ""; my $owg_th = ""; @@ -82,7 +87,8 @@ my %gets = ( "present" => "", "interval" => "", "temperature" => "", - "alarm" => "" + "alarm" => "", + "version" => "" ); my %sets = ( @@ -122,7 +128,7 @@ sub OWTHERM_Initialize ($) { $hash->{AttrList}= "IODev model:DS1820,DS18B20,DS1822 loglevel:0,1,2,3,4,5 ". "stateAL stateAH ". "tempOffset tempUnit:C,Celsius,F,Fahrenheit,K,Kelvin ". - "tempLow tempHigh ". + "tempConv:onkick,onread tempLow tempHigh ". $readingFnAttributes; } @@ -274,6 +280,23 @@ sub OWTHERM_InitializeDevice($) { $hash->{tempf}{offset} = $offset; $hash->{tempf}{factor} = $factor; + #-- Check if temperature conversion is consistent + if( $interface eq "OWX" ){ + if( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){ + if( !(defined($attr{$hash->{IODev}->{NAME}}{dokick})) || + ( defined($attr{$hash->{IODev}->{NAME}}{dokick}) && ($attr{$hash->{IODev}->{NAME}}{dokick} eq "0") )){ + Log 1,"OWTHERM: Attribute tempConv=onkick changed to onread for $name because interface is not kicking"; + $attr{$name}{tempConv}="onread"; + } + } + }elsif( $interface eq "OWServer" ){ + if( !(defined($attr{$name}{tempConv})) || + (defined($attr{$name}{tempConv}) && ($attr{$name}{tempConv} eq "onread") ) ){ + Log 1,"OWTHERM: Attribute tempConv=onread changed to onkick for $name because interface is OWFS"; + $attr{$name}{tempConv}="onread"; + } + } + #-- Set the attribute values if defined if( defined($attr{$name}{"tempLow"}) ){ $value = $attr{$name}{"tempLow"}; @@ -437,11 +460,16 @@ sub OWTHERM_Get($@) { } #-- get interval - if($reading eq "interval") { + if($a[1] eq "interval") { $value = $hash->{INTERVAL}; return "$name.interval => $value"; } + #-- get version + if( $a[1] eq "version") { + return "$name.version => $owx_version"; + } + #-- reset presence $hash->{PRESENT} = 0; @@ -778,9 +806,10 @@ sub OWXTHERM_GetValues($) { my $owx_dev = $hash->{ROM_ID}; #-- hash of the busmaster my $master = $hash->{IODev}; + my $name = $hash->{NAME}; - #-- check, if the conversion has been called before - only on devices with real power - if( defined($attr{$hash->{IODev}->{NAME}}{buspower}) && ( $attr{$hash->{IODev}->{NAME}}{buspower} eq "real") ){ + #-- check, if the conversion has been called before for all sensors + if( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){ $con=0; } @@ -981,7 +1010,9 @@ sub OWXTHERM_SetValues($@) {
        • set <name> interval <int>
          Temperature - measurement intervall in seconds. The default is 300 seconds.
        • + readout intervall in seconds. The default is 300 seconds. Attention:This is the + readout interval. Whether an actual temperature measurement is performed, is determined by the + tempConv attribute
        • set <name> tempHigh <float>
          The high alarm temperature (on the temperature scale chosen by the attribute @@ -1022,6 +1053,12 @@ sub OWXTHERM_SetValues($@) {
          character string for denoting high alarm condition, default is upward triangle, e.g. the code &#x25B4; leading to the sign ▴
        • +
        • + attr <name> tempConv onkick|onread + +
          determines, whether a temperature measurement will happen when "kicked" + through the OWX backend module (all temperature sensors at the same time), or on + reading the sensor (1 second waiting time, default).
        • attr <name> tempOffset <float>
          temperature offset in °C added to the raw temperature reading.