diff --git a/fhem/contrib/1-Wire/00_OWX.pm b/fhem/contrib/1-Wire/00_OWX.pm index 9beee0d62..12c2a5dc9 100644 --- a/fhem/contrib/1-Wire/00_OWX.pm +++ b/fhem/contrib/1-Wire/00_OWX.pm @@ -4,18 +4,21 @@ # # FHEM module to commmunicate directly with 1-Wire bus devices # via an active DS2480/DS2490/DS9097U bus master interface or -# via a passive DS9097 interface +# via a passive DS9097 interface or +# via a network-attached CUNO # -# Version 1.15 - June, 2012 +# Version 2.0 - June, 2012 # # Prof. Dr. Peter A. Henning, 2012 # # Setup interface as: # -# define OWX +# define OWX for USB interfaces or +# define OWX for a CUNO interface # # where may be replaced by any name string -# is a serial (USB) device +# is a serial (USB) device +# is a CUNO device # # get alarms => find alarmed 1-Wire devices # get devices => find all 1-Wire devices @@ -80,9 +83,10 @@ my %attrs = ( #-- some globals needed for the 1-Wire module my $owx_serport; +my $owx_cuno; #-- baud rate serial interface my $owx_baud=9600; -#-- Debugging +#-- Debugging 0,1,2,3 my $owx_debug=0; #-- bus master mode my $owx_mode="undef"; @@ -117,7 +121,6 @@ my $owx_LastDeviceFlag = 0; sub OWX_Initialize ($) { my ($hash) = @_; #-- Provider - #$hash->{Clients} = ":OWCOUNT:OWHUB:OWLCD:OWMULTI:OWSWITCH:OWTEMP:"; $hash->{Clients} = ":OWAD:OWCOUNT:OWID:OWLCD:OWSWITCH:OWTEMP:"; #-- Normal Devices @@ -146,9 +149,9 @@ sub OWX_Alarms ($) { #-- Discover all alarmed devices on the 1-Wire bus @owx_alarm_devs=(); - my $res = OWX_First($hash,"alarm"); + my $res = OWX_First_SER($hash,"alarm"); while( $owx_LastDeviceFlag==0 && $res != 0){ - $res = $res & OWX_Next($hash,"alarm"); + $res = $res & OWX_Next_SER($hash,"alarm"); } if( @owx_alarm_devs == 0){ return "OWX: No alarmed 1-Wire devices found "; @@ -179,24 +182,32 @@ sub OWX_Alarms ($) { ######################################################################################## # -# OWX_Block - Send data block +# OWX_Complex - Send match ROM, data block and receive bytes as response # -# Parameter hash = hash of bus master, data = string to send +# Parameter hash = hash of bus master, +# owx_dev = ROM ID of device +# data = string to send +# numread = number of bytes to receive # # Return response, if OK # 0 if not OK # ######################################################################################## -sub OWX_Block ($$) { - my ($hash,$data) =@_; +sub OWX_Complex ($$$$) { + my ($hash,$owx_dev,$data,$numread) =@_; - if( $owx_interface eq "DS2480" ){ - return OWX_Block_2480($hash,$data); - }elsif( $owx_interface eq "DS9097" ){ - return OWX_Block_9097($hash,$data); + #-- here we treat the directly connected serial interfaces + if( ($owx_interface eq "DS2480") || ($owx_interface eq "DS9097") ){ + return OWX_Complex_SER($hash,$owx_dev,$data,$numread); + + #-- here we treat the network-connected CUNO + }elsif( $owx_interface eq "CUNO" ){ + return OWX_Complex_CUNO($hash,$owx_dev,$data,$numread); + + #-- interface error }else{ - Log 1,"OWX: Block called with unknown interface"; + Log 1,"OWX: Complex called with unknown interface"; return 0; } } @@ -252,7 +263,9 @@ sub OWX_CRC ($) { ######################################################################################## # -# OWX_CRC16 - Calculate the CRC16 code of a string +# OWX_CRC16 - Calculate the CRC16 code of a string +# +# TODO UNFINISHED CODE # # Parameter crc - previous CRC code, c next character # @@ -315,7 +328,7 @@ sub OWX_Define ($$) { if(int(@a) >= 3){ #-- check syntax - Log 1,"OWX: Warning - Some parameter(s) ignored, must be define OWX" + 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]; @@ -323,30 +336,48 @@ sub OWX_Define ($$) { #-- Dummy 1-Wire ROM identifier $hash->{ROM_ID} = "FF"; - #-- First step: open the serial device to test it - #Log 3, "OWX opening device $dev"; - $owx_serport = new Device::SerialPort ($dev); - return "OWX: Can't open $dev: $!" if(!$owx_serport); - Log 3, "OWX: opened device $dev"; - $owx_serport->reset_error(); - $owx_serport->baudrate(9600); - $owx_serport->databits(8); - $owx_serport->parity('none'); - $owx_serport->stopbits(1); - $owx_serport->handshake('none'); - $owx_serport->write_settings; - #-- sleeping for some time - select(undef,undef,undef,0.1); - #$owx_serport->close(); + #-- 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_serport = new Device::SerialPort ($dev); + if($owx_serport){ + Log 1,$msg." defined"; + }else{ + Log 1, $msg." not defined"; + return "OWX: Can't open serial device $dev: $!" + } + $owx_serport->reset_error(); + $owx_serport->baudrate(9600); + $owx_serport->databits(8); + $owx_serport->parity('none'); + $owx_serport->stopbits(1); + $owx_serport->handshake('none'); + $owx_serport->write_settings; + #-- 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_cuno = $main::defs{$dev}; + if($owx_cuno){ + Log 1,$msg." defined"; + #-- reset the 1-Wire system in CUNO + CUL_SimpleWrite($owx_cuno, "Oi"); + }else{ + Log 1, $msg." not defined"; + return "OWX: Can't open cuno device $dev: $!" + } + } - #-- Second step: see, if a bus interface is detected + #-- 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); @@ -375,7 +406,8 @@ sub OWX_Define ($$) { ######################################################################################## # -# OWX_Detect - Detect 1-Wire interface +# OWX_Detect - Detect 1-Wire interface +# TODO: HAS TO BE SPLIT INTO INTERFACE DEPENDENT AND INDEPENDENT PART # # Method rather crude - treated as an 2480, and see whatis returned # @@ -390,59 +422,70 @@ sub OWX_Detect ($) { my ($hash) = @_; my ($i,$j,$k,$l,$res,$ret,$ress); - #-- timing byte for DS2480 - OWX_Query_2480($hash,"\xC1\xC1"); - #-- Max 4 tries to detect an interface - for($l=0;$l<4;$l++) { - #-- write 1-Wire bus (Fig. 2 of Maxim AN192) - $res = OWX_Query_2480($hash,"\x17\x45\x5B\x0F\x91"); - #$ress = "OWX: Answer was "; - #for($i=0;$i{NAME}"; + $owx_interface="CUNO"; $ret=1; } else { + Log 1, "OWX: 1-Wire bus interface in $owx_cuno->{NAME} could not be addressed"; $ret=0; } - last - if( $ret==1 ); - $ress = "OWX: Trying again to detect an interface, answer was "; - for($i=0;$i{NAME} eq $main::defs{$fhem_dev}{NAME} ); @@ -490,7 +554,7 @@ sub OWX_Discover ($) { next if( length($id_fhem) != 15 ); #-- testing if present in defined devices # even with improper family - #print " FHEM-Device = ".substr($id_fhem,3,12)." OWX discovered device ".substr($id_owx,3,12)."\n"; + #Log 1, " FHEM-Device = ".substr($id_fhem,3,12)." OWX discovered device ".substr($id_owx,3,12); if( substr($id_fhem,3,12) eq substr($id_owx,3,12) ) { #-- warn if improper family id if( substr($id_fhem,0,2) ne substr($id_owx,0,2) ){ @@ -564,30 +628,6 @@ sub OWX_Discover ($) { return "OWX: 1-Wire devices found (".join(",",@owx_names).")"; } -######################################################################################## -# -# OWX_First - Find the 'first' devices on the 1-Wire bus -# -# Parameter hash = hash of bus master, mode -# -# Return 1 : device found, ROM number pushed to list -# 0 : no device present -# -######################################################################################## - -sub OWX_First ($$) { - my ($hash,$mode) = @_; - - #-- clear 16 byte of search data - @owx_search=(0,0,0,0 ,0,0,0,0, 0,0,0,0, 0,0,0,0); - #-- reset the search state - $owx_LastDiscrepancy = 0; - $owx_LastDeviceFlag = 0; - $owx_LastFamilyDiscrepancy = 0; - #-- now do the search - return OWX_Search($hash,$mode); -} - ######################################################################################## # # OWX_Get - Implements GetFn function @@ -631,10 +671,9 @@ sub OWX_Get($@) { ######################################################################################## sub OWX_Kick($) { - my($hash) = @_; - my $ret; + #-- Call us in n seconds again. InternalTimer(gettimeofday()+ $hash->{interval}, "OWX_Kick", $hash,1); #-- During reset we see if an alarmed device is present. @@ -643,7 +682,7 @@ sub OWX_Kick($) { #-- Only if we have real power on the bus if( defined($attr{$hash->{NAME}}{buspower}) && ($attr{$hash->{NAME}}{buspower} eq "real") ){ #-- issue the skip ROM command \xCC followed by start conversion command \x44 - $ret = OWX_Block($hash,"\xCC\x44"); + $ret = OWX_Complex($hash,"","\xCC\x44",0); if( $ret eq 0 ){ Log 3, "OWX: Failure in temperature conversion\n"; return 0; @@ -651,28 +690,9 @@ sub OWX_Kick($) { #-- sleeping for some time select(undef,undef,undef,0.5); } - return 1; } -######################################################################################## -# -# OWX_Next - Find the 'next' devices on the 1-Wire bus -# -# Parameter hash = hash of bus master, mode -# -# Return 1 : device found, ROM number in owx_ROM_ID and pushed to list (LastDeviceFlag=0) -# or only in owx_ROM_ID (LastDeviceFlag=1) -# 0 : device not found, or ot searched at all -# -######################################################################################## - -sub OWX_Next ($$) { - my ($hash,$mode) = @_; - #-- now do the search - return OWX_Search($hash,$mode); -} - ######################################################################################## # # OWX_Reset - Reset the 1-Wire bus @@ -685,127 +705,20 @@ sub OWX_Next ($$) { ######################################################################################## sub OWX_Reset ($) { - my ($hash)=@_; + if( $owx_interface eq "DS2480" ){ return OWX_Reset_2480($hash); }elsif( $owx_interface eq "DS9097" ){ return OWX_Reset_9097($hash); + }elsif( $owx_interface eq "CUNO" ){ + return OWX_Reset_CUNO($hash); }else{ Log 1,"OWX: Reset called with unknown interface"; return 0; } } -######################################################################################## -# -# OWX_Search - Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing -# search state. -# -# Parameter hash = hash of bus master, mode=alarm,discover or verify -# -# Return 1 : device found, ROM number in owx_ROM_ID and pushed to list (LastDeviceFlag=0) -# or only in owx_ROM_ID (LastDeviceFlag=1) -# 0 : device not found, or ot searched at all -# -######################################################################################## - -sub OWX_Search ($$) { - my ($hash,$mode)=@_; - - #-- if the last call was the last one, no search - if ($owx_LastDeviceFlag==1){ - return 0; - } - #-- 1-Wire reset - if (OWX_Reset($hash)==0){ - #-- reset the search - Log 1, "OWX: Search reset failed"; - $owx_LastDiscrepancy = 0; - $owx_LastDeviceFlag = 0; - $owx_LastFamilyDiscrepancy = 0; - return 0; - } - - #-- Here we call the device dependent part - if( $owx_interface eq "DS2480" ){ - OWX_Search_2480($hash,$mode); - }elsif( $owx_interface eq "DS9097" ){ - OWX_Search_9097($hash,$mode); - }else{ - Log 1,"OWX: Search called with unknown interface"; - return 0; - } - #--check if we really found a device - if( OWX_CRC(0)!= 0){ - #-- reset the search - Log 1, "OWX: Search CRC failed "; - $owx_LastDiscrepancy = 0; - $owx_LastDeviceFlag = 0; - $owx_LastFamilyDiscrepancy = 0; - return 0; - } - - #-- character version of device ROM_ID, first byte = family - my $dev=sprintf("%02X.%02X%02X%02X%02X%02X%02X.%02X",@owx_ROM_ID); - - #-- for some reason this does not work - replaced by another test, see below - #if( $owx_LastDiscrepancy==0 ){ - # $owx_LastDeviceFlag=1; - #} - #-- - if( $owx_LastDiscrepancy==$owx_LastFamilyDiscrepancy ){ - $owx_LastFamilyDiscrepancy=0; - } - - #-- mode was to verify presence of a device - if ($mode eq "verify") { - Log 5, "OWX: Device verified $dev"; - return 1; - #-- mode was to discover devices - } elsif( $mode eq "discover" ){ - #-- check families - my $famfnd=0; - foreach (@owx_fams){ - if( substr($dev,0,2) eq $_ ){ - #-- if present, set the fam found flag - $famfnd=1; - last; - } - } - push(@owx_fams,substr($dev,0,2)) if( !$famfnd ); - foreach (@owx_devs){ - if( $dev eq $_ ){ - #-- if present, set the last device found flag - $owx_LastDeviceFlag=1; - last; - } - } - if( $owx_LastDeviceFlag!=1 ){ - #-- push to list - push(@owx_devs,$dev); - Log 5, "OWX: New device found $dev"; - } - return 1; - - #-- mode was to discover alarm devices - } else { - for(my $i=0;$i<@owx_alarm_devs;$i++){ - if( $dev eq $owx_alarm_devs[$i] ){ - #-- if present, set the last device found flag - $owx_LastDeviceFlag=1; - last; - } - } - if( $owx_LastDeviceFlag!=1 ){ - #--push to list - push(@owx_alarm_devs,$dev); - Log 5, "OWX: New alarm device found $dev"; - } - return 1; - } -} - ######################################################################################## # # OWX_Set - Implements SetFn function @@ -886,6 +799,267 @@ sub OWX_Undef ($$) { sub OWX_Verify ($$) { my ($hash,$dev) = @_; my $i; + #-- directly connected interface + if( ($owx_interface eq "DS2480") || ($owx_interface eq "DS9097") ){ + return OWX_Verify_SER($hash,$dev) + #-- Ask the cuno + }elsif( $owx_interface eq "CUNO" ) { + return OWX_Verify_CUNO($hash,$dev) + } else { + Log 1,"OWX: Verify called with unknown interface"; + return 0; + } +} + +######################################################################################## +# +# The following subroutines in alphabetical order are only for direct serial bus interface +# +######################################################################################## +# +# OWX_Complex_SER - Send match ROM, data block and receive bytes as response +# +# Parameter hash = hash of bus master, +# owx_dev = ROM ID of device +# data = string to send +# numread = number of bytes to receive +# +# Return response, if OK +# 0 if not OK +# +######################################################################################## + +sub OWX_Complex_SER ($$$$) { + my ($hash,$owx_dev,$data,$numread) =@_; + + my $select; + my $res = ""; + my $res2 = ""; + my ($i,$j,$k); + + #-- has match ROM part + if( $owx_dev ){ + #-- ID of the device + my $owx_rnf = substr($owx_dev,3,12); + my $owx_f = substr($owx_dev,0,2); + + #-- 8 byte 1-Wire device address + my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); + #-- from search string to byte id + $owx_dev=~s/\.//g; + for(my $i=0;$i<8;$i++){ + $owx_ROM_ID[$i]=hex(substr($owx_dev,2*$i,2)); + } + $select=sprintf("\x55%c%c%c%c%c%c%c%c",@owx_ROM_ID).$data; + #-- has no match ROM part + } else { + $select=$data; + } + #-- has receive data part + if( $numread >0 ){ + #$numread += length($data); + for( my $i=0;$i<$numread;$i++){ + $select .= "\xFF"; + }; + } + + #-- for debugging + if( $owx_debug > 1){ + $res2 = "OWX_Complex_SER: Sending out "; + for($i=0;$i 1){ + $res2 = "OWX_Complex_SER: Receiving "; + for($i=0;$ibaudrate($owx_baud); $owx_serport->write_settings; - if( $owx_debug > 1){ + if( $owx_debug > 2){ my $res = "OWX: Sending out "; for($i=0;$iread(48); - if( $owx_debug > 1){ + if( $owx_debug > 2){ my $res = "OWX: Receiving "; for($i=0;$i<$count_in;$i++){ $j=int(ord(substr($string_in,$i,1))/16); @@ -1078,6 +1253,7 @@ sub OWX_Reset_2480 ($) { #-- if not ok, try for max. a second time $r1 = ord(substr($res,0,1)) & 192; if( $r1 != 192){ + #Log 1, "Trying second reset"; $res =OWX_Query_2480($hash,$cmd); } @@ -1092,8 +1268,8 @@ sub OWX_Reset_2480 ($) { $r2 = ord(substr($res,0,1)) & 3; if( $r2 == 3 ){ - Log 3, "OWX: No presence detected"; - return 0; + #Log 3, "OWX: No presence detected"; + return 1; }elsif( $r2 ==2 ){ Log 1, "OWX: Alarm presence detected"; $hash->{ALARMED} = "yes"; @@ -1295,7 +1471,7 @@ sub OWX_Query_9097 ($$) { $owx_serport->baudrate($owx_baud); $owx_serport->write_settings; - if( $owx_debug > 1){ + if( $owx_debug > 2){ my $res = "OWX: Sending out "; for($i=0;$iread(48); - if( $owx_debug > 1){ + if( $owx_debug > 2){ my $res = "OWX: Receiving "; for($i=0;$i<$count_in;$i++){ $j=int(ord(substr($string_in,$i,1))/16); @@ -1550,10 +1726,6 @@ sub OWX_TouchByte_9097 ($$) { } $byte >>= 1; } - #print "-----------------------\n"; - #printf "Sending byte /%02x/\n",$bytein; - #printf "Receiving byte /%02x/\n",$result; - #print "-----------------------\n"; return $result; } @@ -1588,4 +1760,189 @@ sub OWX_WriteBit_9097 ($$) { } } +######################################################################################## +# +# The following subroutines in alphabetical order are only for a CUNO interface +# +######################################################################################## +# +# OWX_Complex_CUNO - Send match ROM, data block and receive bytes as response +# +# Parameter hash = hash of bus master, +# owx_dev = ROM ID of device +# data = string to send +# numread = number of bytes to receive +# +# Return response, if OK +# 0 if not OK +# +######################################################################################## + +sub OWX_Complex_CUNO ($$$$) { + my ($hash,$owx_dev,$data,$numread) =@_; + + my $select; + my $res = ""; + + #-- has match ROM part + if( $owx_dev ){ + #-- ID of the device + my $owx_rnf = substr($owx_dev,3,12); + my $owx_f = substr($owx_dev,0,2); + + #-- 8 byte 1-Wire device address + my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); + #-- from search string to reverse string id + $owx_dev=~s/\.//g; + for(my $i=0;$i<8;$i++){ + $owx_ROM_ID[7-$i]=substr($owx_dev,2*$i,2); + } + $select=sprintf("Om%s%s%s%s%s%s%s%s",@owx_ROM_ID); + Log 3,"OWX: Sending match ROM to CUNO ".$select + if( $owx_debug > 1); + CUL_SimpleWrite($owx_cuno, $select); + my $ob = DevIo_SimpleRead($owx_cuno); + #-- padding first 9 bytes into result string, since we have this + # in the serial interfaces as well + $res .= "000000000"; + } + #-- has data part + if ( $data ){ + OWX_Send_CUNO($hash,$data); + $res .= $data; + } + #-- has receive part + if( $numread > 0 ){ + #$numread += length($data); + $res.=OWX_Receive_CUNO($hash,$numread); + } + return $res; +} + +######################################################################################## +# +# OWX_receive_CUNO - Read from the CUNO +# +# Parameter: hash = hash of bus master, numread = number of bytes to read +# +# Return: string received from the CUNO +# +######################################################################################## + +sub OWX_Receive_CUNO ($$) { + my ($hash,$numread) = @_; + my $res=""; + my $res2=""; + + for( + my $i=0;$i<$numread;$i++){ + CUL_SimpleWrite($owx_cuno, "OrB"); + my $ob = DevIo_SimpleRead($owx_cuno); + #-- process results + if( !(defined($ob)) ){ + return ""; + #-- four bytes received makes one byte of result + }elsif( length($ob) == 4 ){ + $res .= sprintf("%c",hex(substr($ob,0,2))); + $res2 .= "0x".substr($ob,0,2)." "; + #-- 20 bytes received = leftover from match + }elsif( length($ob) == 20 ){ + $numread++; + }else{ + Log 1,"OWX: Received unexpected number of ".length($ob)." bytes from CUNO"; + } + } + Log 3, "OWX: Receive from CUNO $numread bytes = $res2" + if( $owx_debug > 1); + + return($res); +} + +######################################################################################## +# +# OWX_Reset_CUNO - Reset the 1-Wire bus +# +# Parameter hash = hash of bus master +# +# Return 1 : OK +# 0 : not OK +# +######################################################################################## + +sub OWX_Reset_CUNO ($) { + CUL_SimpleWrite($owx_cuno, "ORb"); + my $ob = DevIo_SimpleRead($owx_cuno); + if( substr($ob,0,4) eq "OK:1" ){ + return 1; + }else{ + return 0 + } +} + +######################################################################################### +# +# OWX_Send_CUNO - Send data block +# +# Parameter hash = hash of bus master, data = string to send +# +# Return response, if OK +# 0 if not OK +# +######################################################################################## + +sub OWX_Send_CUNO ($$) { + my ($hash,$data) =@_; + my ($i,$j,$k); + my $res = ""; + my $res2 = ""; + + for( $i=0;$i 1); +} + +######################################################################################## +# +# OWX_Verify_CUNO - Verify a particular device on the 1-Wire bus +# +# Parameter hash = hash of bus master, dev = 8 Byte ROM ID of device to be tested +# +# Return 1 : device found +# 0 : device not +# +######################################################################################## + +sub OWX_Verify_CUNO ($$) { + my ($hash,$dev) = @_; + my $i; + + #-- Ask the cuno + CUL_SimpleWrite($owx_cuno, "OCf"); + #-- sleeping for some time + select(undef,undef,undef,3); + CUL_SimpleWrite($owx_cuno, "Oc"); + my $ob = DevIo_SimpleRead($owx_cuno); + if( $ob ){ + foreach my $dx (split(/\n/,$ob)){ + $dx =~ s/\d+\://; + my $ddx = substr($dx,14,2)."."; + #-- reverse data from culfw + for( my $i=1;$i<7;$i++){ + $ddx .= substr($dx,14-2*$i,2); + } + $ddx .= ".".substr($dx,0,2); + return 1 if( $dev eq $ddx); + } + return 0; + } else { + return 0; + } +} + 1; diff --git a/fhem/contrib/1-Wire/21_OWAD.pm b/fhem/contrib/1-Wire/21_OWAD.pm index 438ec91b6..5fcffbc03 100644 --- a/fhem/contrib/1-Wire/21_OWAD.pm +++ b/fhem/contrib/1-Wire/21_OWAD.pm @@ -14,7 +14,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 1.15 - June, 2012 +# Version 2.0 - June, 2012 # # Setup bus device in fhem.cfg as # @@ -40,17 +40,17 @@ # Additional attributes are defined in fhem.cfg, in some cases per channel, where =A,B,C,D # Note: attributes are read only during initialization procedure - later changes are not used. # -# attr stateAL0 "" = character string for denoting low normal condition, default is green down triangle -# attr stateAH0 "" = character string for denoting high normal condition, default is green up triangle -# attr stateAL1 "" = character string for denoting low alarm condition, default is red down triangle -# attr stateAH1 "" = character string for denoting high alarm condition, default is red up triangle -# attr Name | = name for the channel | a type description for the measured value -# attr Unit | = unit of measurement for this channel | its abbreviation -# attr Offset = offset added to the reading in this channel -# attr Factor = factor multiplied to (reading+offset) in this channel -# attr Alarm = alarm setting in this channel, either both, low, high or none (default) -# attr Low = measurement value for low alarm -# attr High = measurement for high alarm +# attr stateAL0 "" = character string for denoting low normal condition, default is green down triangle +# attr stateAH0 "" = character string for denoting high normal condition, default is green up triangle +# attr stateAL1 "" = character string for denoting low alarm condition, default is red down triangle +# attr stateAH1 "" = character string for denoting high alarm condition, default is red up triangle +# attr Name | = name for the channel | a type description for the measured value +# attr Unit | = unit of measurement for this channel | its abbreviation +# attr Offset = offset added to the reading in this channel +# attr Factor = factor multiplied to (reading+offset) in this channel +# attr Alarm = alarm setting in this channel, either both, low, high or none (default) +# attr Low = measurement value (on the scale determined by offset and factor) for low alarm +# attr High = measurement value (on the scale determined by offset and factor) for high alarm # ######################################################################################## # @@ -201,6 +201,7 @@ sub OWAD_Define ($$) { return "OWAD: Wrong 1-Wire device model $model" if( $model ne "DS2450"); $id = $a[3]; + if(int(@a)>=5) { $interval = $a[4]; } } else { return "OWAD: $a[0] ID $a[2] invalid, specify a 12 digit value"; } @@ -228,7 +229,7 @@ sub OWAD_Define ($$) { my $interface= $hash->{IODev}->{TYPE}; #-- Start timer for initialization in a few seconds - InternalTimer(time()+1, "OWAD_InitializeDevice", $hash, 0); + InternalTimer(time()+10, "OWAD_InitializeDevice", $hash, 0); #-- Start timer for updates InternalTimer(time()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 0); @@ -808,33 +809,19 @@ sub OWXAD_GetPage($$) { my ($select, $res, $res2, $res3, @data); - #-- ID of the device + #-- ID of the device, hash of the busmaster my $owx_dev = $hash->{ROM_ID}; - my $owx_rnf = substr($owx_dev,3,12); - my $owx_f = substr($owx_dev,0,2); - - #-- hash of the busmaster - my $master = $hash->{IODev}; + my $master = $hash->{IODev}; my ($i,$j,$k); - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } - #=============== get the voltage reading =============================== if( $page eq "reading"){ #-- if the conversion has not been called before if( $con==1 ){ OWX_Reset($master); #-- issue the match ROM command \x55 and the start conversion command - $select = sprintf("\x55%c%c%c%c%c%c%c%c\x3C\x0F\x00\xFF\xFF",@owx_ROM_ID); - $res= OWX_Block($master,$select); + $res= OWX_Complex($master,$owx_dev,"\x3C\x0F\x00\xFF\xFF",0); if( $res eq 0 ){ return "OWXAD: Device $owx_dev not accessible for conversion"; } @@ -842,21 +829,18 @@ sub OWXAD_GetPage($$) { select(undef,undef,undef,0.02); } #-- issue the match ROM command \x55 and the read conversion page command - # \xAA\x00\x00 reading 8 data bytes and 2 CRC bytes - $select=sprintf("\x55%c%c%c%c%c%c%c%c\xAA\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - @owx_ROM_ID); + # \xAA\x00\x00 + $select="\xAA\x00\x00"; #=============== get the alarm reading =============================== } elsif ( $page eq "alarm" ) { #-- issue the match ROM command \x55 and the read alarm page command - # \xAA\x10\x00 reading 8 data bytes and 2 CRC bytes - $select=sprintf("\x55%c%c%c%c%c%c%c%c\xAA\x10\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - @owx_ROM_ID); + # \xAA\x10\x00 + $select="\xAA\x10\x00"; #=============== get the status reading =============================== } elsif ( $page eq "status" ) { #-- issue the match ROM command \x55 and the read status memory page command - # \xAA\x08\x00 reading 8 data bytes and 2 CRC bytes - $select=sprintf("\x55%c%c%c%c%c%c%c%c\xAA\x08\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - @owx_ROM_ID); + # \xAA\x08\x00 r + $select="\xAA\x08\x00"; #=============== wrong value requested =============================== } else { return "OWXAD: Wrong memory page requested"; @@ -864,16 +848,21 @@ sub OWXAD_GetPage($$) { #-- reset the bus OWX_Reset($master); - #-- read the data - $res=OWX_Block($master,$select); + #-- reading 9 + 3 + 8 data bytes and 2 CRC bytes = 22 bytes + $res=OWX_Complex($master,$owx_dev,$select,10); + #Log 1, "OWXAD: Device $owx_dev returns data of length ".length($res); if( $res eq 0 ){ return "OWXAD: Device $owx_dev not accessible in reading $page page"; } + #-- reset the bus + OWX_Reset($master); + #-- process results @data=split(//,$res); if ( (@data != 22) ){ - return "OWXAD: Device $owx_dev returns invalid data"; + Log 1, "OWXAD: Device $owx_dev returns invalid data of length ".int(@data); + return "OWXAD: Device $owx_dev returns invalid data of length ".int(@data); } #=============== get the voltage reading =============================== @@ -970,31 +959,17 @@ sub OWXAD_SetPage($$) { my ($select, $res, $res2, $res3, @data); - #-- ID of the device + #-- ID of the device, hash of the busmaster my $owx_dev = $hash->{ROM_ID}; - my $owx_rnf = substr($owx_dev,3,12); - my $owx_f = substr($owx_dev,0,2); - - #-- hash of the busmaster - my $master = $hash->{IODev}; + my $master = $hash->{IODev}; my ($i,$j,$k); - - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } #=============== set the alarm values =============================== if ( $page eq "test" ) { #-- issue the match ROM command \x55 and the set alarm page command # \x55\x10\x00 reading 8 data bytes and 2 CRC bytes - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x55\x10\x00", - @owx_ROM_ID); + $select="\x55\x10\x00"; for( $i=0;$i<4;$i++){ $select .= sprintf "%c\xFF\xFF\xFF",int($owg_vlow[$i]*255000/$owg_range[$i]); $select .= sprintf "%c\xFF\xFF\xFF",int($owg_vhigh[$i]*255000/$owg_range[$i]); @@ -1004,8 +979,7 @@ sub OWXAD_SetPage($$) { my ($sb1,$sb2); #-- issue the match ROM command \x55 and the set status memory page command # \x55\x08\x00 reading 8 data bytes and 2 CRC bytes - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x55\x08\x00", - @owx_ROM_ID); + $select="\x55\x08\x00"; for( $i=0;$i<4;$i++){ if( $owg_mode[$i] eq "input" ){ #-- resolution (TODO: check !) @@ -1029,7 +1003,7 @@ sub OWXAD_SetPage($$) { } OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- process results if( $res eq 0 ){ diff --git a/fhem/contrib/1-Wire/21_OWCOUNT.pm b/fhem/contrib/1-Wire/21_OWCOUNT.pm index d4fc73e36..82fac6653 100644 --- a/fhem/contrib/1-Wire/21_OWCOUNT.pm +++ b/fhem/contrib/1-Wire/21_OWCOUNT.pm @@ -18,7 +18,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 1.15 - June, 2012 +# Version 2.0 - June, 2012 # # Setup bus device in fhem.cfg as # @@ -47,6 +47,12 @@ # attr Unit | = unit of measurement for this channel | its abbreviation # attr Offset = offset added to the reading in this channel # attr Factor = factor multiplied to (reading+offset) in this channel +# attr Mode = normal (default) or daily +# +# In normal counting mode each returned counting value will be factor*(reading+offset) +# In daily counting mode each returned counting value will be factor*(reading+offset)-midnight +# where midnight is stored as string in the 32 byte memory associated with the counter +# if this midnight string # ######################################################################################## # @@ -79,19 +85,23 @@ my @owg_fixed = ("A","B"); my @owg_channel; #-- channel values - always the raw values from the device my @owg_val; +my @owg_midnight; +my $owg_str; my %gets = ( "id" => "", "present" => "", "interval" => "", - #"page" => "", + "memory" => "", + "midnight" => "", "counter" => "", - "counters" => "" + "counters" => "" ); my %sets = ( - "interval" => "" - #"page" => "" + "interval" => "", + "memory" => "", + "midnight" => "" ); my %updates = ( @@ -132,6 +142,7 @@ sub OWCOUNT_Initialize ($) { $attlist .= " ".$owg_fixed[$i]."Offset"; $attlist .= " ".$owg_fixed[$i]."Factor"; $attlist .= " ".$owg_fixed[$i]."Unit"; + $attlist .= " ".$owg_fixed[$i]."Mode:normal,daily"; } $hash->{AttrList} = $attlist; } @@ -175,6 +186,7 @@ sub OWCOUNT_Define ($$) { return "OWCOUNT: Wrong 1-Wire device model $model" if( $model ne "DS2423"); $id = $a[3]; + if(int(@a)>=5) { $interval = $a[4]; } } else { return "OWCOUNT: $a[0] ID $a[2] invalid, specify a 12 digit value"; } @@ -223,11 +235,11 @@ sub OWCOUNT_InitializeDevice($) { my $name = $hash->{NAME}; - #-- Initial readings - @owg_val = (0.0,0.0,0.0,0.0); - #-- Set channel names, channel units and alarm values for( my $i=0;$i{READINGS}{"$owg_channel[$i]"}{TYPE} = $cnama[1]; @@ -270,7 +283,6 @@ sub OWCOUNT_InitializeDevice($) { }else{ return "OWCOUNT: InitializeDevice with wrong IODev type $interface"; } - #-- Initialize all the display stuff OWCOUNT_FormatValues($hash); } @@ -287,7 +299,7 @@ sub OWCOUNT_FormatValues($) { my ($hash) = @_; my $name = $hash->{NAME}; - my ($offset,$factor,$vval); + my ($offset,$factor,$midnight,$vval); my ($value1,$value2,$value3) = ("","",""); my $galarm = 0; @@ -298,22 +310,50 @@ sub OWCOUNT_FormatValues($) { my $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : $owg_fixed[$i]; my @cnama = split(/\|/,$cname); $owg_channel[$i]=$cnama[0]; - $offset = $hash->{READINGS}{"$owg_channel[$i]"}{OFFSET}; - $factor = $hash->{READINGS}{"$owg_channel[$i]"}{FACTOR}; + $offset = $hash->{READINGS}{"$owg_channel[$i]"}{OFFSET}; + $factor = $hash->{READINGS}{"$owg_channel[$i]"}{FACTOR}; + #-- 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; + } + #Log 1, "OWCOUNT: midnight = $midnight"; #-- correct values for proper offset, factor + #-- integer values + 1 decimal if( $factor == 1.0 ){ - $vval = ($owg_val[$i] + $offset)*$factor; + $vval = int(($owg_val[$i] + $offset - $midnight)*10)/10; #-- string buildup for return value and STATE - $value1 .= sprintf( "%s: %d %s", $owg_channel[$i], $vval,$hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR}); - $value2 .= sprintf( "%s: %d %s ", $owg_channel[$i], $vval,$hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR}); + $value1 .= sprintf( "%s: %5.1f %s", $owg_channel[$i], $vval,$hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR}); + $value2 .= sprintf( "%s: %5.1f %s ", $owg_channel[$i], $vval,$hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR}); + #-- floating point values } else { - $vval = int(($owg_val[$i] + $offset)*$factor*1000)/1000; + $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,$hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR}); $value2 .= sprintf( "%s: %5.2f %s ", $owg_channel[$i], $vval,$hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR}); } $value3 .= sprintf( "%s: " , $owg_channel[$i]); + #-- if daily mode and midnight has passed, store the interpolated value in the midnight store + my $oldval = $hash->{READINGS}{"$owg_channel[$i]"}{VAL}; + my $oldtim = $hash->{READINGS}{"$owg_channel[$i]"}{TIME}; + if( $oldtim ){ + my ($yearo,$montho,$dayrest) = split(/-/,$oldtim); + my $dayo = substr($dayrest,0,2); + my ($houro,$mino,$seco) = split(/:/,substr($dayrest,3)); + my ($sec,$min,$hour,$day,$month,$year,$wday,$yday,$isdst) = localtime(time); + if( $day!=$dayo ){ + my $dt = ((24-$houro)*3600 -$mino*60 - $seco)/( ($hour+24-$houro)*3600 + ($min-$mino)*60 + ($sec-$seco) ); + $midnight = $oldval*(1-$dt)+$vval*$dt; + OWXCOUNT_SetPage($hash,14+$i,sprintf("%f",$midnight)); + } + } #-- put into READINGS $hash->{READINGS}{"$owg_channel[$i]"}{VAL} = $vval; $hash->{READINGS}{"$owg_channel[$i]"}{TIME} = $tn; @@ -345,11 +385,11 @@ sub OWCOUNT_Get($@) { my $reading = $a[1]; my $name = $hash->{NAME}; my $model = $hash->{OW_MODEL}; - my ($value,$value2,$value3) = (undef,undef,undef); + my $value = undef; my $ret = ""; - my $offset; - my $factor; my $page; + my $channo = undef; + my $channel; #-- check syntax return "OWCOUNT: Get argument is missing @a" @@ -381,11 +421,51 @@ sub OWCOUNT_Get($@) { } #-- reset presence - $hash->{PRESENT} = 0; + #-- TODO: THIS IS TOO STRONG !!! + #$hash->{PRESENT} = 0; #-- get memory page/counter according to interface type my $interface= $hash->{IODev}->{TYPE}; + #-- 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: " + 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: " + if( int(@a)<2 ); + #-- find out which channel we have + if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){ + $page=14; + }elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){ + $page=15; + } else { + return "OWCOUNT: invalid midnight counter address, must be A, B or defined channel name" + } + } + #-- OWX interface + if( $interface eq "OWX" ){ + $ret = OWXCOUNT_GetPage($hash,$page); + #-- OWFS interface + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSAD_GetPage($hash,"reading"); + #-- Unknown interface + }else{ + return "OWCOUNT: Get with wrong IODev type $interface"; + } + #-- when we have a return code, we have an error + if( $ret ){ + return $ret; + }else{ + return "OWCOUNT: $name.$reading [$page] =>".$owg_str; + } + } + #-- check syntax for getting counter # TODO: WAS passiert, wenn channel name noch falsch ist ? if( $reading eq "counter" ){ @@ -410,11 +490,11 @@ sub OWCOUNT_Get($@) { }else{ return "OWCOUNT: Get with wrong IODev type $interface"; } - #-- check syntax for getting counter + #-- check syntax for getting counters }elsif( $reading eq "counters" ){ return "OWCOUNT: get needs no parameter when reading counters" if( int(@a)==1 ); - + #-- OWX interface if( $interface eq "OWX" ){ $ret = OWXCOUNT_GetPage($hash,14); $ret = OWXCOUNT_GetPage($hash,15); @@ -425,7 +505,7 @@ sub OWCOUNT_Get($@) { } } #-- process results - if( defined($ret) ){ + if( $ret ){ return "OWCOUNT: Could not get values from device $name"; } $hash->{PRESENT} = 1; @@ -511,7 +591,7 @@ sub OWCOUNT_Set($@) { #-- check syntax return "OWCOUNT: Set needs one parameter when setting this value" - if( int(@a)!=3 ); + if( int(@a)<3 ); #-- check argument if( !defined($sets{$a[1]}) ){ @@ -520,14 +600,14 @@ sub OWCOUNT_Set($@) { #-- define vars my $ret = undef; - my $channel = undef; + my $page; + my $data; my $channo = undef; - my $factor; - my $offset; + my $channel; my $name = $hash->{NAME}; my $model = $hash->{OW_MODEL}; - #-- set new timer interval + #-- set new timer interval if($key eq "interval") { # check value return "OWCOUNT: Set with short interval, must be > 1" @@ -538,7 +618,56 @@ sub OWCOUNT_Set($@) { InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWCOUNT_GetValues", $hash, 1); return undef; } - + + #-- set memory page/counter according to interface type + my $interface= $hash->{IODev}->{TYPE}; + + #-- check syntax for setting memory page 0..13 or midnight A/B + if( ($key eq "memory") || ($key eq "midnight") ){ + if( $key eq "memory" ){ + return "OWCOUNT: set needs parameter when writing memory: " + if( int(@a)<2 ); + $page=int($a[2]); + if( ($page<0) || ($page>13) ){ + return "OWXCOUNT: Wrong memory page write attempted"; + } + }else{ + return "OWCOUNT: set needs parameter when writing midnight: " + if( int(@a)<2 ); + #-- find out which channel we have + if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){ + $page=14; + }elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){ + $page=15; + } else { + return "OWCOUNT: invalid midnight counter address, must be A, B or defined channel name" + } + } + + $data=$a[3]; + for( my $i=4;$i 32 ){ + Log 1,"OWXCOUNT: memory data truncated to 32 characters"; + $data=substr($data,0,32); + }elsif( length($data) < 32 ){ + for(my $i=length($data)-1;$i<32;$i++){ + $data.=" "; + } + } + + #-- OWX interface + if( $interface eq "OWX" ){ + $ret = OWXCOUNT_SetPage($hash,$page,$data); + #-- OWFS interface + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSAD_setPage($hash,$page,$data); + #-- Unknown interface + }else{ + return "OWCOUNT: Set with wrong IODev type $interface"; + } + } } ######################################################################################## @@ -581,7 +710,7 @@ sub OWCOUNT_Undef ($) { # OWXAD_GetPage - Get one memory page + counter from device # # Parameter hash = hash of device addressed -# page = "reading", "alarm" or "status" +# page = 0..15 # ######################################################################################## @@ -590,25 +719,12 @@ sub OWXCOUNT_GetPage($$) { my ($select, $res, $res2, $res3, @data); - #-- ID of the device + #-- ID of the device, hash of the busmaster my $owx_dev = $hash->{ROM_ID}; - my $owx_rnf = substr($owx_dev,3,12); - my $owx_f = substr($owx_dev,0,2); - - #-- hash of the busmaster - my $master = $hash->{IODev}; + my $master = $hash->{IODev}; my ($i,$j,$k); - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } - #=============== wrong value requested =============================== if( ($page<0) || ($page>15) ){ return "OWXCOUNT: Wrong memory page requested"; @@ -619,68 +735,61 @@ sub OWXCOUNT_GetPage($$) { my $ta2 = ($page*32) >> 8; my $ta1 = ($page*32) & 255; #Log 1, "OWXCOUNT: getting page Nr. $ta2 $ta1"; - $select=sprintf("\x55%c%c%c%c%c%c%c%c\xA5%c%c", - @owx_ROM_ID,$ta1,$ta2); + $select=sprintf("\xA5%c%c",$ta1,$ta2); #-- reset the bus OWX_Reset($master); - #-- read the data - $res=OWX_Block($master,$select); + #-- reading 9 + 3 + 40 data bytes and 2 CRC bytes = 54 bytes + $res=OWX_Complex($master,$owx_dev,$select,42); if( $res eq 0 ){ return "OWX: Device $owx_dev not accessible in reading $page page"; } #-- process results - if( length($res) != 12 ) { - Log 1, "OWXCOUNT: warning, have received ".length($res)." bytes in first step"; - } - - #-- get 32, 36 or 28 bytes - $select=""; - for( $i=0;$i<42;$i++){ - $select .= "\xFF"; - } - #-- read the data - $res=OWX_Block($master,$select); - - #-- get remaining bytes - $select=""; - for( $i=0;$i<10;$i++){ - $select .= "\xFF"; - } - #-- read the data - $res.=OWX_Block($master,$select); - + if( length($res) < 54 ) { + #Log 1, "OWXCOUNT: warning, have received ".length($res)." bytes in first step"; + #-- read the data in a second step + $res.=OWX_Complex($master,"","",0); + #-- process results + if( length($res) < 54 ) { + #Log 1, "OWXCOUNT: warning, have received ".length($res)." bytes in second step"; + #-- read the data in a third step + $res.=OWX_Complex($master,"","",0); + } + } #-- reset the bus OWX_Reset($master); #-- process results - if( length($res) != 54){ - Log 1, "OWXCOUNT: warning, have received ".length($res)." bytes in second and third step"; - } - @data=split(//,substr($res,32)); - if ( ($data[4] | $data[5] | $data[6] | $data[7]) ne "\x00" ){ - Log 1, "OWXCOUNT: Device $owx_dev returns invalid data"; - return "OWXCOUNT: Device $owx_dev returns invalid data"; + if( length($res) < 54){ + Log 1, "OWXCOUNT: warning, have received ".length($res)." bytes in three steps"; + #return "OWXCOUNT: warning, have received ".length($res)." bytes in three steps"; } + #Log 1, "OWXCOUNT: warning, have received ".length($res)." bytes in three steps"; - #-- for now ignore memory and only use counter + #-- first 12 byte are 9 ROM ID +3 command, next 32 are memory + #-- memory part, treated as string + $owg_str=substr($res,12,32); + #-- counter part + if( ($page == 14) || ($page == 15) ){ + @data=split(//,substr($res,44)); + if ( ($data[4] | $data[5] | $data[6] | $data[7]) ne "\x00" ){ + Log 1, "OWXCOUNT: Device $owx_dev returns invalid data ".ord($data[4])." ".ord($data[5])." ".ord($data[6])." ".ord($data[7]); + return "OWXCOUNT: Device $owx_dev returns invalid data"; + } - my $value = ord($data[3])*4096 + ord($data[2])*256 +ord($data[1])*16 + ord($data[0]); - #my $ress = "OWXCOUNT: Lowest 8 data bytes are "; - # for($i=0;$i<8;$i++){ - # my $j=int(ord($data[$i])/16); - # my $k=ord($data[$i])%16; - # $ress.=sprintf "0x%1x%1x ",$j,$k; - # } - #Log 1, $ress; - #Log 1, "OWXCOUNT: calculating counter value $value"; + #-- first ignore memory and only use counter + my $value = ord($data[3])*4096 + ord($data[2])*256 +ord($data[1])*16 + ord($data[0]); - if( $page == 14) { - $owg_val[0] = $value; - }elsif( $page == 15) { - $owg_val[1] = $value; + if( $page == 14) { + $owg_val[0] = $value; + $owg_midnight[0] = $owg_str; + }elsif( $page == 15) { + $owg_val[1] = $value; + $owg_midnight[1] = $owg_str; + } } - return undef + + return undef; } ######################################################################################## @@ -692,45 +801,52 @@ sub OWXCOUNT_GetPage($$) { # ######################################################################################## -sub OWXCOUNT_SetPage($$) { +sub OWXCOUNT_SetPage($$$) { - my ($hash,$page) = @_; + my ($hash,$page,$data) = @_; - my ($select, $res, $res2, $res3, @data); + my ($select, $res, $res2, $res3); - #-- ID of the device + #-- ID of the device, hash of the busmaster my $owx_dev = $hash->{ROM_ID}; - my $owx_rnf = substr($owx_dev,3,12); - my $owx_f = substr($owx_dev,0,2); + my $master = $hash->{IODev}; - #-- hash of the busmaster - my $master = $hash->{IODev}; - - my ($i,$j,$k); - - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); + #=============== wrong value requested =============================== + if( ($page<0) || ($page>15) ){ + return "OWXCOUNT: Wrong memory page requested"; + } + #=============== set memory ========================================= + #-- issue the match ROM command \x55 and the write scratchpad command + # \x0F TA1 TA2 and the read scratchpad command reading 3 data bytes + my $ta2 = ($page*32) >> 8; + my $ta1 = ($page*32) & 255; + #Log 1, "OWXCOUNT: setting page Nr. $ta2 $ta1"; + $select=sprintf("\x0F%c%c",$ta1,$ta2).$data; + #-- reset the bus + OWX_Reset($master); + #-- reading 9 + 3 + 16 bytes = 29 bytes + $res=OWX_Complex($master,$owx_dev,$select,0); + if( $res eq 0 ){ + return "OWX: Device $owx_dev not accessible in writing scratchpad"; } - #=============== set the alarm values =============================== - #if ( $page eq "test" ) { - #-- issue the match ROM command \x55 and the set alarm page command - # \x55\x10\x00 reading 8 data bytes and 2 CRC bytes - # $select=sprintf("\x55%c%c%c%c%c%c%c%c\x55\x10\x00", - # @owx_ROM_ID); - # - #=============== wrong page write attempt =============================== - #} else { - return "OWXCOUNT: Wrong memory page write attempt"; - #} - + #-- issue the match ROM command \x55 and the read scratchpad command + # \xAA + #-- reset the bus OWX_Reset($master); - $res=OWX_Block($master,$select); + #-- reading 9 + 4 + 16 bytes = 28 bytes + # TODO: sometimes much less than 28 + $res=OWX_Complex($master,$owx_dev,"\xAA",28); + if( length($res) < 13 ){ + return "OWX: Device $owx_dev not accessible in reading scratchpad"; + } + + #-- issue the match ROM command \x55 and the copy scratchpad command + # \x5A followed by 3 byte authentication code + $select="\x5A".substr($res,10,3); + #-- reset the bus + OWX_Reset($master); + $res=OWX_Complex($master,$owx_dev,$select,6); #-- process results if( $res eq 0 ){ diff --git a/fhem/contrib/1-Wire/21_OWID.pm b/fhem/contrib/1-Wire/21_OWID.pm index 2375f4765..a75e5c89e 100644 --- a/fhem/contrib/1-Wire/21_OWID.pm +++ b/fhem/contrib/1-Wire/21_OWID.pm @@ -12,7 +12,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 1.15 - June, 2012 +# Version 2.0 - June, 2012 # # Setup bus device in fhem.cfg as # diff --git a/fhem/contrib/1-Wire/21_OWLCD.pm b/fhem/contrib/1-Wire/21_OWLCD.pm index 4e4c1ea6d..7e93eb80b 100644 --- a/fhem/contrib/1-Wire/21_OWLCD.pm +++ b/fhem/contrib/1-Wire/21_OWLCD.pm @@ -12,7 +12,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 1.15 - June, 2012 +# Version 2.0 - June, 2012 # # Setup bus device in fhem.cfg as # @@ -508,27 +508,15 @@ sub OWXLCD_Byte($$$) { my $master = $hash->{IODev}; my ($i,$j,$k); - - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } - #-- issue the match ROM command \x55 - $select = sprintf("\x55%c%c%c%c%c%c%c%c", - @owx_ROM_ID); #=============== write to LCD register =============================== if ( $cmd eq "register" ) { #-- issue the read LCD register command \x10 - $select .= sprintf("\x10%c",$byte); + $select = sprintf("\x10%c",$byte); #=============== write to LCD data =============================== }elsif ( $cmd eq "data" ) { #-- issue the read LCD data command \x12 - $select .= sprintf("\x12%c",$byte); + $select = sprintf("\x12%c",$byte); #=============== wrong value requested =============================== } else { return "OWXLCD: Wrong byte write attempt"; @@ -536,7 +524,7 @@ sub OWXLCD_Byte($$$) { #-- write to device OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- process results if( $res eq 0 ){ return "OWLCD: Device $owx_dev not accessible for writing a byte"; @@ -570,54 +558,38 @@ sub OWXLCD_Get($$) { my ($i,$j,$k); - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } - - #-- issue the match ROM command \x55 - $select = sprintf("\x55%c%c%c%c%c%c%c%c", - @owx_ROM_ID); - #-- issue the match ROM command \x55 and the read scratchpad command \xBE - $select2 = $select."\xBE"; #=============== fill scratch with gpio ports =============================== if ( $cmd eq "gpio" ) { #-- issue the read GPIO command \x22 (1 byte) - $select .= "\x22"; + $select = "\x22"; $len = 1; #=============== fill scratch with gpio counters =============================== }elsif ( $cmd eq "counter" ) { #-- issue the read counter command \x23 (8 bytes) - $select .= "\x23"; + $select = "\x23"; $len = 8; #=============== fill scratch with version =============================== }elsif ( $cmd eq "version" ) { #-- issue the read version command \x41 - $select .= "\x41"; + $select = "\x41"; $len = 16; } else { return "OWXLCD: Wrong get attempt"; } #-- write to device OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- process results if( $res eq 0 ){ return "OWLCD: Device $owx_dev not accessible for reading"; } - #-- fill according to expected length - for($i=0;$i<$len;$i++){ - $select2 .= "\xFF"; - } + #-- issue the read scratchpad command \xBE + $select2 = "\xBE"; #-- write to device OWX_Reset($master); - $res=OWX_Block($master,$select2); + $res=OWX_Complex($master,$owx_dev,$select2,$len); #-- process results if( $res eq 0 ){ @@ -669,23 +641,11 @@ sub OWXLCD_GetMemory($$) { my ($i,$j,$k); - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } - - #-- issue the match ROM command \x55 - $select = sprintf("\x55%c%c%c%c%c%c%c%c", - @owx_ROM_ID); - #-- issue the match ROM command \x55 and the copy eeprom to scratchpad command \xBE - Log 1," page read is ".$page; - $select .= sprintf("\4E%c\x10\x37",$page); + #-- issue the match ROM command \x55 and the copy eeprom to scratchpad command \x4E + #Log 1," page read is ".$page; + $select = sprintf("\4E%c\x10\x37",$page); OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- process results if( $res eq 0 ){ @@ -696,10 +656,8 @@ sub OWXLCD_GetMemory($$) { #select(undef,undef,undef,0.5); #-- issue the match ROM command \x55 and the read scratchpad command \xBE - $select = sprintf("\x55%c%c%c%c%c%c%c%c\xBE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - @owx_ROM_ID); OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,"\xBE",16); #-- process results if( $res eq 0 ){ @@ -734,15 +692,6 @@ sub OWXLCD_InitializeDevice($) { #-- hash of the busmaster my $master = $hash->{IODev}; - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } - #-- supposedly we do not need to do anything with a HD44780 if( $lcdcontroller eq "HD44780"){ return undef; @@ -803,43 +752,32 @@ sub OWXLCD_SetFunction($$$) { my $master = $hash->{IODev}; my ($i,$j,$k); - - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } - #-- issue the match ROM command \x55 - $select=sprintf("\x55%c%c%c%c%c%c%c%c",@owx_ROM_ID); #=============== set gpio ports =============================== if ( $cmd eq "gpio" ) { #-- issue the write GPIO command # \x21 followed by the data value (= integer 0 - 7) - $select .= sprintf("\x21%c",$value); + $select = sprintf("\x21%c",$value); #=============== switch LCD on =============================== }elsif ( $cmd eq "lcdon" ) { #-- issue the lcd on cmd - $select .= "\x03"; + $select = "\x03"; #=============== switch LCD off =============================== }elsif ( $cmd eq "lcdoff" ) { #-- issue the lcd off cmd - $select .= "\x05"; + $select = "\x05"; #=============== switch LCD backlight on =============================== }elsif ( $cmd eq "bklon" ) { #-- issue the backlight on cmd - $select .= "\x08"; + $select = "\x08"; #=============== switch LCD backlight off =============================== }elsif ( $cmd eq "bkloff" ) { #-- issue the backlight off cmd - $select .= "\x07"; + $select = "\x07"; #=============== switch LCD backlight off =============================== }elsif ( $cmd eq "reset" ) { #-- issue the clear LCD command - $select .= "\x49"; + $select = "\x49"; #=============== wrong write attempt =============================== } else { return "OWXLCD: Wrong function selected"; @@ -847,7 +785,7 @@ sub OWXLCD_SetFunction($$$) { #-- write to device OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- process results if( $res eq 0 ){ return "OWLCD: Device $owx_dev not accessible for writing"; @@ -880,36 +818,27 @@ sub OWXLCD_SetIcon($$$) { #-- hash of the busmaster my $master = $hash->{IODev}; - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } - #-- only for KS0073 if ( $lcdcontroller eq "KS0073"){ #-- write 16 zeros to erase all icons if( $icon == 0){ #-- 4 bit data size, RE => 1, blink Enable = \x26 - $select = sprintf("\x55%c%c%c%c%c%c%c%c\x10\x26",@owx_ROM_ID); + $select = "\x10\x26"; OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- SEGRAM addres to 0 = \x40, - $select = sprintf("\x55%c%c%c%c%c%c%c%c\x10\x40",@owx_ROM_ID); + $select = "x10\x40"; #-- write 16 zeros to scratchpad $select .= "\x4E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- issue the copy scratchpad to LCD command \x48 - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x48",@owx_ROM_ID); + $select="\x48"; OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); } else { #-- determine data value if( int($icon) != 16 ){ @@ -942,24 +871,24 @@ sub OWXLCD_SetIcon($$$) { } } #-- 4 bit data size, RE => 1, blink Enable = \x26 - $select = sprintf("\x55%c%c%c%c%c%c%c%c\x10\x26",@owx_ROM_ID); + $select = "\x10\x26"; OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- SEGRAM addres to 0 = \x40 + icon address - $select = sprintf("\x55%c%c%c%c%c%c%c%c\x10%c",@owx_ROM_ID,63+$icon); + $select = sprintf("\x10%c",63+$icon); OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- data - $select = sprintf("\x55%c%c%c%c%c%c%c%c\x12%c",@owx_ROM_ID,$data); + $select = sprintf("\x12%c",$data); OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); } #-- return to normal state - $select = sprintf("\x55%c%c%c%c%c%c%c%c\x10\x20",@owx_ROM_ID); + $select = "\x10\x20"; OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- or else } else { return "OWXLCD: Wrong LCD controller type"; @@ -1005,15 +934,6 @@ sub OWXLCD_SetLine($$$) { #-- hash of the busmaster my $master = $hash->{IODev}; - - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } #-- split if longer than 16 bytes, fill each with blanks # has already been checked to be <= $lcdchars @@ -1043,28 +963,28 @@ sub OWXLCD_SetLine($$$) { #-- issue the match ROM command \x55 and the write scratchpad command \x4E # followed by LCD page address and the text - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x4E\%c",@owx_ROM_ID,$lcdpage[$line]).$msgA; + $select=sprintf("\x4E\%c",@owx_ROM_ID,$lcdpage[$line]).$msgA; OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); #-- issue the copy scratchpad to LCD command \x48 - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x48",@owx_ROM_ID); + $select="\x48"; OWX_Reset($master); - $res3=OWX_Block($master,$select); + $res3=OWX_Complex($master,$owx_dev,$select,0); #-- if second string available: if( defined($msgB) ) { #select(undef,undef,undef,0.005); #-- issue the match ROM command \x55 and the write scratchpad command \x4E # followed by LCD page address and the text - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x4E\%c",@owx_ROM_ID,$lcdpage[$line]+16).$msgB; + $select=sprintf("\x4E\%c",@owx_ROM_ID,$lcdpage[$line]+16).$msgB; OWX_Reset($master); - $res2=OWX_Block($master,$select); + $res2=OWX_Complex($master,$owx_dev,$select,0); #-- issue the copy scratchpad to LCD command \x48 - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x48",@owx_ROM_ID); + $select="x48"; OWX_Reset($master); - $res3=OWX_Block($master,$select); + $res3=OWX_Complex($master,$owx_dev,$select,0); } #-- process results @@ -1101,15 +1021,6 @@ sub OWXLCD_SetMemory($$$) { #-- hash of the busmaster my $master = $hash->{IODev}; - - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } #-- fillup with blanks $msgA = $msg; @@ -1119,15 +1030,14 @@ sub OWXLCD_SetMemory($$$) { #-- issue the match ROM command \x55 and the write scratchpad command \x4E # followed by LCD page address and the text - Log 1," page written is ".$page; - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x4E\%c",@owx_ROM_ID,$page).$msgA; + #Log 1," page written is ".$page; + $select=sprintf("\x4E\%c",$page).$msgA; OWX_Reset($master); - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,0); - #-- issue the copy scratchpad to EEPROM command \x39 - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x39",@owx_ROM_ID); + #-- issue the copy scratchpad to EEPROM command \x39 OWX_Reset($master); - $res2=OWX_Block($master,$select); + $res2=OWX_Complex($master,$owx_dev,"\x39",0); #-- process results if( ($res eq 0) || ($res2 eq 0) ){ diff --git a/fhem/contrib/1-Wire/21_OWSWITCH.pm b/fhem/contrib/1-Wire/21_OWSWITCH.pm index c883d848c..8b374b23f 100644 --- a/fhem/contrib/1-Wire/21_OWSWITCH.pm +++ b/fhem/contrib/1-Wire/21_OWSWITCH.pm @@ -16,7 +16,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 1.15 - June, 2012 +# Version 2.0 - June, 2012 # # Setup bus device in fhem.cfg as # @@ -291,14 +291,15 @@ sub OWSWITCH_FormatValues($) { #-- result is zero or one $vval = $owg_val[$i]; + #-- string buildup for return value and STATE my @unarr=split(/\|/,$hash->{READINGS}{"$owg_channel[$i]"}{UNIT}); - $value1 .= sprintf( "%s: %s", $owg_channel[$i], $unarr[1-$vval]); - $value2 .= sprintf( "%s: %s ", $owg_channel[$i], $unarr[1-$vval]); + $value1 .= sprintf( "%s: %s", $owg_channel[$i], $unarr[$vval]); + $value2 .= sprintf( "%s: %s ", $owg_channel[$i], $unarr[$vval]); $value3 .= sprintf( "%s: " , $owg_channel[$i]); #-- put into READINGS - $hash->{READINGS}{"$owg_channel[$i]"}{VAL} = $unarr[1-$vval]; + $hash->{READINGS}{"$owg_channel[$i]"}{VAL} = $unarr[$vval]; $hash->{READINGS}{"$owg_channel[$i]"}{TIME} = $tn; #-- insert comma @@ -540,9 +541,9 @@ sub OWSWITCH_Set($@) { #-- prepare gpio value my $nval; if( lc($a[3]) eq "on" ){ - $nval = 1; - }elsif( lc($a[3]) eq "off" ){ $nval = 0; + }elsif( lc($a[3]) eq "off" ){ + $nval = 1; }else{ return "OWSWITCH: Wrong data value $a[3]"; } @@ -555,7 +556,7 @@ sub OWSWITCH_Set($@) { }elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){ $value = 2*$nval+$owg_val[0]; } - $ret .= OWXSWITCH_SetState($hash,$value); + $ret = OWXSWITCH_SetState($hash,$value); #-- OWFS interface #}elsif( $interface eq "OWFS" ){ # $ret = OWFSAD_GetPage($hash,"reading"); @@ -664,23 +665,21 @@ sub OWXSWITCH_GetState($) { #=============== get gpio values =============================== #-- issue the match ROM command \x55 and the read gpio command # \xF5 plus 2 empty bytes - $select=sprintf("\x55%c%c%c%c%c%c%c%c\xF5\xFF\xFF\xFF", - @owx_ROM_ID); #-- reset the bus OWX_Reset($master); #-- read the data - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,"\xF5",2); if( $res eq 0 ){ return "OWX: Device $owx_dev not accessible in reading"; } - - #-- reset the bus - OWX_Reset($master); #-- process results # TODO: could we put in a check if the two bytes are equal @data=split(//,substr($res,10)); + #-- reset the bus + OWX_Reset($master); + #my $ress = "OWXSWITCH_Get: three data bytes "; # for($i=0;$i<3;$i++){ # my $j=int(ord($data[$i])/16); @@ -723,25 +722,15 @@ sub OWXSWITCH_SetState($$) { my $master = $hash->{IODev}; my ($i,$j,$k); - - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } #=============== set gpio values =============================== #-- issue the match ROM command \x55 and the write gpio command # \x5A plus the value byte and its complement - $select=sprintf("\x55%c%c%c%c%c%c%c%c\x5A%c%c\xFF", - @owx_ROM_ID,252+$value,3-$value); + $select=sprintf("\x5A%c%c",252+$value,3-$value); #-- reset the bus OWX_Reset($master); #-- read the data - $res=OWX_Block($master,$select); + $res=OWX_Complex($master,$owx_dev,$select,1); if( $res eq 0 ){ return "OWX: Device $owx_dev not accessible in reading"; } @@ -752,13 +741,13 @@ sub OWXSWITCH_SetState($$) { #-- process results @data=split(//,substr($res,10)); - my $ress = "OWXSWITCH_Set: three data bytes "; - for($i=0;$i<3;$i++){ - my $j=int(ord($data[$i])/16); - my $k=ord($data[$i])%16; - $ress.=sprintf "0x%1x%1x ",$j,$k; - } - Log 1, $ress; + #my $ress = "OWXSWITCH_Set: three data bytes "; + # for($i=0;$i<3;$i++){ + # my $j=int(ord($data[$i])/16); + # my $k=ord($data[$i])%16; + # $ress.=sprintf "0x%1x%1x ",$j,$k; + # } + #Log 1, $ress; if( $data[2] ne "\xAA"){ Log 1, "OWXSWITCH: State could not be set"; @@ -767,9 +756,9 @@ sub OWXSWITCH_SetState($$) { #-- Put the new values in the system variables #-- This holds only for DS2413 - $owg_val[0] = $value && 1; - $owg_val[1] = ($value>>2) && 1; + $owg_val[0] = $value % 2; + $owg_val[1] = int($value / 2); return undef } diff --git a/fhem/contrib/1-Wire/21_OWTEMP.pm b/fhem/contrib/1-Wire/21_OWTEMP.pm index 4fd98b86c..8377668d2 100644 --- a/fhem/contrib/1-Wire/21_OWTEMP.pm +++ b/fhem/contrib/1-Wire/21_OWTEMP.pm @@ -4,10 +4,9 @@ # # FHEM module to commmunicate with 1-Wire temperature sensors DS1820, DS18S20, DS18B20, DS1822 # -# Attention: This module works as a replacement for the standard 21_OWTEMP.pm, -# therefore may communicate with the 1-Wire File System OWFS, -# but also with the newer and more direct OWX module -# +# Attention: This module may communicate with the OWX module, +# and also with the 1-Wire File System OWFS + # Prefixes for subroutines of this module: # OW = General 1-Wire routines (Martin Fischer, Peter Henning) # OWFS = 1-Wire file system (Martin Fischer) @@ -16,7 +15,7 @@ # Prof. Dr. Peter A. Henning, 2012 # Martin Fischer, 2011 # -# Version 1.15 - June, 2012 +# Version 2.0 - June, 2012 # # Setup bus device in fhem.cfg as # @@ -635,27 +634,16 @@ sub OWXTEMP_GetValues($) { my ($hash) = @_; + my ($i,$j,$k); + #-- For default, perform the conversion NOT now my $con=1; #-- ID of the device my $owx_dev = $hash->{ROM_ID}; - my $owx_rnf = substr($owx_dev,3,12); - my $owx_f = substr($owx_dev,0,2); - #-- hash of the busmaster my $master = $hash->{IODev}; - - my ($i,$j,$k); - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } #-- 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") ){ @@ -666,8 +654,7 @@ sub OWXTEMP_GetValues($) { if( $con==1 ){ OWX_Reset($master); #-- issue the match ROM command \x55 and the start conversion command - my $select=sprintf("\x55%c%c%c%c%c%c%c%c\x44",@owx_ROM_ID); - if( OWX_Block($master,$select) eq 0 ){ + if( OWX_Complex($master,$owx_dev,"\x44",0) eq 0 ){ return "OWXTEMP: Device $owx_dev not accessible"; } #-- conversion needs some 950 ms - but we may also do it in shorter time ! @@ -677,14 +664,14 @@ sub OWXTEMP_GetValues($) { #-- NOW ask the specific device OWX_Reset($master); #-- issue the match ROM command \x55 and the read scratchpad command \xBE - my $select=sprintf("\x55%c%c%c%c%c%c%c%c\xBE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - @owx_ROM_ID); - - my $res=OWX_Block($master,$select); + #-- reading 9 + 1 + 8 data bytes and 1 CRC byte = 19 bytes + my $res=OWX_Complex($master,$owx_dev,"\xBE",9); + #Log 1,"OWXTEMP: data length from reading device is ".length($res)." bytes"; #-- process results if( $res eq 0 ){ return "OWXTEMP: Device $owx_dev not accessible in 2nd step"; } + #my $res2 = "====> OWXTEMP Received "; #for(my $i=0;$i<19;$i++){ # my $j=int(ord(substr($res,$i,1))/16); @@ -754,27 +741,14 @@ sub OWXTEMP_GetValues($) { sub OWXTEMP_SetValues($@) { my ($hash, @a) = @_; + my ($i,$j,$k); + my $name = $hash->{NAME}; - #-- ID of the device my $owx_dev = $hash->{ROM_ID}; - my $owx_rnf = substr($owx_dev,3,12); - my $owx_f = substr($owx_dev,0,2); - #-- hash of the busmaster my $master = $hash->{IODev}; - my ($i,$j,$k); - - #-- 8 byte 1-Wire device address - my @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - #-- from search string to byte id - my $devs=$owx_dev; - $devs=~s/\.//g; - for($i=0;$i<8;$i++){ - $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2)); - } - #-- define vars my $key = $a[1]; my $value = $a[2]; @@ -795,23 +769,13 @@ sub OWXTEMP_SetValues($@) { # 2. \x48 appended to match ROM => command not ok. # 3. \x48 sent by WriteBytePower after match ROM => command ok, no effect on EEPROM - my $select=sprintf("\x55%c%c%c%c%c%c%c%c\x4E%c%c\x48",@owx_ROM_ID,$thp,$tlp); - my $res=OWX_Block($master,$select); + my $select=sprintf("\x4E%c%c\x48",$thp,$tlp); + my $res=OWX_Complex($master,$owx_dev,$select,0); if( $res eq 0 ){ return "OWXTEMP: Device $owx_dev not accessible"; } - #-- issue the match ROM command \x55 and the copy scratchpad command \x48 - #$select=sprintf("\x55%c%c%c%c%c%c%c%c",@owx_ROM_ID); - #$res=OWX_Block($hash,$select); - #$res=OWX_WriteBytePower($hash,"\x48"); - - #if( $res eq 0 ){ - # Log 3, "OWXTEMP_SetTemp: Device $romid not accessible in the second step"; - # return 0; - #} - DoTrigger($name, undef) if($init_done); return undef; }