1
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-05-04 22:19:38 +00:00

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@4748 2b470e98-0d58-463d-a4d8-8e2adae1ed80

This commit is contained in:
pahenning 2014-01-26 13:15:48 +00:00
parent 8552d27636
commit 61ab6a3c33

View File

@ -4,7 +4,7 @@
# #
# FHEM module to commmunicate with 1-Wire temperature sensors DS1820, DS18S20, DS18B20, DS1822 # FHEM module to commmunicate with 1-Wire temperature sensors DS1820, DS18S20, DS18B20, DS1822
# #
# Prof. Dr. Peter A. Henning # Prof. Dr. Peter A. Henning und Norbert Truchsess
# #
# $Id$ # $Id$
# #
@ -31,7 +31,7 @@
# get <name> alarm => alarm temperature settings # get <name> alarm => alarm temperature settings
# get <name> version => OWX version number # get <name> version => OWX version number
# #
# set <name> interval => set period for measurement # set <name> interval => period for measurement
# set <name> tempLow => lower alarm temperature setting # set <name> tempLow => lower alarm temperature setting
# set <name> tempHigh => higher alarm temperature setting # set <name> tempHigh => higher alarm temperature setting
# #
@ -40,12 +40,14 @@
# attr <name> stateAL "<string>" = character string for denoting low alarm condition, default is down triangle # attr <name> stateAL "<string>" = character string for denoting low alarm condition, default is down triangle
# attr <name> stateAH "<string>" = character string for denoting high alarm condition, default is up triangle # attr <name> stateAH "<string>" = character string for denoting high alarm condition, default is up triangle
# attr <name> tempOffset <float> = temperature offset in degree Celsius added to the raw temperature reading # 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 or C/K/F, default is Celsius # 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" # 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 # through the OWX backend module (all temperature sensors at the same time), or on
# reading the sensor (1 second waiting time). # reading the sensor (1 second waiting time).
# attr <name> tempLow <float> = value for low alarm # attr <name> resolution 9|10|11|12 = resolution in bit for measurement
# attr <name> tempHigh <float> = value for high alarm # attr <name> interval <floar> = period for measurement
# attr <name> tempLow <float> = lower alarm temperature setting
# attr <name> tempHigh <float> = higher alarm temperature setting
# #
######################################################################################## ########################################################################################
# #
@ -73,7 +75,7 @@ use warnings;
sub Log($$); sub Log($$);
sub AttrVal($$$); sub AttrVal($$$);
my $owx_version="3.24"; my $owx_version="5.02";
my %gets = ( my %gets = (
"id" => "", "id" => "",
@ -97,10 +99,10 @@ my %updates = (
); );
my %convtimes = ( my %convtimes = (
9 => 0.1, 9 => 100,
10 => 0.2, 10 => 200,
11 => 0.4, 11 => 400,
12 => 0.8, 12 => 800,
); );
######################################################################################## ########################################################################################
@ -127,12 +129,13 @@ sub OWTHERM_Initialize ($) {
$hash->{AttrFn} = "OWTHERM_Attr"; $hash->{AttrFn} = "OWTHERM_Attr";
$hash->{AttrList}= "IODev model:DS1820,DS18B20,DS1822 loglevel:0,1,2,3,4,5 ". $hash->{AttrList}= "IODev model:DS1820,DS18B20,DS1822 loglevel:0,1,2,3,4,5 ".
"stateAL stateAH ". "stateAL stateAH ".
"tempOffset tempUnit:C,Celsius,F,Fahrenheit,K,Kelvin ". "tempOffset tempUnit:Celsius,Fahrenheit,Kelvin ".
"tempConv:onkick,onread tempLow tempHigh ". "tempConv:onkick,onread tempLow tempHigh ".
"resolution:9,10,11,12 interval ". "resolution:9,10,11,12 interval ".
$readingFnAttributes; $readingFnAttributes;
#-- ASYNC this function is needed for asynchronous execution of the device reads
#make sure OWX is loaded so OWX_CRC is available if running with OWServer $hash->{AfterExecuteFn} = "OWXTHERM_ProcValues";
#-- make sure OWX is loaded so OWX_CRC is available if running with OWServer
main::LoadModule("OWX"); main::LoadModule("OWX");
} }
@ -168,6 +171,7 @@ sub OWTHERM_Define ($$) {
#-- no model, 12 characters #-- no model, 12 characters
if( $a2 =~ m/^[0-9|a-f|A-F]{12}$/ ) { if( $a2 =~ m/^[0-9|a-f|A-F]{12}$/ ) {
$model = "DS1820"; $model = "DS1820";
CommandAttr (undef,"$name model DS1820");
$fam = "10"; $fam = "10";
$id = $a[2]; $id = $a[2];
if(int(@a)>=4) { $interval = $a[3]; } if(int(@a)>=4) { $interval = $a[3]; }
@ -220,6 +224,7 @@ sub OWTHERM_Define ($$) {
$hash->{ROM_ID} = "$fam.$id.$crc"; $hash->{ROM_ID} = "$fam.$id.$crc";
$hash->{INTERVAL} = $interval; $hash->{INTERVAL} = $interval;
$hash->{ERRCOUNT} = 0; $hash->{ERRCOUNT} = 0;
$hash->{ASYNC} = 0; #-- false for now
#-- temperature globals - always the raw values from/for the device #-- temperature globals - always the raw values from/for the device
$hash->{".owg_temp"} = ""; $hash->{".owg_temp"} = "";
@ -259,10 +264,11 @@ sub OWTHERM_Attr(@) {
if ( $do eq "set") { if ( $do eq "set") {
ARGUMENT_HANDLER: { ARGUMENT_HANDLER: {
#-- 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 with short interval, must be > 1" if(int($value) < 1);
# update timer #-- update timer
$hash->{INTERVAL} = $value; $hash->{INTERVAL} = $value;
if ($init_done) { if ($init_done) {
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
@ -270,16 +276,16 @@ sub OWTHERM_Attr(@) {
} }
last; last;
}; };
#-- resolution modified at runtime
$key eq "resolution" and do { $key eq "resolution" and do {
$hash->{".owg_cf"} = $value; $hash->{".owg_cf"} = $value;
last; last;
}; };
#-- only alarm settings may be modified at runtime for now #-- alarm settings modified at runtime
$key =~ m/(.*)(Low|High)/ and do { $key =~ m/(.*)(Low|High)/ and do {
#-- safeguard against uninitialized devices #-- safeguard against uninitialized devices
return undef return undef
if( $hash->{READINGS}{"state"}{VAL} eq "defined" ); if( $hash->{READINGS}{"state"}{VAL} eq "defined" );
$ret = OWTHERM_Set($hash,($name,$key,$value)); $ret = OWTHERM_Set($hash,($name,$key,$value));
}; };
}; };
@ -577,11 +583,11 @@ sub OWTHERM_InitializeDevice($) {
my $args = {}; my $args = {};
#-- Set the attribute values if defined
if ( defined($attr{$name}{resolution}) ) { if ( defined($attr{$name}{resolution}) ) {
$args->{resolution} = $attr{$name}{resolution}; $args->{resolution} = $attr{$name}{resolution};
} }
#-- Set the attribute values if defined
if( defined($attr{$name}{"tempLow"}) ){ if( defined($attr{$name}{"tempLow"}) ){
$args->{tempLow} = floor($attr{$name}{"tempLow"}/$factor-$offset+0.5); $args->{tempLow} = floor($attr{$name}{"tempLow"}/$factor-$offset+0.5);
} }
@ -638,6 +644,10 @@ sub OWTHERM_Set($@) {
#-- set new timer interval #-- set new timer interval
if($key eq "interval") { if($key eq "interval") {
# check value
return "OWTHERM: Set with short interval, must be >= 1"
if(int($value) < 1);
# update timer
return OWTHERM_Attr("set",@a); return OWTHERM_Attr("set",@a);
} }
@ -808,7 +818,7 @@ sub OWFSTHERM_SetValues($$) {
# #
######################################################################################## ########################################################################################
# #
# OWXTHERM_GetValues - Get reading from one device # OWXTHERM_GetValues - Trigger reading from one device
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# #
@ -837,20 +847,49 @@ sub OWXTHERM_GetValues($) {
#-- if the conversion has not been called before #-- if the conversion has not been called before
if( $con==1 ){ if( $con==1 ){
OWX_Reset($master); #-- issue the match ROM command \x55 and the start conversion command \x44
#-- issue the match ROM command \x55 and the start conversion command #-- asynchronous mode
if( OWX_Complex($master,$owx_dev,"\x44",0) eq 0 ){ if( $hash->{ASYNC} ){
return "$owx_dev not accessible"; OWX_Execute($master,"convert",1,$owx_dev,"\x44",0,$convtimes{AttrVal($name,"resolution",12)});
} #-- synchronous mode
#-- conversion needs some 950 ms - but we may also do it in shorter time ! }else{
select(undef,undef,undef,$convtimes{AttrVal($name,"resolution",12)}); OWX_Reset($master);
if( OWX_Complex($master,$owx_dev,"\x44",0) eq 0 ){
return "$owx_dev not accessible";
}
#-- conversion needs some 950 ms - but we may also do it in shorter time !
select(undef,undef,undef,$convtimes{AttrVal($name,"resolution",12)}*0.001);
}
} }
#-- NOW ask the specific device
#-- NOW ask the specific device
OWX_Reset($master);
#-- 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
my $res=OWX_Complex($master,$owx_dev,"\xBE",9); #-- asynchronous mode
if( $hash->{ASYNC} ){
OWX_Execute($master,"read",1,$owx_dev,"\xBE",9,undef);
#-- synchronous mode
} else {
OWX_Reset($master);
my $res=OWX_Complex($master,$owx_dev,"\xBE",9);
OWXTHERM_ProcValues($hash,"read",undef,undef,$owx_dev,undef,undef,substr($res,10,9));
}
}
########################################################################################
#
# OWXTHERM_ProcValues - Process reading from one device - translate binary into raw
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWXTHERM_ProcValues($$$$$$$$) {
my ($hash, $context, $success, $reset, $owx_dev, $data, $numread, $res) = @_;
return undef unless (defined $context and $context eq "read");
my ($i,$j,$k,@data,$ow_thn,$ow_tln);
my $change = 0;
#Log 1,"OWXTHERM: data length from reading device is ".length($res)." bytes"; #Log 1,"OWXTHERM: data length from reading device is ".length($res)." bytes";
#-- process results #-- process results
if( $res eq 0 ){ if( $res eq 0 ){
@ -858,25 +897,25 @@ sub OWXTHERM_GetValues($) {
} }
#-- process results #-- process results
@data=split(//,substr($res,9)); @data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 10 bytes" return "invalid data length, ".int(@data)." instead of 9 bytes"
if (@data != 10); if (@data != 9);
return "invalid data" return "invalid data"
if (ord($data[8])<=0); if (ord($data[7])<=0);
return "invalid CRC" return "invalid CRC"
if (OWX_CRC8(substr($res,10,8),$data[9])==0); if (OWX_CRC8(substr($res,0,8),$data[8])==0);
#-- 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
if( $hash->{OW_FAMILY} eq "10" ) { if( $hash->{OW_FAMILY} eq "10" ) {
my $count_remain = ord($data[7]); my $count_remain = ord($data[6]);
my $count_perc = ord($data[8]); my $count_perc = ord($data[7]);
my $delta = -0.25 + ($count_perc - $count_remain)/$count_perc; my $delta = -0.25 + ($count_perc - $count_remain)/$count_perc;
my $lsb = ord($data[1]); my $lsb = ord($data[0]);
my $msb = 0; my $msb = 0;
my $sign = ord($data[2]) & 255; my $sign = ord($data[1]) & 255;
#-- test with -25 degrees #-- test with -25 degrees
#$lsb = 12*16+14; #$lsb = 12*16+14;
@ -889,14 +928,14 @@ sub OWXTHERM_GetValues($) {
$hash->{".owg_temp"} = -128+$hash->{".owg_temp"}; $hash->{".owg_temp"} = -128+$hash->{".owg_temp"};
} }
$ow_thn = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]); $ow_thn = ord($data[2]) > 127 ? 128-ord($data[2]) : ord($data[2]);
$ow_tln = ord($data[4]) > 127 ? 128-ord($data[4]) : ord($data[4]); $ow_tln = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]);
} elsif ( ($hash->{OW_FAMILY} eq "22") || ($hash->{OW_FAMILY} eq "28") ) { } elsif ( ($hash->{OW_FAMILY} eq "22") || ($hash->{OW_FAMILY} eq "28") ) {
my $lsb = ord($data[1]); my $lsb = ord($data[0]);
my $msb = ord($data[2]) & 7; my $msb = ord($data[1]) & 7;
my $sign = ord($data[2]) & 248; my $sign = ord($data[1]) & 248;
#-- test with -55 degrees #-- test with -55 degrees
#$lsb = 9*16; #$lsb = 9*16;
@ -908,8 +947,8 @@ sub OWXTHERM_GetValues($) {
if( $sign !=0 ){ if( $sign !=0 ){
$hash->{".owg_temp"} = -128+$hash->{".owg_temp"}; $hash->{".owg_temp"} = -128+$hash->{".owg_temp"};
} }
$ow_thn = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]); $ow_thn = ord($data[2]) > 127 ? 128-ord($data[2]) : ord($data[2]);
$ow_tln = ord($data[4]) > 127 ? 128-ord($data[4]) : ord($data[4]); $ow_tln = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]);
} else { } else {
return "OWXTHERM: Unknown device family $hash->{OW_FAMILY}\n"; return "OWXTHERM: Unknown device family $hash->{OW_FAMILY}\n";
@ -918,7 +957,9 @@ sub OWXTHERM_GetValues($) {
#-- 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;
#-- and now from raw to formatted values
OWTHERM_FormatValues($hash);
return undef; return undef;
} }
@ -970,10 +1011,15 @@ sub OWXTHERM_SetValues($$) {
# 3. \x48 sent by WriteBytePower after match ROM => command ok, no effect on EEPROM # 3. \x48 sent by WriteBytePower after match ROM => command ok, no effect on EEPROM
my $select=sprintf("\x4E%c%c%c",$thp,$tlp,$cfg); my $select=sprintf("\x4E%c%c%c",$thp,$tlp,$cfg);
my $res=OWX_Complex($master,$owx_dev,$select,3); #-- asynchronous mode
if( $hash->{ASYNC} ){
if( $res eq 0 ){ OWX_Execute($master,"setvalues",1,$owx_dev,$select,3,undef);
return "OWXTHERM: Device $owx_dev not accessible"; #-- synchronous mode
}else{
my $res=OWX_Complex($master,$owx_dev,$select,3);
if( $res eq 0 ){
return "OWXTHERM: Device $owx_dev not accessible";
}
} }
return undef; return undef;
@ -1032,7 +1078,7 @@ sub OWXTHERM_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 intervall in seconds. The default is 300 seconds. <b>Attention:</b>This is the readout interval in seconds. The default is 300 seconds. <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">
@ -1085,9 +1131,17 @@ sub OWXTHERM_SetValues($$) {
</a> </a>
<br />temperature offset in &deg;C added to the raw temperature reading. </li> <br />temperature offset in &deg;C added to the raw temperature reading. </li>
<li><a name="owtherm_tempUnit"><code>attr &lt;name&gt; tempUnit <li><a name="owtherm_tempUnit"><code>attr &lt;name&gt; tempUnit
Celsius|Kelvin|Fahrenheit|C|K|F</code> Celsius|Kelvin|Fahrenheit</code>
</a> </a>
<br />unit of measurement (temperature scale), default is Celsius = &deg;C </li> <br />unit of measurement (temperature scale), default is Celsius = &deg;C </li>
<li><a name="owtherm_resolution">
<code>attr &lt;name&gt; resolution 9|10|11|12</code></a><br /> Temperature
resolution in bit, only relevant for DS18B20 </li>
<li><a name="owtherm_interval2">
<code>attr &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. Whether an actual temperature measurement is performed, is determined by the
tempConv attribute </li>
<li><a name="owtherm_tempHigh2"> <li><a name="owtherm_tempHigh2">
<code>attr &lt;name&gt; tempHigh &lt;float&gt;</code> <code>attr &lt;name&gt; tempHigh &lt;float&gt;</code>
</a> </a>
@ -1098,6 +1152,7 @@ sub OWXTHERM_SetValues($$) {
</a> </a>
<br /> low alarm temperature (on the temperature scale chosen by the attribute <br /> low alarm temperature (on the temperature scale chosen by the attribute
value). </li> value). </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a <li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#event-on-update-reading">event-on-update-reading</a>, <a href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a href="#event-on-change-reading">event-on-change-reading</a>, <a