2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 16:56:54 +00:00

21_OWID.pm: Neue Version 7.0, angepasst an OWX Next Generation.

21_OWVAR.pm: Neue Version 7.0, angepasst an OWX Next Generation.
21_OWTHERM.pm: Neue Version 7.0, angepasst an OWX Next Generation.

git-svn-id: https://svn.fhem.de/fhem/trunk@14699 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
phenning 2017-07-13 08:07:17 +00:00
parent 01ab9f74f0
commit 2dffd5cf20
3 changed files with 217 additions and 321 deletions

View File

@ -11,25 +11,6 @@
# #
######################################################################################## ########################################################################################
# #
# define <name> OWID <FAM_ID> <ROM_ID> [interval] or OWID <FAM_ID>.<ROM_ID> [interval]
#
# where <name> may be replaced by any name string
#
# <FAM_ID> is a 2 character (1 byte) 1-Wire Family ID
#
# <ROM_ID> is a 12 character (6 byte) 1-Wire ROM ID
# without Family ID, e.g. A2D90D000800
# [interval] is an optional query interval in seconds
#
# set <name> interval => set query interval for checking presence
#
# get <name> id => FAM_ID.ROM_ID.CRC
# get <name> present => 1 if device present, 0 if not
# get <name> version => OWX version number
#
#
########################################################################################
#
# This programm is free software; you can redistribute it and/or modify # This programm is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # the Free Software Foundation; either version 2 of the License, or
@ -68,11 +49,10 @@ use ProtoThreads;
no warnings 'deprecated'; no warnings 'deprecated';
sub Log3($$$); sub Log3($$$);
my $owx_version="6.1"; my $owx_version="7.0";
#-- declare variables #-- declare variables
my %gets = ( my %gets = (
"present" => "", "present" => "",
"interval" => "",
"id" => "", "id" => "",
"version" => "" "version" => ""
); );
@ -215,10 +195,8 @@ sub OWID_Define ($$) {
$hash->{NOTIFYDEV} = "global"; $hash->{NOTIFYDEV} = "global";
if ($init_done) {
return OWID_Init($hash); return OWID_Init($hash);
}
return undef;
} }
######################################################################################### #########################################################################################
@ -249,7 +227,7 @@ sub OWID_Init ($) {
my ($hash)=@_; my ($hash)=@_;
#-- Start timer for updates #-- Start timer for updates
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+10, "OWID_GetValues", $hash, 0); InternalTimer(gettimeofday()+30, "OWID_GetValues", $hash, 0);
#-- #--
readingsSingleUpdate($hash,"state","Initialized",1); readingsSingleUpdate($hash,"state","Initialized",1);
@ -280,9 +258,9 @@ sub OWID_Attr(@) {
#-- interval modified at runtime #-- interval modified at runtime
$key eq "interval" and do { $key eq "interval" and do {
#-- check value #-- check value
return "OWID: Set with short interval, must be > 1" if(int($value) < 1); return "OWID: set $name interval must be >= 0" if(int($value) < 0);
#-- update timer #-- update timer
$hash->{INTERVAL} = $value; $hash->{INTERVAL} = int($value);
if ($init_done) { if ($init_done) {
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0); InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0);
@ -337,26 +315,31 @@ sub OWID_Get($@) {
return "$name.id => $value"; return "$name.id => $value";
} }
#-- get interval
if($a[1] eq "interval") {
$value = $hash->{INTERVAL};
return "$name.interval => $value";
}
#-- get present #-- get present
if($a[1] eq "present") { if($a[1] eq "present") {
#-- hash of the busmaster #-- hash of the busmaster
my $master = $hash->{IODev}; my $master = $hash->{IODev};
#-- asynchronous mode my $interface = $master->{TYPE};
if( $hash->{ASYNC} ){
#-- OWX interface
if( $interface eq "OWX" ){
$value = OWX_Verify($master,$name,$hash->{ROM_ID},0);
#-- OWX_ASYNC interface
}elsif( $interface eq "OWX_ASYNC" ){
eval { eval {
OWX_ASYNC_RunToCompletion($hash,OWX_ASYNC_PT_Verify($hash)); OWX_ASYNC_RunToCompletion($hash,OWX_ASYNC_PT_Verify($hash));
}; };
return GP_Catch($@) if $@; return GP_Catch($@) if $@;
return "$name.present => ".ReadingsVal($name,"present","unknown");
#-- Unknown interface
} else { } else {
$value = OWX_Verify($master,$hash->{ROM_ID}); return "OWID: Verification not yet implemented for interface $interface";
} }
#-- process results
if( $master->{ASYNCHRONOUS} ){
return undef;
}else{
#-- generate an event only if presence has changed
if( $value == 0 ){ if( $value == 0 ){
readingsSingleUpdate($hash,"present",0,$hash->{PRESENT}); readingsSingleUpdate($hash,"present",0,$hash->{PRESENT});
} else { } else {
@ -365,6 +348,7 @@ sub OWID_Get($@) {
$hash->{PRESENT} = $value; $hash->{PRESENT} = $value;
return "$name.present => $value"; return "$name.present => $value";
} }
}
#-- get version #-- get version
if( $a[1] eq "version") { if( $a[1] eq "version") {
@ -389,23 +373,33 @@ sub OWID_GetValues($) {
my $offset; my $offset;
my $factor; my $factor;
#-- restart timer for updates
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
#-- auto-update for device disabled;
return undef
if( $hash->{INTERVAL} == 0 );
#-- restart timer for updates
InternalTimer(time()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0); InternalTimer(time()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0);
#-- hash of the busmaster #-- hash of the busmaster
my $master = $hash->{IODev}; my $master = $hash->{IODev};
my $interface = $master->{TYPE};
if( $hash->{ASYNC} ){ #-- OWX interface
if( $interface eq "OWX" ){
$value = OWX_Verify($master,$name,$hash->{ROM_ID},0);
#-- OWX_ASYNC interface
}elsif( $interface eq "OWX_ASYNC" ){
eval { eval {
OWX_ASYNC_Schedule($hash,OWX_ASYNC_PT_Verify($hash)); OWX_ASYNC_RunToCompletion($hash,OWX_ASYNC_PT_Verify($hash));
}; };
return GP_Catch($@) if $@; return GP_Catch($@) if $@;
return undef;
} else {
$value = OWX_Verify($master,$hash->{ROM_ID});
} }
#-- process results
if( $master->{ASYNCHRONOUS} ){
return undef;
}else{
#-- generate an event only if presence has changed #-- generate an event only if presence has changed
if( $value == 0 ){ if( $value == 0 ){
readingsSingleUpdate($hash,"present",0,$hash->{PRESENT}); readingsSingleUpdate($hash,"present",0,$hash->{PRESENT});
@ -413,6 +407,8 @@ sub OWID_GetValues($) {
readingsSingleUpdate($hash,"present",1,!$hash->{PRESENT}); readingsSingleUpdate($hash,"present",1,!$hash->{PRESENT});
} }
$hash->{PRESENT} = $value; $hash->{PRESENT} = $value;
return "$name.present => $value";
}
} }
####################################################################################### #######################################################################################
@ -449,10 +445,10 @@ sub OWID_Set($@) {
#-- set new timer interval #-- set new timer interval
if($key eq "interval") { if($key eq "interval") {
# check value # check value
return "OWID: Set with short interval, must be > 1" return "OWID: Set $name interval must be >= 0"
if(int($value) < 1); if(int($value) < 0);
# update timer # update timer
$hash->{INTERVAL} = $value; $hash->{INTERVAL} = int($value);
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0); InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0);
return undef; return undef;
@ -533,7 +529,9 @@ sub OWID_Undef ($) {
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li> <br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
</ul> </ul>
<h4>Attributes</h4> <h4>Attributes</h4>
<ul> <ul><li><a name="owtherm_interval2">
<code>attr &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update.</li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li> <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul> </ul>

View File

@ -11,44 +11,6 @@
# #
######################################################################################## ########################################################################################
# #
# define <name> OWTHERM [<model>] <ROM_ID> [interval] or <FAM_ID>.<ROM_ID> [interval]
#
# where <name> may be replaced by any name string
#
# <model> is a 1-Wire device type. If omitted AND no FAM_ID given we assume this to be an
# DS1820 temperature sensor. Currently allowed values are DS1820, DS18B20, DS1822
# <FAM_ID> is a 1-Wire family id, currently allowed values are 10, 22, 28
# <ROM_ID> is a 12 character (6 byte) 1-Wire ROM ID
# without Family ID, e.g. A2D90D000800
# [interval] is an optional query interval in seconds
#
# get <name> id => FAM_ID.ROM_ID.CRC
# get <name> present => 1 if device present, 0 if not
# get <name> interval => query interval
# get <name> temperature => temperature measurement
# get <name> alarm => alarm temperature settings
# get <name> version => OWX version number
#
# set <name> interval => period for measurement
# set <name> tempLow => lower alarm temperature setting
# set <name> tempHigh => higher alarm temperature setting
#
# Additional attributes are defined in fhem.cfg
#
# attr <name> stateAL "<string>" = character string for denoting low alarm condition, default is ↓
# attr <name> stateAH "<string>" = character string for denoting high alarm condition, default is ↑
# attr <name> tempOffset <float> = temperature offset in degree Celsius added to the raw temperature reading
# attr <name> tempUnit <string> = unit of measurement, e.g. Celsius/Kelvin/Fahrenheit, default is Celsius
# 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).
# attr <name> resolution 9|10|11|12 = resolution in bit for measurement
# attr <name> interval <floar> = period for measurement
# attr <name> tempLow <float> = lower alarm temperature setting
# attr <name> tempHigh <float> = higher alarm temperature setting
#
########################################################################################
#
# This programm is free software; you can redistribute it and/or modify # This programm is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # the Free Software Foundation; either version 2 of the License, or
@ -86,12 +48,10 @@ no warnings 'deprecated';
sub Log3($$$); sub Log3($$$);
sub AttrVal($$$); sub AttrVal($$$);
my $owx_version="6.1"; my $owx_version="7.0";
my %gets = ( my %gets = (
"id" => "", "id" => "",
"present" => "",
"interval" => "",
"temperature" => "", "temperature" => "",
"alarm" => "", "alarm" => "",
"version" => "" "version" => ""
@ -114,7 +74,7 @@ my %convtimes = (
9 => 100, 9 => 100,
10 => 200, 10 => 200,
11 => 400, 11 => 400,
12 => 800, 12 => 1000,
); );
######################################################################################## ########################################################################################
@ -273,7 +233,6 @@ sub OWTHERM_Define ($$) {
# #
######################################################################################## ########################################################################################
sub OWTHERM_Notify ($$) { sub OWTHERM_Notify ($$) {
my ($hash,$dev) = @_; my ($hash,$dev) = @_;
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) { if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
@ -291,7 +250,6 @@ sub OWTHERM_Notify ($$) {
# #
######################################################################################## ########################################################################################
sub OWTHERM_Init ($) { sub OWTHERM_Init ($) {
my ($hash)=@_; my ($hash)=@_;
#-- Start timer for updates #-- Start timer for updates
@ -320,9 +278,9 @@ sub OWTHERM_Attr(@) {
#-- interval modified at runtime #-- interval modified at runtime
$key eq "interval" and do { $key eq "interval" and do {
#-- check value #-- check value
return "OWTHERM: Set with short interval, must be > 1" if(int($value) < 1); return "OWTHERM: set $name interval must be >=0" if(int($value) < 0);
#-- update timer #-- update timer
$hash->{INTERVAL} = $value; $hash->{INTERVAL} = int($value);
if ($init_done) { if ($init_done) {
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
@ -427,6 +385,8 @@ sub OWTHERM_FormatValues($) {
} else { } else {
$hash->{ALARM} = 0; $hash->{ALARM} = 0;
} }
main::OWX_Alarms($hash->{IODev})
if( $hash->{ALARM} );
#-- put into READINGS #-- put into READINGS
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
@ -476,33 +436,6 @@ sub OWTHERM_Get($@) {
#-- Get other values according to interface type #-- Get other values according to interface type
my $interface= $hash->{IODev}->{TYPE}; my $interface= $hash->{IODev}->{TYPE};
#-- get present
if($a[1] eq "present" ) {
#-- OWX interface
if( $interface =~ /^OWX/ ){
#-- asynchronous mode
if( $hash->{ASYNC} ){
eval {
OWX_ASYNC_RunToCompletion($hash,OWX_ASYNC_PT_Verify($hash));
};
return GP_Catch($@) if $@;
return "$name.present => ".ReadingsVal($name,"present","unknown");
} else {
$value = OWX_Verify($master,$hash->{ROM_ID});
}
$hash->{PRESENT} = $value;
return "$name.present => $value";
} else {
return "OWTHERM: Verification not yet implemented for interface $interface";
}
}
#-- get interval
if($a[1] eq "interval") {
$value = $hash->{INTERVAL};
return "$name.interval => $value";
}
#-- get version #-- get version
if( $a[1] eq "version") { if( $a[1] eq "version") {
return "$name.version => $owx_version"; return "$name.version => $owx_version";
@ -510,13 +443,15 @@ sub OWTHERM_Get($@) {
#-- OWX interface #-- OWX interface
if( $interface eq "OWX" ){ if( $interface eq "OWX" ){
#-- not different from getting all values ..
$ret = OWXTHERM_GetValues($hash); $ret = OWXTHERM_GetValues($hash);
#-- OWX_ASYNC interface
}elsif( $interface eq "OWX_ASYNC" ){ }elsif( $interface eq "OWX_ASYNC" ){
eval { eval {
$ret = OWX_ASYNC_RunToCompletion($hash,OWXTHERM_PT_GetValues($hash)); $ret = OWX_ASYNC_RunToCompletion($hash,OWXTHERM_PT_GetValues($hash));
}; };
$ret = GP_Catch($@) if $@; $ret = GP_Catch($@) if $@;
#-- OWFS interface #-- OWFS interface
}elsif( $interface eq "OWServer" ){ }elsif( $interface eq "OWServer" ){
$ret = OWFSTHERM_GetValues($hash); $ret = OWFSTHERM_GetValues($hash);
@ -527,7 +462,8 @@ sub OWTHERM_Get($@) {
#-- process results #-- process results
if( $master->{ASYNCHRONOUS} ){ if( $master->{ASYNCHRONOUS} ){
return "OWTHERM: $name getting values, please wait for completion"; #return "OWTHERM: $name getting values, please wait for completion";
return undef;
}else{ }else{
#-- when we have a return code, we have an error #-- when we have a return code, we have an error
if( defined($ret) ){ if( defined($ret) ){
@ -567,19 +503,17 @@ sub OWTHERM_GetValues($@) {
OWTHERM_FormatValues($hash); OWTHERM_FormatValues($hash);
} }
#-- restart timer for updates
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
#-- auto-update for device disabled;
return undef
if( $hash->{INTERVAL} == 0 );
#-- restart timer for updates
InternalTimer(time()+$hash->{INTERVAL}, "OWTHERM_GetValues", $hash, 0); InternalTimer(time()+$hash->{INTERVAL}, "OWTHERM_GetValues", $hash, 0);
#-- Get values according to interface type #-- Get values according to interface type
my $interface= $hash->{IODev}->{TYPE}; my $interface= $hash->{IODev}->{TYPE};
if( $interface eq "OWX" ){ if( $interface eq "OWX" ){
#-- max 3 tries
for(my $try=0; $try<3; $try++){
$ret = OWXTHERM_GetValues($hash); $ret = OWXTHERM_GetValues($hash);
last
if( !defined($ret) );
}
}elsif( $interface eq "OWX_ASYNC" ){ }elsif( $interface eq "OWX_ASYNC" ){
#-- skip, if the conversion is driven by master #-- skip, if the conversion is driven by master
unless ( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){ unless ( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){
@ -597,10 +531,6 @@ sub OWTHERM_GetValues($@) {
#-- process results #-- process results
if( defined($ret) ){ if( defined($ret) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){
$hash->{INTERVAL} = 9999;
}
return "OWTHERM: Could not get values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret"; return "OWTHERM: Could not get values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
} }
@ -735,10 +665,11 @@ sub OWTHERM_Set($@) {
#-- set new timer interval #-- set new timer interval
if($key eq "interval") { if($key eq "interval") {
# check value # check value
return "OWTHERM: Set with short interval, must be >= 1" return "OWTHERM: set $name interval must be >= 0"
if(int($value) < 1); if(int($value) < 0);
# update timer $hash->{INTERVAL} = int($value);
return OWTHERM_Attr("set",@a); RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWTHERM_GetValues", $hash, 0);
} }
#-- set tempLow or tempHigh #-- set tempLow or tempHigh
@ -800,7 +731,7 @@ sub OWTHERM_Set($@) {
#-- process results #-- process results
$hash->{PRESENT} = 1; $hash->{PRESENT} = 1;
OWTHERM_FormatValues($hash); #OWTHERM_FormatValues($hash);
Log3 $name, 4, "OWTHERM: Set $hash->{NAME} $key $value"; Log3 $name, 4, "OWTHERM: Set $hash->{NAME} $key $value";
return undef; return undef;
@ -944,30 +875,35 @@ sub OWFSTHERM_SetValues($$) {
sub OWXTHERM_BinValues($$$$$$$) { sub OWXTHERM_BinValues($$$$$$$) {
my ($hash, $context, $reset, $owx_dev, $crcpart, $numread, $res) = @_; my ($hash, $context, $reset, $owx_dev, $crcpart, $numread, $res) = @_;
my ($i,$j,$k,@data,$ow_thn,$ow_tln); #-- hash of the busmaster
my $change = 0; my $master = $hash->{IODev};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my ($i,$j,$k,@data,$ow_thn,$ow_tln);
my $error = 0;
my $change = 0;
my $msg; my $msg;
OWX_WDBG($name,"OWTHERM_BinValues called for device $name with ",$res)
if( $main::owx_debug>2 ); OWX_WDBGL($name,5,"OWXTHERM_BinValues called for device $name in context $context with data ",$res);
#-- we have to get rid of the first 10 bytes
if( length($res) == 19 ){
$res=substr($res,10);
}
@data=split(//,$res);
#-- process results #-- process results
@data=split(//,$res);
if (@data != 9){ if (@data != 9){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 9 bytes, "; $error = 1;
$msg = "$name: invalid data length, ".int(@data)." instead of 9 bytes, ";
}elsif(ord($data[7])<=0){ }elsif(ord($data[7])<=0){
$msg="Error - $name returns invalid data, "; $error = 1;
$msg = "$name: invalid data, ";
}elsif(OWX_CRC8(substr($res,0,8),$data[8])==0){ }elsif(OWX_CRC8(substr($res,0,8),$data[8])==0){
$msg="Error - invalid data from device $name, invalid CRC, "; $error = 1;
$msg = "$name: invalid CRC, ";
}else{ }else{
$msg="No error, "; $msg = "$name: no error, ";
for(my $i=0;$i<8;$i++){
$hash->{owg_val}->[$i] = (ord($data[0])>>$i) & 1;
$hash->{owg_vax}->[$i] = (ord($data[1])>>$i) & 1;
};
} }
OWX_WDBG($name,"OWXTHERM_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#-- this must be different for the different device types #-- this must be different for the different device types
# family = 10 => DS1820, DS18S20 # family = 10 => DS1820, DS18S20
@ -975,7 +911,7 @@ sub OWXTHERM_BinValues($$$$$$$) {
my $count_remain = ord($data[6]); my $count_remain = ord($data[6]);
my $count_perc = ord($data[7]); my $count_perc = ord($data[7]);
my $delta = -0.25 + ($count_perc - $count_remain)/$count_perc; my $delta = ($count_perc != 0)?(-0.25 + ($count_perc - $count_remain)/$count_perc):0;
my $lsb = ord($data[0]); my $lsb = ord($data[0]);
my $msb = 0; my $msb = 0;
@ -1014,17 +950,22 @@ sub OWXTHERM_BinValues($$$$$$$) {
$ow_thn = ord($data[2]) > 127 ? 128-ord($data[2]) : ord($data[2]); $ow_thn = ord($data[2]) > 127 ? 128-ord($data[2]) : ord($data[2]);
$ow_tln = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]); $ow_tln = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]);
} else {
die "OWTHERM: $name: Unknown device family $hash->{OW_FAMILY}\n";
} }
#-- process alarm settings #-- process alarm settings
$hash->{owg_tl} = $ow_tln; $hash->{owg_tl} = $ow_tln;
$hash->{owg_th} = $ow_thn; $hash->{owg_th} = $ow_thn;
OWX_WDBGL($name,5-4*$error,"OWXTHERM_BinValues: ".$msg." ".$hash->{owg_temp}." ",$res);
#-- and now from raw to formatted values #-- and now from raw to formatted values
if( $error ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
}else{
$hash->{PRESENT} = 1; $hash->{PRESENT} = 1;
my $value = OWTHERM_FormatValues($hash); OWTHERM_FormatValues($hash);
}
return undef; return undef;
} }
@ -1070,9 +1011,10 @@ sub OWXTHERM_GetValues($) {
#-- NEW OWX interface #-- NEW OWX interface
}else{ }else{
#### master slave context proc owx_dev data crcpart numread startread callback delay #### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, undef, 0, $owx_dev, "\x44", 0, 0, undef, undef, $convtimes{AttrVal($name,"resolution",12)}*0.001); OWX_Qomplex($master, $hash, "convert", 5, $owx_dev, "\x44", 0, 1, undef, undef, $convtimes{AttrVal($name,"resolution",12)}*0.001 );
} }
} }
#-- NOW ask the specific device #-- NOW ask the specific device
#-- issue the match ROM command \x55 and the read scratchpad command \xBE #-- issue the match ROM command \x55 and the read scratchpad command \xBE
#-- reading 9 + 1 + 8 data bytes and 1 CRC byte = 19 bytes #-- reading 9 + 1 + 8 data bytes and 1 CRC byte = 19 bytes
@ -1082,16 +1024,14 @@ sub OWXTHERM_GetValues($) {
my $res=OWX_Complex($master,$owx_dev,"\xBE",9); my $res=OWX_Complex($master,$owx_dev,"\xBE",9);
return "OWTHERM: $name not accessible in reading" return "OWTHERM: $name not accessible in reading"
if( $res eq 0 ); if( $res eq 0 );
return "OWTHERM: $name has returned invalid data" Log 1,"OWTHERM: $name has returned invalid data of length ".length($res)
if( length($res)!=19); if( length($res)!=19);
eval { return OWXTHERM_BinValues($hash,"getsp",$owx_dev,undef,undef,9,substr($res,10,9));
OWXTHERM_BinValues($hash,undef,$owx_dev,undef,undef,9,substr($res,10,9));
};
return $@ ? $@ : undef;
#-- NEW OWX interface #-- NEW OWX interface
}else{ }else{
#### master slave context proc owx_dev data crcpart numread startread callback delay #### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, undef, 1, $owx_dev, "\xBE", 0, 9, 10, \&OWXTHERM_BinValues, 0.01); OWX_Qomplex($master, $hash, "readsp", 1, $owx_dev, "\xBE", 0, 19, 0, \&OWXTHERM_BinValues, undef);
return undef; return undef;
} }
} }
@ -1150,7 +1090,7 @@ sub OWXTHERM_SetValues($$) {
#-- NEW OWX interface #-- NEW OWX interface
}else{ }else{
#### master slave context proc owx_dev data crcpart numread startread callback delay #### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, undef, 0, $owx_dev, $select, 0, 3, 10, undef, 0.05); OWX_Qomplex($master, $hash, "writesp", 0, $owx_dev, $select, 0, 3, 10, undef, undef);
} }
return undef; return undef;
} }
@ -1331,7 +1271,7 @@ sub OWXTHERM_PT_SetValues($$) {
<ul> <ul>
<li><a name="owtherm_interval"> <li><a name="owtherm_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Temperature <code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Temperature
readout interval in seconds. The default is 300 seconds. <b>Attention:</b>This is the readout interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update. <b>Attention:</b>This is the
readout interval. Whether an actual temperature measurement is performed, is determined by the readout interval. Whether an actual temperature measurement is performed, is determined by the
tempConv attribute </li> tempConv attribute </li>
<li><a name="owtherm_tempHigh"> <li><a name="owtherm_tempHigh">
@ -1350,12 +1290,6 @@ sub OWXTHERM_PT_SetValues($$) {
<li><a name="owtherm_id"> <li><a name="owtherm_id">
<code>get &lt;name&gt; id</code></a> <code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li> <br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owtherm_present">
<code>get &lt;name&gt; present</code></a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owtherm_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns temperature measurement
interval in seconds.</li>
<li><a name="owtherm_temperature"> <li><a name="owtherm_temperature">
<code>get &lt;name&gt; temperature</code></a><br />Obtain the temperature. </li> <code>get &lt;name&gt; temperature</code></a><br />Obtain the temperature. </li>
<li><a name="owtherm_alarm"> <li><a name="owtherm_alarm">

View File

@ -10,34 +10,6 @@
# #
######################################################################################## ########################################################################################
# #
# define <name> OWVAR [<model>] <ROM_ID> or <FAM_ID>.<ROM_ID>
#
# where <name> may be replaced by any name string
#
# <model> is a 1-Wire device type. If omitted AND no FAM_ID given we assume this to be an
# DS2890 variable resistor
# <FAM_ID> is a 1-Wire family id, currently allowed values are 2C
# <ROM_ID> is a 12 character (6 byte) 1-Wire ROM ID
# without Family ID, e.g. A2D90D000800
#
# get <name> id => FAM_ID.ROM_ID.CRC
# get <name> present => 1 if device present, 0 if not
# get <name> value => query value
# get <name> version => OWX version number
# set <name> value => wiper setting
#
# Additional attributes are defined in fhem.cfg
# attr <name> Name <string>[|<string>] = name for the channel [|name used in state reading]
# attr <name> Unit <string>[|<string>] = unit of measurement for this channel [|unit used in state reading]
# attr <name> Function <string>|<string> = The first string is an arbitrary functional expression f(V) involving the variable V.
# V is replaced by the raw potentiometer reading (in the range of [0,100]). The second string must be the inverse
# function g(U) involving the variable U, such that U can be replaced by the value given in the
# set argument. Care has to taken that g(U) is in the range [0,100].
# No check on the validity of these functions is performed,
# singularities my crash FHEM.
#
########################################################################################
#
# This programm is free software; you can redistribute it and/or modify # This programm is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # the Free Software Foundation; either version 2 of the License, or
@ -75,12 +47,11 @@ no warnings 'deprecated';
sub Log3($$$); sub Log3($$$);
sub AttrVal($$$); sub AttrVal($$$);
my $owx_version="6.1"; my $owx_version="7.0";
my $owg_channel = ""; my $owg_channel = "";
my %gets = ( my %gets = (
"id" => "", "id" => "",
"present" => "",
"value" => "", "value" => "",
"version" => "" "version" => ""
); );
@ -266,7 +237,7 @@ sub OWVAR_Attr(@) {
if ( $do eq "set") { if ( $do eq "set") {
ARGUMENT_HANDLER: { ARGUMENT_HANDLER: {
#-- interval modified at runtime #-- IODev
$key eq "IODev" and do { $key eq "IODev" and do {
AssignIoPort($hash,$value); AssignIoPort($hash,$value);
if( defined($hash->{IODev}) ) { if( defined($hash->{IODev}) ) {
@ -407,28 +378,6 @@ sub OWVAR_Get($@) {
#-- Get other values according to interface type #-- Get other values according to interface type
my $interface= $hash->{IODev}->{TYPE}; my $interface= $hash->{IODev}->{TYPE};
#-- get present
if($a[1] eq "present" ) {
#-- OWX interface
if( $interface =~ /^OWX/ ){
#-- asynchronous mode
if( $hash->{ASYNC} ){
Log3 $name, 1,"OWVAR: Get ASYNC interface not implemented";
#eval {
# OWX_ASYNC_RunToCompletion($hash,OWX_ASYNC_PT_Verify($hash));
#};
#return GP_Catch($@) if $@;
return "$name.present => ".ReadingsVal($name,"present","unknown");
} else {
$value = OWX_Verify($master,$hash->{ROM_ID});
}
$hash->{PRESENT} = $value;
return "$name.present => $value";
} else {
return "OWVAR: Verification not yet implemented for interface $interface";
}
}
#-- get version #-- get version
if( $a[1] eq "version") { if( $a[1] eq "version") {
return "$name.version => $owx_version"; return "$name.version => $owx_version";
@ -455,7 +404,8 @@ sub OWVAR_Get($@) {
} }
#-- process results #-- process results
if( $master->{ASYNCHRONOUS} ){ if( $master->{ASYNCHRONOUS} ){
return "OWVAR: $name getting value, please wait for completion"; #return "OWVAR: $name getting value, please wait for completion";
return undef;
}else{ }else{
#-- when we have a return code, we have an error #-- when we have a return code, we have an error
if( defined($ret) ){ if( defined($ret) ){
@ -493,19 +443,10 @@ sub OWVAR_GetValues($@) {
OWVAR_FormatValues($hash); OWVAR_FormatValues($hash);
} }
#-- restart timer for updates
RemoveInternalTimer($hash);
#InternalTimer(time()+$hash->{INTERVAL}, "OWVAR_GetValues", $hash, 0);
#-- Get values according to interface type #-- Get values according to interface type
my $interface= $hash->{IODev}->{TYPE}; my $interface= $hash->{IODev}->{TYPE};
if( $interface eq "OWX" ){ if( $interface eq "OWX" ){
#-- max 3 tries
for(my $try=0; $try<3; $try++){
$ret = OWXVAR_GetValues($hash); $ret = OWXVAR_GetValues($hash);
last
if( !defined($ret) );
}
}elsif( $interface eq "OWX_ASYNC" ){ }elsif( $interface eq "OWX_ASYNC" ){
Log3 $name, 1,"OWVAR: Get ASYNC interface not implemented"; Log3 $name, 1,"OWVAR: Get ASYNC interface not implemented";
}elsif( $interface eq "OWServer" ){ }elsif( $interface eq "OWServer" ){
@ -518,9 +459,6 @@ sub OWVAR_GetValues($@) {
#-- process results #-- process results
if( defined($ret) ){ if( defined($ret) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1; $hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){
$hash->{INTERVAL} = 9999;
}
return "OWVAR: Could not get values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret"; return "OWVAR: Could not get values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
} }
@ -747,26 +685,79 @@ sub OWFSVAR_SetValues($$$) {
sub OWXVAR_BinValues($$$$$$$) { sub OWXVAR_BinValues($$$$$$$) {
my ($hash, $context, $reset, $owx_dev, $crcpart, $numread, $res) = @_; my ($hash, $context, $reset, $owx_dev, $crcpart, $numread, $res) = @_;
my $master = $hash->{IODev};
my $name = $hash->{NAME};
my $error = 0;
my ($i,$j,$k,@data); my ($i,$j,$k,@data);
my $change = 0; my $change = 0;
my $master = $hash->{IODev};
my $name = $hash->{NAME};
my $msg; my $msg;
OWX_WDBG($name,"OWVAR: $name: BinValues called with ",$res) OWX_WDBGL($name,4,"OWXVAR_BinValues called for device $name in context $context with data ",$res);
if( $main::owx_debug>2 );
#-- process results #-- process results
#die "OWVAR: $name not accessible in 2nd step" unless ( defined $res and $res ne 0 ); if( $context eq "setstate" ) {
#-- we have to get rid of the first 10 bytes
if( length($res) == 11 ){
$res=substr($res,10);
}
if( $context eq "getstate" ) { if( length($res) != 1 ) {
#-- process results $error = 1;
@data=split(//,$res); $msg = "$name: invalid data length, ".length($res)." instead of 1 bytes ";
if (@data != 2) { }elsif( $res ne $crcpart ){
$msg="Error- $name returns invalid data length, ".int(@data)." instead of 2 bytes "; $error = 1;
$msg = "$name: invalid data ";
}else{ }else{
$msg="No error"; $msg = "$name: no error, ";
}
OWX_WDBGL($name,5-4*$error,"OWXVAR_BinValues setstate: ".$msg,$res);
#-- increase error count
if( $error ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "release", 18, $owx_dev, "\x96", 0, 11, 0, \&OWXVAR_BinValues, 0.01);
}
#------------------------------------------------------------------
}elsif( $context eq "release" ) {
#-- we have to get rid of the first 10 bytes
if( length($res) == 11 ){
$res=substr($res,10);
}
if( length($res) != 1 ) {
$error = 1;
$msg = "$name: invalid data length, ".length($res)." instead of 1 bytes ";
}elsif( $res ne "\x96" ){
$error = 1;
$msg = "$name: invalid data ";
}else{
$msg = "$name: no error, ";
}
OWX_WDBGL($name,5-4*$error,"OWXVAR_BinValues release : ".$msg,$res);
#-- increase error count
if( $error ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
}
#------------------------------------------------------------------
}elsif( $context eq "getstate" ) {
#-- we have to get rid of the first 10 bytes
if( length($res) == 12 ){
$res=substr($res,10);
}
@data=split(//,$res);
#-- process results
if (@data != 2) {
$error = 1;
$msg = "$name: invalid data length, ".int(@data)." instead of 2 bytes ";
}else{
$msg = "$name: no error, ";
}
OWX_WDBGL($name,5-4*$error,"OWXVAR_BinValues getstate: ".$msg,$res);
my $stat = ord($data[0]); my $stat = ord($data[0]);
my $val = ord($data[1]); my $val = ord($data[1]);
@ -774,33 +765,14 @@ sub OWXVAR_BinValues($$$$$$$) {
#-- and now from raw to formatted values #-- and now from raw to formatted values
$hash->{PRESENT} = 1; $hash->{PRESENT} = 1;
my $value = OWVAR_FormatValues($hash); if ( !$error ){
#Log3 $hash->{NAME}, 5, $value; my $value = OWVAR_FormatValues($hash)
}
OWX_WDBG($name,"OWXVAR_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
return undef;
#--- obsolete code - we have put all operations into the SetValues part. Leave in for now
}elsif( $context eq "setstate" ) {
my $val = ord($res);
#$hash->{owg_val}=sprintf("%5.2f",(1-$val/255.0)*100);
#-- process results
if (length($res) != 1){
$msg="$name returns invalid data length, ".length($res)." instead of 1 bytes, ";
}elsif($val ne $crcpart){
$msg="$name returns invalid data $val instead of $crcpart, "
}else{ }else{
$msg="No error, val = $val"; $hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
}
} }
OWX_WDBG($name,"OWXVAR_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#### master slave context proc owx_dev data crcpart numread startread callback delay
# 2 suppresses the initial bus reset, 16 inserts at top of queue
#OWX_Qomplex($master, $hash, "confirm", 18, $owx_dev, "\x96", 0, 2, 11, undef, 0.01);
return undef; return undef;
} }
}
######################################################################################## ########################################################################################
# #
@ -832,14 +804,12 @@ sub OWXVAR_GetValues($) {
return "OWVAR: $name has returned invalid data" return "OWVAR: $name has returned invalid data"
if( length($res)!=12); if( length($res)!=12);
OWX_Reset($master); OWX_Reset($master);
eval { return OWXVAR_BinValues($hash,"getstate",0,$owx_dev,0,2,substr($res,10,2));
OWXVAR_BinValues($hash,"getstate",0,$owx_dev,0,2,substr($res,10,2));
};
return $@ ? $@ : undef;
#-- NEW OWX interface #-- NEW OWX interface
}else{ }else{
#### master slave context proc owx_dev data crcpart numread startread callback delay #### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "getstate", 0, $owx_dev, "\xF0", 0, 2, 10, \&OWXVAR_BinValues, 0.01); OWX_Qomplex($master, $hash, "getstate", 0, $owx_dev, "\xF0", 0, 12, 0, \&OWXVAR_BinValues, undef);
return undef; return undef;
} }
} }
@ -890,8 +860,7 @@ sub OWXVAR_SetValues($$$) {
#-- NEW OWX interface #-- NEW OWX interface
}else{ }else{
#### master slave context proc owx_dev data crcpart numread startread callback delay #### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "setstate", 0, $owx_dev, $select, 0, 1, 0, undef, 0); OWX_Qomplex($master, $hash, "setstate", 0, $owx_dev, $select, substr($select,1), 11, 0, \&OWXVAR_BinValues, 0.1);
OWX_Qomplex($master, $hash, "confirm", 3, $owx_dev, "\x96", 0, 1, 0, undef, 0);
$hash->{owg_val}=sprintf("%5.2f",(1-$pos/255.0)*100); $hash->{owg_val}=sprintf("%5.2f",(1-$pos/255.0)*100);
} }
return undef; return undef;
@ -951,11 +920,6 @@ sub OWXVAR_SetValues($$$) {
<li><a name="owvar_id"> <li><a name="owvar_id">
<code>get &lt;name&gt; id</code></a> <code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li> <br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owvar_present">
<code>get &lt;name&gt; present</code></a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owvar_value2">
<code>get &lt;name&gt; value</code></a><br />Obtain the value. </li>
</ul> </ul>
<br /> <br />
<a name="OWVARattr"></a> <a name="OWVARattr"></a>