diff --git a/fhem/contrib/1-Wire/00_OWX.pm b/fhem/contrib/1-Wire/00_OWX.pm index d490efa11..8d1ef012d 100644 --- a/fhem/contrib/1-Wire/00_OWX.pm +++ b/fhem/contrib/1-Wire/00_OWX.pm @@ -9,7 +9,7 @@ # Internally these interfaces are vastly different, read the corresponding Wiki pages # http://fhemwiki.de/wiki/Interfaces_f%C3%BCr_1-Wire # -# Version 2.15 - July, 2012 +# Version 2.17 - August, 2012 # # Prof. Dr. Peter A. Henning, 2012 # @@ -57,9 +57,10 @@ package main; use strict; use warnings; use Device::SerialPort; - -# Prototypes to make komodo happy use vars qw{%attr %defs}; + +require "$attr{global}{modpath}/FHEM/DevIo.pm"; + sub Log($$); # Line counter @@ -129,6 +130,105 @@ sub OWX_Initialize ($) { $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 buspower:real,parasitic"; } +######################################################################################## +# +# OWX_Define - Implements DefFn function +# +# Parameter hash = hash of device addressed, def = definition string +# +######################################################################################## + +sub OWX_Define ($$) { + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + + #-- check syntax + if(int(@a) < 3){ + return "OWX: Syntax error - must be define OWX" + } + + #-- check syntax + Log 1,"OWX: Warning - Some parameter(s) ignored, must be define OWX |" + if(int(@a) > 3); + #-- If this line contains 3 parameters, it is the bus master definition + my $dev = $a[2]; + + #-- TODO: what should we do when the specified device name contains @ already ? + $hash->{DeviceName} = $dev."\@9600"; + #-- Dummy 1-Wire ROM identifier + $hash->{ROM_ID} = "FF"; + + #-- First step: check if we have a directly connected serial interface or a CUNO attached + # (mod suggested by T.Faust) + if ( $dev =~ m/\/dev\/.*/ ){ + #-- 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); + $owx_hwdevice = $hash->{USBDev}; + if($ret){ + Log 1, $msg." not defined"; + return "OWX: Can't open serial device $dev: $!" + } else { + Log 1,$msg." defined"; + } + $owx_hwdevice->reset_error(); + $owx_hwdevice->baudrate(9600); + $owx_hwdevice->databits(8); + $owx_hwdevice->parity('none'); + $owx_hwdevice->stopbits(1); + $owx_hwdevice->handshake('none'); + $owx_hwdevice->write_settings; + #-- store with OWX device + $hash->{INTERFACE} = "serial"; + $hash->{HWDEVICE} = $owx_hwdevice; + + #-- sleeping for some time + select(undef,undef,undef,0.1); + + } else { + #-- Second step in case of CUNO: See if we can open it + my $msg = "OWX: CUNO device $dev"; + $owx_hwdevice = $main::defs{$dev}; + if($owx_hwdevice){ + Log 1,$msg." defined"; + #-- store with OWX device + $hash->{INTERFACE} = "CUNO"; + $hash->{HWDEVICE} = $owx_hwdevice; + #-- reset the 1-Wire system in CUNO + CUL_SimpleWrite($owx_hwdevice, "Oi"); + }else{ + Log 1, $msg." not defined"; + return "OWX: Can't open cuno device $dev: $!" + } + } + #-- Third step: see, if a bus interface is detected + if (!OWX_Detect($hash)){ + $hash->{STATE} = "Failed"; + $hash->{PRESENT} = 0; + $init_done = 1; + return undef; + } + + #-- In 10 seconds discover all devices on the 1-Wire bus + InternalTimer(gettimeofday()+10, "OWX_Discover", $hash,0); + + #-- Default settings + $hash->{interval} = 300; # kick every minute + $hash->{followAlarms} = "off"; + $hash->{ALARMED} = "no"; + + #-- InternalTimer blocks if init_done is not true + my $oid = $init_done; + $hash->{PRESENT} = 1; + $hash->{STATE} = "Initialized"; + $init_done = 1; + #-- Intiate first alarm detection and eventually conversion in a minute or so + InternalTimer(gettimeofday() + $hash->{interval}, "OWX_Kick", $hash,1); + $init_done = $oid; + $hash->{STATE} = "Active"; + return undef; +} + ######################################################################################## # # OWX_Alarms - Find devices on the 1-Wire bus, @@ -143,6 +243,7 @@ sub OWX_Initialize ($) { sub OWX_Alarms ($) { my ($hash) = @_; + my $name = $hash->{NAME}; my @owx_alarm_names=(); #-- Discover all alarmed devices on the 1-Wire bus @@ -152,13 +253,13 @@ sub OWX_Alarms ($) { $res = $res & OWX_Next_SER($hash,"alarm"); } if( @owx_alarm_devs == 0){ - return "OWX: No alarmed 1-Wire devices found "; + return "OWX: No alarmed 1-Wire devices found on bus $name"; } #-- walk through all the devices to get their proper fhem names foreach my $fhem_dev (sort keys %main::defs) { #-- skip if busmaster - next if( $hash->{NAME} eq $main::defs{$fhem_dev}{NAME} ); + next if( $name eq $main::defs{$fhem_dev}{NAME} ); #-- all OW types start with OW next if( substr($main::defs{$fhem_dev}{TYPE},0,2) ne "OW"); foreach my $owx_dev (@owx_alarm_devs) { @@ -175,7 +276,7 @@ sub OWX_Alarms ($) { } } #-- so far, so good - what do we want to do with this ? - return "OWX: Alarmed 1-Wire devices found (".join(",",@owx_alarm_names).")"; + return "OWX: Alarmed 1-Wire devices found on bus $name (".join(",",@owx_alarm_names).")"; } ######################################################################################## @@ -194,14 +295,15 @@ sub OWX_Alarms ($) { sub OWX_Complex ($$$$) { my ($hash,$owx_dev,$data,$numread) =@_; - + my $name = $hash->{NAME}; + #-- get the interface $owx_interface = $hash->{INTERFACE}; $owx_hwdevice = $hash->{HWDEVICE}; #-- interface error if( !(defined($owx_interface))){ - Log 3,"OWX: Complex called with unknown interface"; + Log 3,"OWX: Complex called with unknown interface on bus $name"; return 0; #-- here we treat the directly connected serial interfaces }elsif( ($owx_interface eq "DS2480") || ($owx_interface eq "DS9097") ){ @@ -213,7 +315,7 @@ sub OWX_Complex ($$$$) { #-- interface error }else{ - Log 3,"OWX: Complex called with unknown interface"; + Log 3,"OWX: Complex called with unknown interface $owx_interface on bus $name"; return 0; } } @@ -226,10 +328,7 @@ sub OWX_Complex ($$$$) { # ######################################################################################## -sub OWX_CRC ($) { - my ($romid) = @_; - - my @crc8_table = ( +my @crc8_table = ( 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, @@ -247,6 +346,9 @@ sub OWX_CRC ($) { 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53); + +sub OWX_CRC ($) { + my ($romid) = @_; my $crc8=0; if( $romid eq "0" ){ @@ -267,6 +369,36 @@ sub OWX_CRC ($) { } } +######################################################################################## +# +# OWX_CRC - Check the CRC8 code of an a byte string +# +# Parameter string, crc. +# If crc is defined, make a comparison, otherwise output crc8 +# +######################################################################################## + +sub OWX_CRC8 ($$) { + my ($string,$crc) = @_; + my $crc8=0; + my @strhex; + + for(my $i=0; $i<8; $i++){ + $strhex[$i]=ord(substr($string,$i,1)); + $crc8 = $crc8_table[ $crc8 ^ $strhex[$i] ]; + } + + if( defined($crc) ){ + if ( $crc = $crc8 ){ + return 1; + }else{ + return 0; + } + }else{ + return $crc8; + } +} + ######################################################################################## # # OWX_CRC16 - Calculate the CRC16 code of a string @@ -318,103 +450,6 @@ sub OWX_DOCRC16($$) { #//... #} - - -######################################################################################## -# -# OWX_Define - Implements DefFn function -# -# Parameter hash = hash of device addressed, def = definition string -# -######################################################################################## - -sub OWX_Define ($$) { - my ($hash, $def) = @_; - my @a = split("[ \t][ \t]*", $def); - - if(int(@a) >= 3){ - #-- check syntax - Log 1,"OWX: Warning - Some parameter(s) ignored, must be define OWX |" - if(int(@a) > 3); - #-- If this line contains 3 parameters, it is the bus master definition - my $dev = $a[2]; - $hash->{DeviceName} = $dev; - #-- Dummy 1-Wire ROM identifier - $hash->{ROM_ID} = "FF"; - - #-- First step: check if we have a directly connected serial interface or a CUNO attached - if ( $dev =~ m/.*USB.*/){ - #-- Second step in case of serial device: open the serial device to test it - my $msg = "OWX: Serial device $dev"; - $owx_hwdevice = new Device::SerialPort ($dev); - if($owx_hwdevice){ - Log 1,$msg." defined"; - }else{ - Log 1, $msg." not defined"; - return "OWX: Can't open serial device $dev: $!" - } - $owx_hwdevice->reset_error(); - $owx_hwdevice->baudrate(9600); - $owx_hwdevice->databits(8); - $owx_hwdevice->parity('none'); - $owx_hwdevice->stopbits(1); - $owx_hwdevice->handshake('none'); - $owx_hwdevice->write_settings; - #-- store with OWX device - $hash->{INTERFACE} = "serial"; - $hash->{HWDEVICE} = $owx_hwdevice; - #-- sleeping for some time - select(undef,undef,undef,0.1); - } else { - #-- Second step in case of CUNO: See if we can open it - my $msg = "OWX: CUNO device $dev"; - $owx_hwdevice = $main::defs{$dev}; - if($owx_hwdevice){ - Log 1,$msg." defined"; - #-- store with OWX device - $hash->{INTERFACE} = "CUNO"; - $hash->{HWDEVICE} = $owx_hwdevice; - #-- reset the 1-Wire system in CUNO - CUL_SimpleWrite($owx_hwdevice, "Oi"); - }else{ - Log 1, $msg." not defined"; - return "OWX: Can't open cuno device $dev: $!" - } - } - - #-- Third step: see, if a bus interface is detected - if (!OWX_Detect($hash)){ - $hash->{STATE} = "Failed"; - $hash->{PRESENT} = 0; - $init_done = 1; - return undef; - } - - #-- In 10 seconds discover all devices on the 1-Wire bus - InternalTimer(gettimeofday()+10, "OWX_Discover", $hash,0); - - #-- Default settings - $hash->{interval} = 300; # kick every minute - $hash->{followAlarms} = "off"; - $hash->{ALARMED} = "no"; - - #-- InternalTimer blocks if init_done is not true - my $oid = $init_done; - $hash->{PRESENT} = 1; - $hash->{STATE} = "Initialized"; - $init_done = 1; - - #-- Intiate first alarm detection and eventually conversion in a minute or so - InternalTimer(gettimeofday() + $hash->{interval}, "OWX_Kick", $hash,1); - $init_done = $oid; - $hash->{STATE} = "Active"; - return undef; - } else { - #-- check syntax - return "OWX: Syntax error - must be define OWX" - } -} - ######################################################################################## # # OWX_Detect - Detect 1-Wire interface @@ -433,7 +468,10 @@ sub OWX_Detect ($) { my ($hash) = @_; my ($i,$j,$k,$l,$res,$ret,$ress); - + my $name = $hash->{NAME}; + my $ress0 = "OWX: 1-Wire bus $name: interface "; + $ress = $ress0; + #-- get the interface $owx_interface = $hash->{INTERFACE}; $owx_hwdevice = $hash->{HWDEVICE}; @@ -449,16 +487,19 @@ sub OWX_Detect ($) { $res = OWX_Query_2480($hash,"\x17\x45\x5B\x0F\x91"); #-- process 4/5-byte string for detection - if( ($res eq "\x16\x44\x5A\x00\x90") || ($res eq "\x16\x44\x5A\x00\x93")){ - Log 1, "OWX: 1-Wire bus master DS2480 detected for the first time"; + if( !defined($res)){ + $res=""; + $ret=0; + }elsif( ($res eq "\x16\x44\x5A\x00\x90") || ($res eq "\x16\x44\x5A\x00\x93")){ + $ress .= "master DS2480 detected for the first time"; $owx_interface="DS2480"; $ret=1; } elsif( $res eq "\x17\x45\x5B\x0F\x91"){ - Log 1, "OWX: 1-Wire bus master DS2480 re-detected"; + $ress .= "master DS2480 re-detected"; $owx_interface="DS2480"; $ret=1; - } elsif( ($res eq "\x17\x0A\x5B\x0F\x02") || ($res eq "\x00\x17\x0A\x5B\x0F\x02") ){ - Log 1, "OWX: Passive 1-Wire bus interface DS9097 detected"; + } elsif( ($res eq "\x17\x0A\x5B\x0F\x02") || ($res eq "\x00\x17\x0A\x5B\x0F\x02") || ($res eq "\x30\xf8\x00") ){ + $ress .= "passive DS9097 detected"; $owx_interface="DS9097"; $ret=1; } else { @@ -466,19 +507,20 @@ sub OWX_Detect ($) { } last if( $ret==1 ); - $ress = "OWX: Trying again to detect an interface, answer was "; + $ress .= "not found, answer was "; for($i=0;$i{NAME}; #-- get the interface $owx_interface = $hash->{INTERFACE}; @@ -649,8 +692,8 @@ sub OWX_Discover ($) { Log 1, "OWX: Deleting unused 1-Wire device $main::defs{$fhem_dev}{NAME} of type $main::defs{$fhem_dev}{TYPE}"; CommandDelete(undef,$main::defs{$fhem_dev}{NAME}); } - Log 1, "OWX: 1-Wire devices found (".join(",",@owx_names).")"; - return "OWX: 1-Wire devices found (".join(",",@owx_names).")"; + Log 1, "OWX: 1-Wire devices found on bus $name: (".join(",",@owx_names).")"; + return "OWX: 1-Wire devices found on bus $name: (".join(",",@owx_names).")"; } ######################################################################################## @@ -738,7 +781,7 @@ sub OWX_Reset ($) { #-- interface error if( !(defined($owx_interface))){ - Log 3,"OWX: Reset called with unknown interface"; + Log 3,"OWX: Reset called with undefined interface"; return 0; }elsif( $owx_interface eq "DS2480" ){ return OWX_Reset_2480($hash); @@ -747,7 +790,7 @@ sub OWX_Reset ($) { }elsif( $owx_interface eq "CUNO" ){ return OWX_Reset_CUNO($hash); }else{ - Log 3,"OWX: Reset called with unknown interface"; + Log 3,"OWX: Reset called with unknown interface $owx_interface"; return 0; } } @@ -815,6 +858,7 @@ sub OWX_Set($@) { sub OWX_Undef ($$) { my ($hash, $name) = @_; RemoveInternalTimer($hash); + DevIo_CloseDev($hash); return undef; } @@ -1221,8 +1265,8 @@ sub OWX_Query_2480 ($$) { my ($hash,$cmd) = @_; my ($i,$j,$k); - my $dev = $hash->{DeviceName}; - + + $owx_hwdevice = $hash->{HWDEVICE}; $owx_hwdevice->baudrate($owx_baud); $owx_hwdevice->write_settings; @@ -1235,7 +1279,7 @@ sub OWX_Query_2480 ($$) { } Log 3, $res; } - + my $count_out = $owx_hwdevice->write($cmd); Log 1, "OWX: Write incomplete $count_out ne ".(length($cmd))."" if ( $count_out != length($cmd) ); @@ -1257,8 +1301,6 @@ sub OWX_Query_2480 ($$) { #-- sleeping for some time select(undef,undef,undef,0.04); - - #$owx_hwdevice->close(); return($string_in); } @@ -1280,7 +1322,7 @@ sub OWX_Reset_2480 ($) { my ($res,$r1,$r2); #-- if necessary, prepend \xE3 character for command mode - if( $owx_mode ne "command" ) { + if( $owx_mode ne "command" ){ $cmd = "\xE3"; } #-- Reset command \xC5 @@ -1504,11 +1546,10 @@ sub OWX_Query_9097 ($$) { my ($hash,$cmd) = @_; my ($i,$j,$k); - my $dev = $hash->{DeviceName}; - + $owx_hwdevice = $hash->{HWDEVICE}; $owx_hwdevice->baudrate($owx_baud); $owx_hwdevice->write_settings; - + if( $owx_debug > 2){ my $res = "OWX: Sending out "; for($i=0;$iread(48); - if( $owx_debug > 2){ + if( $owx_debug > 2){ my $res = "OWX: Receiving "; for($i=0;$i<$count_in;$i++){ $j=int(ord(substr($string_in,$i,1))/16); @@ -1540,8 +1581,7 @@ sub OWX_Query_9097 ($$) { #-- sleeping for some time select(undef,undef,undef,0.01); - - #$owx_hwdevice->close(); + return($string_in); } diff --git a/fhem/contrib/1-Wire/21_OWCOUNT.pm b/fhem/contrib/1-Wire/21_OWCOUNT.pm index 9fc0a02d0..c6c158a4c 100644 --- a/fhem/contrib/1-Wire/21_OWCOUNT.pm +++ b/fhem/contrib/1-Wire/21_OWCOUNT.pm @@ -14,7 +14,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 2.15 - July, 2012 +# Version 2.17 - August, 2012 # # Setup bus device in fhem.cfg as # @@ -290,13 +290,6 @@ sub OWCOUNT_InitializeDevice($) { $hash->{READINGS}{"$owg_rate[$i]"}{UNITABBR} = $unarr[1].$runit; #Log 1,"OWCOUNT InitializeDevice with period $period and UNITABBR = ".$hash->{READINGS}{"$owg_rate[$i]"}{UNITABBR}; - #-- remove units if they are unwanted - if( defined($attr{$name}{"UnitInReading"})){ - if( $attr{$name}{"UnitInReading"} == 0){ - $hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR} = ""; - $hash->{READINGS}{"$owg_rate[$i]"}{UNITABBR} = ""; - } - } } #-- set status according to interface type @@ -319,9 +312,9 @@ sub OWCOUNT_InitializeDevice($) { ######################################################################################## # -# OWCOUNT_FormatValues - put together various format strings +# OWCOUNT_FormatValues - put together various format strings and assemble STATE variable # -# Parameter hash = hash of device addressed, fs = format string +# Parameter hash = hash of device addressed # ######################################################################################## @@ -329,7 +322,7 @@ sub OWCOUNT_FormatValues($) { my ($hash) = @_; my $name = $hash->{NAME}; - my ($offset,$factor,$present,$period,$unit,$runit,$midnight,$vval,$vrate); + my ($offset,$factor,$period,$unit,$runit,$midnight,$vval,$vrate); my ($value1,$value2,$value3,$value4,$value5) = ("","","","",""); my $galarm = 0; @@ -339,6 +332,10 @@ sub OWCOUNT_FormatValues($) { my $daybreak = 0; my $monthbreak = 0; + my $present = $hash->{PRESENT}; + #-- remove units if they are unwanted + my $unir = defined($attr{$name}{"UnitInReading"}) ? $attr{$name}{"UnitInReading"} : 1; + #-- 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}; - $present = $hash->{PRESENT}; + $period = $hash->{READINGS}{"$owg_channel[$i]"}{PERIOD}; + $runit = $hash->{READINGS}{"$owg_rate[$i]"}{UNITABBR}; #-- only if attribute value Mode=daily, take the midnight value from memory if( defined($attr{$name}{$owg_fixed[$i]."Mode"} )){ @@ -362,21 +360,16 @@ sub OWCOUNT_FormatValues($) { } 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; - #-- string buildup for return value and STATE - $value1 .= sprintf( "%s: %5.1f %s", $owg_channel[$i], $vval,$unit); - $value2 .= sprintf( "%s: %5.1f %s ", $owg_channel[$i], $vval,$unit); #-- 3 decimals } else { $vval = int((($owg_val[$i] + $offset)*$factor - $midnight)*1000)/1000; - #-- string buildup for return value and STATE - $value1 .= sprintf( "%s: %5.3f %s", $owg_channel[$i], $vval,$unit); - $value2 .= sprintf( "%s: %5.2f %s ", $owg_channel[$i], $vval,$unit); } - $value3 .= sprintf( "%s: " , $owg_channel[$i]); #-- get the old values my $oldval = $hash->{READINGS}{"$owg_channel[$i]"}{VAL}; @@ -398,40 +391,20 @@ sub OWCOUNT_FormatValues($) { if( ($vval < $oldval) && ($daybreak==0) && ($present==1) ){ Log 1,"OWCOUNT TODO: Counter wraparound"; } - #-- rate - if( $delt > 0 ){ - $vrate = ($vval-$oldval)/$delt; - } else { - Log 1, "OWCOUNT: Invalid time interval $delt for rate calculation"; - $vrate = 0.0; - } - #-- correct rate for wraparound at midnight - if( ($vrate < 0) && ($hash->{PRESENT}==1) ){ - Log 1,"OWCOUNT: correcting raw rate directly after midnight from $vrate to ".($vrate+$midnight/$delt)." vval=$vval, oldval=$oldval, delt=$delt"; - $vrate += $midnight/$delt; - } - #-- correct rate for peroid setting - $period = $hash->{READINGS}{"$owg_channel[$i]"}{PERIOD}; - if( $period eq "hour" ){ - $vrate*=3600; - }elsif( $period eq "minute" ){ - $vrate*=60; - } - $runit = $hash->{READINGS}{"$owg_rate[$i]"}{UNITABBR}; - #-- string buildup for return value and STATE - $value1 .= sprintf( " %5.3f %s", $vrate,$runit); - $value2 .= sprintf( " %5.2f %s ",$vrate,$runit); - + if( $daybreak==1 ){ - #-- we need to check this ! - Log 1,"OWCOUNT: Daybreak routine called with oldtim=$oldtim and day=$day and present=".$present; #-- linear interpolation my $dt = ((24-$houro)*3600 -$mino*60 - $seco)/( ($hour+24-$houro)*3600 + ($min-$mino)*60 + ($sec-$seco) ); my $dv = $oldval*(1-$dt)+$vval*$dt; + #-- correct reading in daily mode + if( $midnight > 0.0 ){ + $vval -= $dv; + $delt *= (1-$dt); + $oldval = 0.0; + } + #-- in any mode store the interpolated value in the midnight store $midnight += $dv; - #-- in any mode, when midnight has passed, store the interpolated value in the midnight store OWXCOUNT_SetPage($hash,14+$i,sprintf("%f",$midnight)); - Log 1, "OWCOUNT: Interpolated additional value for channel ".$owg_channel[$i]." is ".$dv." at time ".$tn; #-- string buildup for monthly logging $value4 .= sprintf( "%s: %5.1f %s", $owg_channel[$i], $dv,$unit); if( $day<$dayo ){ @@ -440,12 +413,53 @@ sub OWCOUNT_FormatValues($) { #-- string buildup for yearly logging $value5 .= sprintf( "%s: %5.1f %s", $owg_channel[$i], $dv,$unit); } + } + #-- rate + if( ($delt > 0.0) && $present ){ + $vrate = ($vval-$oldval)/$delt; + } else { + $vrate = 0.0; } + #-- correct rate for period setting + if( $period eq "hour" ){ + $vrate*=3600; + }elsif( $period eq "minute" ){ + $vrate*=60; + } + + if( !defined($runit) ){ + Log 1,"OWCOUNT: Error in rate unit definition. i=$i, owg_rate[i]=".$owg_rate[$i]; + $runit = "ERR"; + } + + #-- string buildup for return value and STATE + if( $unir ){ + #-- 1 decimal + if( $factor == 1.0 ){ + $value1 .= sprintf( "%s: %5.1f %s %5.2f %s", $owg_channel[$i], $vval,$unit,$vrate,$runit); + $value2 .= sprintf( "%s: %5.1f %s %5.2f %s", $owg_channel[$i], $vval,$unit,$vrate,$runit); + #-- 3 decimals + } else { + $value1 .= sprintf( "%s: %5.3f %s %5.2f %s", $owg_channel[$i], $vval,$unit,$vrate,$runit); + $value2 .= sprintf( "%s: %5.2f %s %5.2f %s", $owg_channel[$i], $vval,$unit,$vrate,$runit); + } + }else { + #-- 1 decimal + if( $factor == 1.0 ){ + $value1 .= sprintf( "%s: %5.1f %5.2f", $owg_channel[$i], $vval,$vrate); + $value2 .= sprintf( "%s: %5.1f %5.2f", $owg_channel[$i], $vval,$vrate); + #-- 3 decimals + } else { + $value1 .= sprintf( "%s: %5.3f %5.2f", $owg_channel[$i], $vval,$vrate); + $value2 .= sprintf( "%s: %5.2f %5.2f", $owg_channel[$i], $vval,$vrate); + } + } + $value3 .= sprintf( "%s: " , $owg_channel[$i]); } #-- put into READINGS $hash->{READINGS}{"$owg_channel[$i]"}{VAL} = $vval; #-- but times and rate only when valid - if( $hash->{PRESENT}==1 ){ + if( $present ){ $hash->{READINGS}{"$owg_channel[$i]"}{TIME} = $tn; $hash->{READINGS}{"$owg_rate[$i]"}{VAL} = $vrate; $hash->{READINGS}{"$owg_rate[$i]"}{TIME} = $tn; @@ -465,6 +479,12 @@ sub OWCOUNT_FormatValues($) { } #-- STATE $hash->{STATE} = $value2; + + #-- write units as header if they are unwanted in lines + if( $unir == 0 ){ + #TODO: the entry into CHANGED must be into the lowest array position + } + if( $daybreak == 1 ){ $value4 = sprintf("D_%d: %d-%d-%d_23:59:59 %s",$dayo,$yearo,$montho,$dayo,$value4); #-- needs to be higher array elements, @@ -896,8 +916,8 @@ sub OWXCOUNT_GetPage($$) { return "OWXCOUNT: Device $owx_dev returns invalid data"; } - #-- first ignore memory and only use counter - my $value = ord($data[3])*4096 + ord($data[2])*256 +ord($data[1])*16 + ord($data[0]); + #-- first ignore memory and only use counter (Fehler gefunden von jamesgo) + my $value = (ord($data[3])<<32) + (ord($data[2])<<16) +(ord($data[1])<<8) + ord($data[0]); if( $page == 14) { $owg_val[0] = $value; diff --git a/fhem/contrib/1-Wire/21_OWTHERM.pm b/fhem/contrib/1-Wire/21_OWTHERM.pm index a36c09a75..3713ae1f5 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.13 - July, 2012 +# Version 2.17 - August, 2012 # # Setup bus device in fhem.cfg as # @@ -457,7 +457,12 @@ sub OWTHERM_GetValues($@) { #-- Get values according to interface type my $interface= $hash->{IODev}->{TYPE}; if( $interface eq "OWX" ){ - $ret = OWXTHERM_GetValues($hash); + #-- max 3 tries + for(my $try=0; $try<3; $try++){ + $ret = OWXTHERM_GetValues($hash); + last + if( !defined($ret) ); + } }elsif( $interface eq "OWFS" ){ $ret = OWFSTHERM_GetValues($hash); }else{ @@ -466,7 +471,7 @@ sub OWTHERM_GetValues($@) { #-- process results if( defined($ret) ){ - return "OWTHERM: Could not get values from device $name"; + return "OWTHERM: Could not get values from device $name, reason $ret"; } $hash->{PRESENT} = 1; $value=OWTHERM_FormatValues($hash); @@ -652,7 +657,6 @@ sub OWXTHERM_GetValues($) { my $owx_dev = $hash->{ROM_ID}; #-- hash of the busmaster my $master = $hash->{IODev}; - #-- 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") ){ @@ -691,58 +695,62 @@ sub OWXTHERM_GetValues($) { #-- process results my @data=split(//,$res); + return "invalid data length" + if (@data != 19); + return "invalid data" + if (ord($data[17])<=0); + return "invalid CRC" + if (OWX_CRC8(substr($res,10,8),$data[18])==0); + #-- this must be different for the different device types # family = 10 => DS1820, DS18S20 - if( $hash->{OW_FAMILY} eq "10" ) { - if ( (@data == 19) && (ord($data[17])>0) ){ - my $count_remain = ord($data[16]); - my $count_perc = ord($data[17]); - my $delta = -0.25 + ($count_perc - $count_remain)/$count_perc; + if( $hash->{OW_FAMILY} eq "10" ) { - my $lsb = ord($data[10]); - my $msb = 0; - my $sign = ord($data[11]) & 255; - - #-- test with -25 degrees - #$lsb = 12*16+14; - #$sign = 1; - #$delta = 0; - - #-- 2's complement form = signed bytes - $owg_temp = int($lsb/2) + $delta; - if( $sign !=0 ){ - $owg_temp = -128+$owg_temp; - } - - $owg_th = ord($data[12]) > 127 ? 128-ord($data[12]) : ord($data[12]); - $owg_tl = ord($data[13]) > 127 ? 128-ord($data[13]) : ord($data[13]); - return undef; - } else { - return "OWXTHERM: Device $owx_dev returns invalid data"; - } - } elsif ( ($hash->{OW_FAMILY} eq "22") || ($hash->{OW_FAMILY} eq "28") ) { - if ( (@data == 19) && (ord($data[17])>0) ){ + my $count_remain = ord($data[16]); + my $count_perc = ord($data[17]); + my $delta = -0.25 + ($count_perc - $count_remain)/$count_perc; - my $lsb = ord($data[10]); - my $msb = ord($data[11]) & 7; - my $sign = ord($data[11]) & 248; + my $lsb = ord($data[10]); + my $msb = 0; + my $sign = ord($data[11]) & 255; - #-- test with -55 degrees - #$lsb = 9*16; - #$sign = 1; - #$msb = 7; + #-- test with -25 degrees + #$lsb = 12*16+14; + #$sign = 1; + #$delta = 0; - #-- 2's complement form = signed bytes - $owg_temp = $msb*16+ $lsb/16; - if( $sign !=0 ){ - $owg_temp = -128+$owg_temp; - } - $owg_th = ord($data[12]) > 127 ? 128-ord($data[12]) : ord($data[12]); - $owg_tl = ord($data[13]) > 127 ? 128-ord($data[13]) : ord($data[13]); - return undef; - } else { - return "OWXTHERM: Device $owx_dev returns invalid data"; + #-- 2's complement form = signed bytes + $owg_temp = int($lsb/2) + $delta; + if( $sign !=0 ){ + $owg_temp = -128+$owg_temp; } + + $owg_th = ord($data[12]) > 127 ? 128-ord($data[12]) : ord($data[12]); + $owg_tl = ord($data[13]) > 127 ? 128-ord($data[13]) : ord($data[13]); + + return undef; + + } elsif ( ($hash->{OW_FAMILY} eq "22") || ($hash->{OW_FAMILY} eq "28") ) { + + my $lsb = ord($data[10]); + my $msb = ord($data[11]) & 7; + my $sign = ord($data[11]) & 248; + + #-- test with -55 degrees + #$lsb = 9*16; + #$sign = 1; + #$msb = 7; + + #-- 2's complement form = signed bytes + $owg_temp = $msb*16+ $lsb/16; + if( $sign !=0 ){ + $owg_temp = -128+$owg_temp; + } + $owg_th = ord($data[12]) > 127 ? 128-ord($data[12]) : ord($data[12]); + $owg_tl = ord($data[13]) > 127 ? 128-ord($data[13]) : ord($data[13]); + + return undef; + } else { return "OWXTHERM: Unknown device family $hash->{OW_FAMILY}\n"; }