diff --git a/fhem/contrib/1-Wire/00_OWX.pm b/fhem/contrib/1-Wire/00_OWX.pm index 8d1ef012d..1bb365195 100644 --- a/fhem/contrib/1-Wire/00_OWX.pm +++ b/fhem/contrib/1-Wire/00_OWX.pm @@ -2,6 +2,9 @@ # # OWX.pm # +# TODO: Abfangen, wenn das Serial Device nach Öffnung nicht existiert ??? +# set init als rediscover ausführen. +# # FHEM module to commmunicate with 1-Wire bus devices # * via an active DS2480/DS2482/DS2490/DS9097U bus master interface attached to an USB port # * via a passive DS9097 interface attached to an USB port @@ -9,16 +12,16 @@ # Internally these interfaces are vastly different, read the corresponding Wiki pages # http://fhemwiki.de/wiki/Interfaces_f%C3%BCr_1-Wire # -# Version 2.17 - August, 2012 +# Version 2.20 - October, 2012 # # Prof. Dr. Peter A. Henning, 2012 # # define OWX for USB interfaces or -# define OWX for a CUNO interface +# define OWX for a CUNO or COC interface # # where may be replaced by any name string # is a serial (USB) device -# is a CUNO device +# is a CUNO or COC device # # get alarms => find alarmed 1-Wire devices (not with CUNO) # get devices => find all 1-Wire devices @@ -161,6 +164,8 @@ sub OWX_Define ($$) { #-- First step: check if we have a directly connected serial interface or a CUNO attached # (mod suggested by T.Faust) if ( $dev =~ m/\/dev\/.*/ ){ + #-- TODO: what should we do when the specified device name contains @ already ? + $hash->{DeviceName} = $dev."\@9600"; #-- Second step in case of serial device: open the serial device to test it my $msg = "OWX: Serial device $dev"; my $ret = DevIo_OpenDev($hash,0,undef); @@ -186,8 +191,9 @@ sub OWX_Define ($$) { select(undef,undef,undef,0.1); } else { + $hash->{DeviceName} = $dev; #-- Second step in case of CUNO: See if we can open it - my $msg = "OWX: CUNO device $dev"; + my $msg = "OWX: CUNO/COC device $dev"; $owx_hwdevice = $main::defs{$dev}; if($owx_hwdevice){ Log 1,$msg." defined"; @@ -198,7 +204,7 @@ sub OWX_Define ($$) { CUL_SimpleWrite($owx_hwdevice, "Oi"); }else{ Log 1, $msg." not defined"; - return "OWX: Can't open cuno device $dev: $!" + return "OWX: Can't open CUNO/COC device $dev: $!" } } #-- Third step: see, if a bus interface is detected @@ -529,16 +535,37 @@ sub OWX_Detect ($) { } #-- here we treat the network-connected CUNO } else { - CUL_SimpleWrite($owx_hwdevice, "ORm"); - my $ob = DevIo_SimpleRead($owx_hwdevice); - if( $ob =~ m/OK.*/){ - $owx_interface="CUNO"; - $ress .= "DS2482 detected in $owx_hwdevice->{NAME}"; - $ret=1; - } else { + #-- sleeping for some time + select(undef,undef,undef,0.5); + #-- Max 4 tries to detect an interface + for($l=0;$l<4;$l++) { + #-- write 1-Wire bus + CUL_SimpleWrite($owx_hwdevice, "ORm"); + my $ob = OWX_SimpleRead($owx_hwdevice); + + #-- process result for detection + #Log 1,"ERGEBNIS ORm =>".$ob."<="; + if( !defined($ob)){ + $ob=""; + $ret=0; + }elsif( $ob =~ m/OK.*/){ + $owx_interface="CUNO"; + $ress .= "DS2482 detected in $owx_hwdevice->{NAME}"; + $ret=1; + } else { + $ret=0; + } + last + if( $ret==1 ); + $ress .= "not found, answer was ".$ob; + Log 1, $ress; + $ress = $ress0; + #-- sleeping for some time + select(undef,undef,undef,0.5); + } + if( $ret == 0 ){ $owx_interface=undef; $ress .= "in $owx_hwdevice->{NAME} could not be addressed"; - $ret=0; } } #-- store with OWX device @@ -583,7 +610,7 @@ sub OWX_Discover ($) { #-- sleeping for some time select(undef,undef,undef,3); CUL_SimpleWrite($owx_hwdevice, "Oc"); - my $ob = DevIo_SimpleRead($owx_hwdevice); + my $ob = OWX_SimpleRead($owx_hwdevice); if( $ob ){ foreach my $dx (split(/\n/,$ob)){ $dx =~ s/\d+\://; @@ -1879,7 +1906,7 @@ sub OWX_Complex_CUNO ($$$$) { Log 3,"OWX: Sending match ROM to CUNO ".$select if( $owx_debug > 1); CUL_SimpleWrite($owx_hwdevice, $select); - my $ob = DevIo_SimpleRead($owx_hwdevice); + my $ob = OWX_SimpleRead($owx_hwdevice); #-- padding first 9 bytes into result string, since we have this # in the serial interfaces as well $res .= "000000000"; @@ -1894,12 +1921,14 @@ sub OWX_Complex_CUNO ($$$$) { #$numread += length($data); $res.=OWX_Receive_CUNO($hash,$numread); } + Log 3,"OWX: returned from CUNO $res" + if( $owx_debug > 1); return $res; } ######################################################################################## # -# OWX_receive_CUNO - Read from the CUNO +# OWX_Receive_CUNO - Read from the CUNO # # Parameter: hash = hash of bus master, numread = number of bytes to read # @@ -1915,7 +1944,7 @@ sub OWX_Receive_CUNO ($$) { for( my $i=0;$i<$numread;$i++){ CUL_SimpleWrite($owx_hwdevice, "OrB"); - my $ob = DevIo_SimpleRead($owx_hwdevice); + my $ob = OWX_SimpleRead($owx_hwdevice); #-- process results if( !(defined($ob)) ){ return ""; @@ -1949,7 +1978,7 @@ sub OWX_Receive_CUNO ($$) { sub OWX_Reset_CUNO ($) { CUL_SimpleWrite($owx_hwdevice, "ORb"); - my $ob = DevIo_SimpleRead($owx_hwdevice); + my $ob = OWX_SimpleRead($owx_hwdevice); if( substr($ob,0,4) eq "OK:1" ){ return 1; }else{ @@ -1985,6 +2014,36 @@ sub OWX_Send_CUNO ($$) { if( $owx_debug > 1); } +######################################################################################### +# +# OWX_SimpleRead - Reading with retry. +# Suggested in this way by Dirk Tostmann +# +# Parameter hash = hash of device +# +# Return response, if OK +# 0 if not OK +# +######################################################################################## + +sub OWX_SimpleRead($) +{ + my ($hash) = @_; + my $buf = DevIo_DoSimpleRead($owx_hwdevice); + + # Lets' try again: Some drivers return len(0) on the first read... + if(defined($buf) && length($buf) == 0) { + #-- allow some time + select(undef,undef,undef,0.5); + $buf = DevIo_DoSimpleRead($owx_hwdevice); + } + + if(!defined($buf) || length($buf) == 0) { + DevIo_Disconnected($hash); + return undef; + } + return $buf; +} ######################################################################################## # # OWX_Verify_CUNO - Verify a particular device on the 1-Wire bus @@ -2005,7 +2064,7 @@ sub OWX_Verify_CUNO ($$) { #-- sleeping for some time select(undef,undef,undef,3); CUL_SimpleWrite($owx_hwdevice, "Oc"); - my $ob = DevIo_SimpleRead($owx_hwdevice); + my $ob = OWX_SimpleRead($owx_hwdevice); if( $ob ){ foreach my $dx (split(/\n/,$ob)){ $dx =~ s/\d+\://; diff --git a/fhem/contrib/1-Wire/21_OWTHERM.pm b/fhem/contrib/1-Wire/21_OWTHERM.pm index 3713ae1f5..106546b29 100755 --- a/fhem/contrib/1-Wire/21_OWTHERM.pm +++ b/fhem/contrib/1-Wire/21_OWTHERM.pm @@ -15,7 +15,7 @@ # Prof. Dr. Peter A. Henning, 2012 # Martin Fischer, 2011 # -# Version 2.17 - August, 2012 +# Version 2.20 - October, 2012 # # Setup bus device in fhem.cfg as # @@ -43,6 +43,8 @@ # Additional attributes are defined in fhem.cfg # Note: attributes "tempXXXX" are read during every update operation. # +# attr event on-change/on-update = when to write an event (default= on-update) +# # attr stateAL "" = character string for denoting low alarm condition, default is red down triangle # attr stateAH "" = character string for denoting high alarm condition, default is red up triangle # attr tempOffset = temperature offset in degree Celsius added to the raw temperature reading @@ -129,6 +131,7 @@ sub OWTHERM_Initialize ($) { #tempOffset = a temperature offset added to the temperature reading for correction #tempUnit = a unit of measure: C/F/K $hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 loglevel:0,1,2,3,4,5 ". + "event:on-update,on-change ". "stateAL stateAH ". "tempOffset tempUnit:C,Celsius,F,Fahrenheit,K,Kelvin ". "tempLow tempHigh"; @@ -278,7 +281,7 @@ sub OWTHERM_FormatValues($) { $stateal = defined($attr{$name}{stateAL}) ? $attr{$name}{stateAL} : ""; $stateah = defined($attr{$name}{stateAH}) ? $attr{$name}{stateAH} : ""; $unit = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : $hash->{READINGS}{"temperature"}{UNIT}; - $offset = defined($attr{$name}{"tempoffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ; + $offset = defined($attr{$name}{"tempOffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ; $factor = 1.0; if( $unit eq "Celsius" ){ @@ -474,12 +477,18 @@ sub OWTHERM_GetValues($@) { return "OWTHERM: Could not get values from device $name, reason $ret"; } $hash->{PRESENT} = 1; + + #-- old state, new state + my $oldval = $hash->{STATE}; $value=OWTHERM_FormatValues($hash); - #--logging + my $newval = $hash->{STATE}; + #--logging depends on setting of the event-attribute Log 5, $value; - $hash->{CHANGED}[0] = $value; - - DoTrigger($name, undef); + my $ev = defined($attr{$name}{"event"}) ? $attr{$name}{"event"} : "on-update"; + if( ($ev eq "on-update") || (($ev eq "on-change") && ($newval ne $oldval)) ){ + $hash->{CHANGED}[0] = $value; + DoTrigger($name, undef); + } return undef; } @@ -685,21 +694,25 @@ sub OWXTHERM_GetValues($) { return "OWXTHERM: Device $owx_dev not accessible in 2nd step"; } - #my $res2 = "====> OWXTHERM Received "; - #for(my $i=0;$i<19;$i++){ - # my $j=int(ord(substr($res,$i,1))/16); - # my $k=ord(substr($res,$i,1))%16; - # $res2.=sprintf "0x%1x%1x ",$j,$k; + #if (length($res) == 10){ + # my $res2 = "====> OWXTHERM Received "; + # for(my $i=0;$i<19;$i++){ + # my $j=int(ord(substr($res,$i,1))/16); + # my $k=ord(substr($res,$i,1))%16; + # $res2.=sprintf "0x%1x%1x ",$j,$k; + # } + # Log 1, $res2; #} - #Log 1, $res2; #-- process results + #$res="000000000".$res + # if(length($res)==10); my @data=split(//,$res); - return "invalid data length" + return "OWTHERM: invalid data length, ".int(@data)." bytes" if (@data != 19); - return "invalid data" + return "OWXTHERM: invalid data" if (ord($data[17])<=0); - return "invalid CRC" + return "OWXTHERM: invalid CRC" if (OWX_CRC8(substr($res,10,8),$data[18])==0); #-- this must be different for the different device types