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 ▴ 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.