diff --git a/contrib/1-Wire/00_OWX.pm b/contrib/1-Wire/00_OWX.pm index 0f89641cd..0624d9054 100644 --- a/contrib/1-Wire/00_OWX.pm +++ b/contrib/1-Wire/00_OWX.pm @@ -21,6 +21,9 @@ # # set interval => set period for temperature conversion and alarm testing # +# attr buspower real/parasitic - whether the 1-Wire bus is really powered or +# the devices take their power from the data wire (parasitic is default !) +# # Ordering of subroutines in this module # 1. Subroutines independent of bus interface type # 2. Subroutines for a specific type of the interface @@ -72,6 +75,7 @@ my %attrs = ( ); #-- some globals needed for the 1-Wire module +my $owx_serport; #-- baud rate serial interface my $owx_baud=9600; #-- Debugging @@ -96,8 +100,30 @@ my $owx_LastDeviceFlag = 0; ######################################################################################## # -# The following subroutines in alphabetical order are independent of the bus interface +# The following subroutines are independent of the bus interface # +######################################################################################## +# +# OWX_Initialize +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWX_Initialize ($) { + my ($hash) = @_; + #-- Provider + #$hash->{Clients} = ":OWCOUNT:OWHUB:OWLCD:OWMULTI:OWSWITCH:OWTEMP:"; + $hash->{Clients} = ":OWAD:OWID:OWTEMP:"; + + #-- Normal Devices + $hash->{DefFn} = "OWX_Define"; + $hash->{UndefFn} = "OWX_Undef"; + $hash->{GetFn} = "OWX_Get"; + $hash->{SetFn} = "OWX_Set"; + $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 buspower:real,parasitic"; +} + ######################################################################################## # # OWX_Alarms - Find devices on the 1-Wire bus, @@ -126,10 +152,10 @@ sub OWX_Alarms ($) { #-- walk through all the devices to get their proper fhem names foreach my $fhem_dev (sort keys %main::defs) { - - #-- all OW types start with OW - next if( substr($main::defs{$fhem_dev}{TYPE},0,2) ne "OW"); - next if($main::defs{$fhem_dev}{ROM_ID} eq "FF"); + #-- skip if busmaster + next if( $hash->{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) { #-- two pieces of the ROM ID found on the bus my $owx_rnf = substr($owx_dev,3,12); @@ -171,34 +197,6 @@ sub OWX_Block ($$) { } } -######################################################################################## -# -# OWX_Convert - Initiate temperature conversion in all devices -# -# Parameter hash = hash of bus master -# -# Return 1 : OK -# 0 : Not OK -# -######################################################################################## - -sub OWX_Convert($) { - - my($hash) = @_; - - #-- Call us in n seconds again. - InternalTimer(gettimeofday()+ $hash->{interval}, "OWX_Convert", $hash,1); - - OWX_Reset($hash); - - #-- issue the skip ROM command \xCC followed by start conversion command \x44 - if( OWX_Block($hash,"\xCC\x44") eq 0) { - Log 3, "OWX: Failure in temperature conversion\n"; - return 0; - } - return 1; -} - ######################################################################################## # # OWX_CRC - Check the CRC8 code of a device address in @owx_ROM_ID @@ -320,42 +318,45 @@ sub OWX_Define ($$) { #-- First step: open the serial device to test it #Log 3, "OWX opening device $dev"; - my $owx_serport = new Device::SerialPort ($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) || die "failed setting baudrate"; - $owx_serport->databits(8) || die "failed setting databits"; - $owx_serport->parity('none') || die "failed setting parity"; - $owx_serport->stopbits(1) || die "failed setting stopbits"; - $owx_serport->handshake('none') || die "failed setting handshake"; - $owx_serport->write_settings || die "no settings"; - sleep(1); - $owx_serport->close(); + $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(); #-- Second step: see, if a bus interface is detected if (!OWX_Detect($hash)){ $hash->{STATE} = "Failed"; + $hash->{PRESENT} = 0; $init_done = 1; return undef; } - #-- default temperature-scale: C - # C: Celsius, F: Fahrenheit, K: Kelvin, R: Rankine - $attr{$hash->{NAME}}{"temp-scale"} = "C"; - #-- In 10 seconds discover all devices on the 1-Wire bus InternalTimer(gettimeofday()+5, "OWX_Discover", $hash,0); - $hash->{interval} = 60; # call every minute + + #-- Default settings + $hash->{interval} = 60; # kick every minute #-- InternalTimer blocks if init_done is not true my $oid = $init_done; - $hash->{STATE} = "Initialized"; - $hash->{INTERFACE} = $owx_interface; + $hash->{PRESENT} = 1; + #$hash->{TYPE} = "OWX"; + #$hash->{T} = "OWX"; + $hash->{STATE} = "Initialized"; + $hash->{INTERFACE} = $owx_interface; $init_done = 1; - #-- Intiate the first temp conversion only after the proper subroutines have been defined - InternalTimer(gettimeofday() + 5, "OWX_Convert", $hash,1); + #-- Intiate first alarm detection and eventually conversion in a minute or so + InternalTimer(gettimeofday() + 60, "OWX_Kick", $hash,1); $init_done = $oid; $hash->{STATE} = "Active"; return undef; @@ -378,16 +379,22 @@ sub OWX_Define ($$) { sub OWX_Detect ($) { my ($hash) = @_; - my ($i,$j,$k,$l,$res,$ret); + my ($i,$j,$k,$l,$res,$ret,$ress); #-- timing byte for DS2480 - OWX_Query_2480($hash,"\xC1"); + 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} eq $main::defs{$fhem_dev}{NAME} ); #-- all OW types start with OW next if( substr($main::defs{$fhem_dev}{TYPE},0,2) ne "OW"); - next if( $main::defs{$fhem_dev}{ROM_ID} eq "FF"); my $id_fhem = substr($main::defs{$fhem_dev}{ROM_ID},0,15); #-- testing if present in defined devices if( $id_fhem eq $id_owx ){ @@ -476,26 +491,22 @@ sub OWX_Discover ($) { if( $match==0 ){ #-- Default name OWX_FF_XXXXXXXXXXXX, default type = OWX_FF my $name = sprintf "OWX_%s_%s",$owx_f,$owx_rnf; - + #-- Family 10 = Temperature sensor, assume DS1820 as default if( $owx_f eq "10" ){ - #-- Family 10 = Temperature sensor, assume DS1820 as default - CommandDefine(undef,"$name OWTEMP DS1820 $owx_rnf"); - $main::defs{$name}{PRESENT}=1; - #-- default room - CommandAttr (undef,"$name IODev $hash->{NAME}"); - CommandAttr (undef,"$name room OWX"); - push(@owx_names,$name); + CommandDefine(undef,"$name OWTEMP DS1820 $owx_rnf"); + #-- Family 20 = A/D converter, assume DS2450 as default } elsif( $owx_f eq "20" ){ - #-- Family 20 = A/D converter, assume DS2450 as default - CommandDefine(undef,"$name OWAD DS2450 $owx_rnf"); - $main::defs{$name}{PRESENT}=1; - #-- default room - CommandAttr (undef,"$name IODev $hash->{NAME}"); - CommandAttr (undef,"$name room OWX"); - push(@owx_names,$name); + CommandDefine(undef,"$name OWAD DS2450 $owx_rnf"); + #-- All unknown families are ID only } else { - Log 1, "OWX: Undefined device family $owx_f"; + CommandDefine(undef,"$name OWID $owx_rnf"); } + #-- yes, it is on the bus and therefore present + push(@owx_names,$name); + $main::defs{$name}{PRESENT}=1; + #-- default room + CommandAttr (undef,"$name IODev $hash->{NAME}"); + CommandAttr (undef,"$name room OWX"); #-- replace the ROM ID by the proper value $main::defs{$name}{ROM_ID}=$owx_dev; } @@ -504,10 +515,13 @@ sub OWX_Discover ($) { #-- final step: Undefine all 1-Wire devices which are not on the bus # TODO: IF WE HAVE MULTIPLE IO Devices ??? foreach my $fhem_dev (sort keys %main::defs) { + #-- skip if malformed device + #next if( !defined($main::defs{$fhem_dev}{NAME}) ); #-- all OW types start with OW next if( substr($main::defs{$fhem_dev}{TYPE},0,2) ne "OW"); - next if( $main::defs{$fhem_dev}{ROM_ID} eq "FF"); + #-- skip if the device is present. next if( $main::defs{$fhem_dev}{PRESENT} == 1); + 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).")"; @@ -569,26 +583,40 @@ sub OWX_Get($@) { } } -######################################################################################### +######################################################################################## # -# OWX_Initialize +# OWX_Kick - Initiate some processes in all devices # -# Parameter hash = hash of device addressed +# Parameter hash = hash of bus master +# +# Return 1 : OK +# 0 : Not OK # ######################################################################################## -sub OWX_Initialize ($) { - my ($hash) = @_; - #-- Provider - #$hash->{Clients} = ":OWCOUNT:OWHUB:OWLCD:OWMULTI:OWSWITCH:OWTEMP:"; - $hash->{Clients} = ":OWTEMP:OWAD:"; - - #-- Normal Devices - $hash->{DefFn} = "OWX_Define"; - $hash->{UndefFn} = "OWX_Undef"; - $hash->{GetFn} = "OWX_Get"; - $hash->{SetFn} = "OWX_Set"; - $hash->{AttrList}= "temp-scale:C,F,K,R loglevel:0,1,2,3,4,5,6"; +sub OWX_Kick($) { + + my($hash) = @_; + + my $ret; + #-- Call us in n seconds again. + InternalTimer(gettimeofday()+ $hash->{interval}, "OWX_Kick", $hash,1); + + OWX_Reset($hash); + + #-- 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"); + if( $ret eq 0 ){ + Log 3, "OWX: Failure in temperature conversion\n"; + return 0; + } + #-- sleeping for some time + select(undef,undef,undef,0.5); + } + + return 1; } ######################################################################################## @@ -723,6 +751,7 @@ sub OWX_Search ($$) { 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++){ @@ -788,7 +817,7 @@ sub OWX_Set($@) { sub OWX_Undef ($$) { my ($hash, $name) = @_; - delete($modules{OWX}{defptr}{$hash->{CODE}}); + RemoveInternalTimer($hash); return undef; } @@ -929,56 +958,54 @@ sub OWX_Query_2480 ($$) { my ($hash,$cmd) = @_; my ($i,$j,$k); my $dev = $hash->{DeviceName}; - - if( $dev ne "emulator") { - #Log 3, "OWX opening device $dev"; - my $owx_serport = new Device::SerialPort ($dev); - return "OWX: Can't open $dev: $!" if(!$owx_serport); - Log 4, "OWX: Opened device $dev"; - - $owx_serport->reset_error(); - $owx_serport->baudrate($owx_baud) || die "failed setting baudrate"; - $owx_serport->databits(8) || die "failed setting databits"; - $owx_serport->parity('none') || die "failed setting parity"; - $owx_serport->stopbits(1) || die "failed setting stopbits"; - $owx_serport->handshake('none') || die "failed setting handshake"; - $owx_serport->write_settings || die "no settings"; - if( $owx_debug > 1){ - my $res = "OWX: Sending out "; - for($i=0;$iwrite($cmd); - - Log 1, "OWX: Write incomplete $count_out ne ".(length($cmd))."" if ( $count_out != length($cmd) ); - #-- sleeping for some time - select(undef,undef,undef,0.04); - - #-- read the data - my ($count_in, $string_in) = $owx_serport->read(48); + #Log 3, "OWX opening device $dev"; + #my $owx_serport = new Device::SerialPort ($dev); + #return "OWX: Can't open $dev: $!" if(!$owx_serport); + #Log 4, "OWX: Opened device $dev"; - if( $owx_debug > 1){ - my $res = "OWX: Receiving "; - for($i=0;$i<$count_in;$i++){ - $j=int(ord(substr($string_in,$i,1))/16); - $k=ord(substr($string_in,$i,1))%16; - $res.=sprintf "0x%1x%1x ",$j,$k; - } - Log 3, $res; + #$owx_serport->reset_error(); + $owx_serport->baudrate($owx_baud); + #$owx_serport->databits(8) || die "failed setting databits"; + #$owx_serport->parity('none') || die "failed setting parity"; + #$owx_serport->stopbits(1) || die "failed setting stopbits"; + #$owx_serport->handshake('none') || die "failed setting handshake"; + $owx_serport->write_settings; + + if( $owx_debug > 1){ + my $res = "OWX: Sending out "; + for($i=0;$iclose(); - return($string_in); + Log 3, $res; } + + my $count_out = $owx_serport->write($cmd); + + Log 1, "OWX: Write incomplete $count_out ne ".(length($cmd))."" if ( $count_out != length($cmd) ); + #-- sleeping for some time + select(undef,undef,undef,0.04); + + #-- read the data + my ($count_in, $string_in) = $owx_serport->read(48); + + if( $owx_debug > 1){ + my $res = "OWX: Receiving "; + for($i=0;$i<$count_in;$i++){ + $j=int(ord(substr($string_in,$i,1))/16); + $k=ord(substr($string_in,$i,1))%16; + $res.=sprintf "0x%1x%1x ",$j,$k; + } + Log 3, $res; + } + + #-- sleeping for some time + select(undef,undef,undef,0.04); + + #$owx_serport->close(); + return($string_in); } ######################################################################################## @@ -997,22 +1024,30 @@ sub OWX_Reset_2480 ($) { my ($hash)=@_; my $cmd=""; + my ($res,$r1,$r2); #-- if necessary, prepend \xE3 character for command mode if( $owx_mode ne "command" ) { $cmd = "\xE3"; } #-- Reset command \xC5 - $cmd = $cmd."\xC1"; + $cmd = $cmd."\xC5"; #-- write 1-Wire bus - my $res =OWX_Query_2480($hash,$cmd); + $res =OWX_Query_2480($hash,$cmd); + + #-- if not ok, try for max. a second time + $r1 = ord(substr($res,0,1)) & 192; + if( $r1 != 192){ + $res =OWX_Query_2480($hash,$cmd); + } + #-- process result - my $r1 = ord(substr($res,0,1)) & 192; + $r1 = ord(substr($res,0,1)) & 192; if( $r1 != 192){ Log 3, "OWX: Reset failure"; return 0; } - my $r2 = ord(substr($res,0,1)) & 3; + $r2 = ord(substr($res,0,1)) & 3; if( $r2 == 3 ){ Log 3, "OWX: No presence detected"; @@ -1214,55 +1249,54 @@ sub OWX_Query_9097 ($$) { my ($i,$j,$k); my $dev = $hash->{DeviceName}; - if( $dev ne "emulator") { - #Log 3, "OWX opening device $dev"; - my $owx_serport = new Device::SerialPort ($dev); - return "OWX: Can't open $dev: $!" if(!$owx_serport); - Log 4, "OWX: Opened device $dev"; + + #Log 3, "OWX opening device $dev"; + #my $owx_serport = new Device::SerialPort ($dev); + #return "OWX: Can't open $dev: $!" if(!$owx_serport); + #Log 4, "OWX: Opened device $dev"; - #$owx_serport->reset_error(); - $owx_serport->baudrate($owx_baud) || die "failed setting baudrate"; - $owx_serport->databits(8) || die "failed setting databits"; - $owx_serport->parity('none') || die "failed setting parity"; - $owx_serport->stopbits(1) || die "failed setting stopbits"; - $owx_serport->handshake('none') || die "failed setting handshake"; - $owx_serport->write_settings || die "no settings"; + #$owx_serport->reset_error(); + $owx_serport->baudrate($owx_baud); + #$owx_serport->databits(8) || die "failed setting databits"; + #$owx_serport->parity('none') || die "failed setting parity"; + #$owx_serport->stopbits(1) || die "failed setting stopbits"; + #$owx_serport->handshake('none') || die "failed setting handshake"; + $owx_serport->write_settings; - if( $owx_debug > 1){ - my $res = "OWX: Sending out "; - for($i=0;$i 1){ + my $res = "OWX: Sending out "; + for($i=0;$iwrite($cmd); + my $count_out = $owx_serport->write($cmd); - Log 1, "OWX: Write incomplete $count_out ne ".(length($cmd))."" if ( $count_out != length($cmd) ); - #-- sleeping for some time - select(undef,undef,undef,0.01); + Log 1, "OWX: Write incomplete $count_out ne ".(length($cmd))."" if ( $count_out != length($cmd) ); + #-- sleeping for some time + select(undef,undef,undef,0.01); - #-- read the data - my ($count_in, $string_in) = $owx_serport->read(48); + #-- read the data + my ($count_in, $string_in) = $owx_serport->read(48); - if( $owx_debug > 1){ - my $res = "OWX: Receiving "; - for($i=0;$i<$count_in;$i++){ - $j=int(ord(substr($string_in,$i,1))/16); - $k=ord(substr($string_in,$i,1))%16; - $res.=sprintf "0x%1x%1x ",$j,$k; - } - Log 3, $res; + if( $owx_debug > 1){ + my $res = "OWX: Receiving "; + for($i=0;$i<$count_in;$i++){ + $j=int(ord(substr($string_in,$i,1))/16); + $k=ord(substr($string_in,$i,1))%16; + $res.=sprintf "0x%1x%1x ",$j,$k; } - - #-- sleeping for some time - select(undef,undef,undef,0.01); - - $owx_serport->close(); - return($string_in); + Log 3, $res; } + + #-- sleeping for some time + select(undef,undef,undef,0.01); + + #$owx_serport->close(); + return($string_in); } ######################################################################################## diff --git a/contrib/1-Wire/21_OWAD.pm b/contrib/1-Wire/21_OWAD.pm index c0341a5bf..537eca4b9 100644 --- a/contrib/1-Wire/21_OWAD.pm +++ b/contrib/1-Wire/21_OWAD.pm @@ -4,8 +4,8 @@ # # FHEM module to commmunicate with 1-Wire A/D converters # -# Attention: This module may communicate with the OWX module -# currently not with the 1-Wire File System OWFS, +# Attention: This module may communicate with the OWX module, +# but currently not with the 1-Wire File System OWFS # # Prefixes for subroutines of this module: # OW = General 1-Wire routines Peter Henning) @@ -14,7 +14,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 1.02 - February 29, 2012 +# Version 1.03 - March, 2012 # # Setup bus device in fhem.cfg as # define OWAD [] [interval] @@ -29,7 +29,10 @@ # # Additional attributes are defined in fhem.cfg as # -# attr offset = a offset added to the v1erature reading +# attr Name string = a name for the channel, where =A,B,C,D +# attr Offset = an offset added to the reading in this channel +# attr Factor = a factor multiplied to (reading+offset) in this channel +# attr Unit = a scale description for this channel # ######################################################################################## # @@ -57,15 +60,10 @@ use strict; use warnings; sub Log($$); -#-- declare variables -my $ownet; -my %gets = (); -my %sets = (); -my %updates = (); - ##-- value globals my @owg_status; -#-- channel name - fixed for now +#-- channel name - fixed is the first array, variable the second +my @owg_fixed = ("A","B","C","D"); my @owg_channel = ("A","B","C","D"); #-- channel values my @owg_val; @@ -75,14 +73,15 @@ my @owg_mode = ("input","input","input","input"); my @owg_resoln = (16,16,16,16); #-- bare range in mV - fixed for now my @owg_range = (5100,5100,5100,5100); -#-- alarm status 0 = disabled, 1 = enabled, but not present, 2 = alarmed -my @owg_alarmlow = (0,0,1,1); -my @owg_alarmhigh = (0,1,0,1); +#-- alarm status 0 = disabled, 1 = enabled, but not alarmed, 2 = alarmed +my @owg_alarmlow = (0,0,0,0); +my @owg_alarmhigh = (0,0,0,0); #-- alarm values my @owg_low = (0.0,0.0,0.0,0.0); my @owg_high = (5.0,5.0,5.0,5.0); -%gets = ( +my %gets = ( + "id" => "", "present" => "", "interval" => "", "reading" => "", @@ -90,19 +89,11 @@ my @owg_high = (5.0,5.0,5.0,5.0); "status" => "", ); -%sets = ( - "interval" => "", - "Alow" => "", - "Ahigh" => "", - "Blow" => "", - "Bhigh" => "", - "Clow" => "", - "Chigh" => "", - "Dlow" => "", - "Dhigh" => "" +my %sets = ( + "interval" => "" ); -%updates = ( +my %updates = ( "present" => "", "reading" => "", "alarm" => "", @@ -131,12 +122,19 @@ sub OWAD_Initialize ($) { $hash->{UndefFn} = "OWAD_Undef"; $hash->{GetFn} = "OWAD_Get"; $hash->{SetFn} = "OWAD_Set"; - #Xoffset = a v(oltage) offset added to the reading - #Xfactor = a v(oltage) factor multiplied with (reading+offset) - #Xscale = a unit of measure - $hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 model:DS2450 loglevel:0,1,2,3,4,5 ". - "Aoffset Afactor Ascale Boffset Bfactor Bscale ". - "Coffset Cfactor Cscale Doffset Dfactor Dscale "; + #name = channel name + #offset = a v(oltage) offset added to the reading + #factor = a v(oltage) factor multiplied with (reading+offset) + #unit = a unit of measure + my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2450 loglevel:0,1,2,3,4,5 ". + "channels "; + for( my $i=0;$i<4;$i++ ){ + $attlist .= " ".$owg_fixed[$i]."name"; + $attlist .= " ".$owg_fixed[$i]."offset"; + $attlist .= " ".$owg_fixed[$i]."factor"; + $attlist .= " ".$owg_fixed[$i]."unit"; + } + $hash->{AttrList} = $attlist; } ######################################################################################### @@ -150,15 +148,15 @@ sub OWAD_Initialize ($) { sub OWAD_Define ($$) { my ($hash, $def) = @_; - # define OWAD [] [interval] [alarminterval] + # define OWAD [] [interval] # e.g.: define flow OWAD 525715020000 300 my @a = split("[ \t][ \t]*", $def); - my ($name,$model,$id,$interval,$alarminterval,$scale,$ret); + my ($name,$model,$id,$interval,$scale,$ret); #-- default $name = $a[0]; - $interval = 30; + $interval = 300; $scale = ""; $ret = ""; @@ -195,34 +193,16 @@ sub OWAD_Define ($$) { #-- Couple to I/O device AssignIoPort($hash); - return "OWAD: No 1-Wire I/O device found for $name." + Log 3, "OWAD: Warning, no 1-Wire I/O device found for $name." if(!defined($hash->{IODev}->{NAME})); + $modules{OWAD}{defptr}{$id} = $hash; - #-- Define several things - # Take channel names from $owg_channel - my $value2 = ""; - for (my $i=0;$i<4;$i++){ - #$owx_temp += $attr{$name}{offset} if ($attr{$name}{offset} ); - #-- Initial readings values - $hash->{READINGS}{$owg_channel[$i]}{VAL} = 0.0; - $hash->{READINGS}{$owg_channel[$i]}{TIME} = ""; - $hash->{READINGS}{$owg_channel[$i]."low"}{VAL} = 0.0; - $hash->{READINGS}{$owg_channel[$i]."low"}{TIME} = ""; - $hash->{READINGS}{$owg_channel[$i]."high"}{VAL} = 0.0; - $hash->{READINGS}{$owg_channel[$i]."high"}{TIME} = ""; - $value2 .= sprintf "%s: L- H- ",$owg_channel[$i]; - } - $hash->{READINGS}{alarms}{VAL} = $value2; - $hash->{READINGS}{alarms}{TIME} = ""; - $hash->{STATE} = "Defined"; - Log 3, "OWAD: Device $name defined."; - - - my $interface= $hash->{IODev}->{TYPE}; + Log 3, "OWAD: Device $name defined."; #-- Initialization reading according to interface type + my $interface= $hash->{IODev}->{TYPE}; #-- OWX interface if( $interface eq "OWX" ){ OWXAD_SetPage($hash,"alarm"); @@ -235,6 +215,9 @@ sub OWAD_Define ($$) { return "OWAD: Define with wrong IODev type $interface"; } + #-- Start timer for initialization in a few seconds + InternalTimer(time()+1, "OWAD_InitializeDevice", $hash, 0); + #-- Start timer for updates InternalTimer(time()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 0); @@ -244,6 +227,45 @@ sub OWAD_Define ($$) { return undef; } +######################################################################################## +# +# OWAD_InitializeDevice - delayed setting of initial readings and channel names +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWAD_InitializeDevice($) { + my ($hash) = @_; + + my $name = $hash->{NAME}; + #-- name attribute present ? + for( my $i=0;$i<4;$i++) { + if( defined($attr{$name}{$owg_fixed[$i]."name"}) ){ + $owg_channel[$i]= $attr{$name}{$owg_fixed[$i]."name"}; + } + } + + my $value2 = ""; + for (my $i=0;$i<4;$i++){ + #-- Initial readings values + $hash->{READINGS}{$owg_channel[$i]}{VAL} = 0.0; + $hash->{READINGS}{$owg_channel[$i]}{TIME} = ""; + #$hash->{READINGS}{$owg_channel[$i]}{UNIT} = "volt"; + #$hash->{READINGS}{$owg_channel[$i]}{TYPE} = "voltage"; + $hash->{READINGS}{$owg_channel[$i]."Low"}{VAL} = 0.0; + $hash->{READINGS}{$owg_channel[$i]."Low"}{TIME} = ""; + $hash->{READINGS}{$owg_channel[$i]."High"}{VAL} = 0.0; + $hash->{READINGS}{$owg_channel[$i]."High"}{TIME} = ""; + + $value2 .= sprintf "%s: L- H- ",$owg_channel[$i]; + } + $hash->{READINGS}{alarms}{VAL} = $value2; + $hash->{READINGS}{alarms}{TIME} = ""; + + +} + ######################################################################################## # # OWAD_Get - Implements GetFn function @@ -260,14 +282,31 @@ sub OWAD_Get($@) { my $model = $hash->{OW_MODEL}; my $value = undef; my $ret = ""; + my $offset; + my $factor; - #-- check argument - return "OWAD: Get with unknown argument $a[1], choose one of ".join(",", sort keys %gets) - if(!defined($gets{$a[1]})); #-- check syntax return "OWAD: Get argument is missing @a" if(int(@a) != 2); + + #-- check argument + return "OWAD: Get with unknown argument $a[1], choose one of ".join(",", sort keys %gets) + if(!defined($gets{$a[1]})); + #-- get id + if($a[1] eq "id") { + $value = $hash->{ROM_ID}; + return "$a[0] $reading => $value"; + } + + #-- get present + if($a[1] eq "present") { + #-- hash of the busmaster + my $master = $hash->{IODev}; + $value = OWX_Verify($master,$hash->{ROM_ID}); + $hash->{PRESENT} = $value; + return "$a[0] $reading => $value"; + } #-- get interval if($a[1] eq "interval") { @@ -275,15 +314,11 @@ sub OWAD_Get($@) { return "$a[0] $reading => $value"; } - #-- get present - if($a[1] eq "present") { - $value = $hash->{PRESENT}; - return "$a[0] $reading => $value"; - } - - my $interface= $hash->{IODev}->{TYPE}; - + #-- reset presence + $hash->{PRESENT} = 0; + #-- get reading according to interface type + my $interface= $hash->{IODev}->{TYPE}; if($a[1] eq "reading") { #-- OWX interface if( $interface eq "OWX" ){ @@ -297,19 +332,20 @@ sub OWAD_Get($@) { } #-- process results + if( defined($ret) ){ + return "OWAD: Could not get values from device $name"; + } + $hash->{PRESENT} = 1; my $tn = TimeNow(); $value = ""; + for (my $i=0;$i<4;$i++){ #-- correct values for proper offset, factor - $owg_val[$i] += $attr{$name}{$owg_channel[$i]."offset"} if ($attr{$name}{$owg_channel[$i]."offset"} ); - $owg_val[$i] *= $attr{$name}{$owg_channel[$i]."factor"} if ($attr{$name}{$owg_channel[$i]."factor"} ); - #-- Test for alarm condition - #if( ($owg_v1 <= $owg_v2) | ($owg_v1 >= $owg_v3) ){ - # $hash->{STATE} = "Alarmed"; - #} else { - # $hash->{STATE} = "Normal"; - #} - + $offset = $attr{$name}{$owg_fixed[$i]."offset"}; + $factor = $attr{$name}{$owg_fixed[$i]."factor"}; + $owg_val[$i] += $offset if ($offset ); + $owg_val[$i] *= $factor if ($factor ); + #-- put into READINGS $hash->{READINGS}{$owg_channel[$i]}{VAL} = $owg_val[$i]; $hash->{READINGS}{$owg_channel[$i]}{TIME} = $tn; @@ -332,27 +368,27 @@ sub OWAD_Get($@) { } #-- process results + if( defined($ret) ){ + return "OWAD: Could not get values from device $name"; + } + $hash->{PRESENT} = 1; my $tn = TimeNow(); $value = ""; for (my $i=0;$i<4;$i++){ #-- correct alarm values for proper offset, factor - $owg_low[$i] += $attr{$name}{$owg_channel[$i]."offset"} if ($attr{$name}{$owg_channel[$i]."offset"} ); - $owg_low[$i] *= $attr{$name}{$owg_channel[$i]."factor"} if ($attr{$name}{$owg_channel[$i]."factor"} ); - $owg_high[$i] += $attr{$name}{$owg_channel[$i]."offset"} if ($attr{$name}{$owg_channel[$i]."offset"} ); - $owg_high[$i] *= $attr{$name}{$owg_channel[$i]."factor"} if ($attr{$name}{$owg_channel[$i]."factor"} ); - #-- Test for alarm condition - #if( ($owg_v1 <= $owg_v2) | ($owg_v1 >= $owg_v3) ){ - # $hash->{STATE} = "Alarmed"; - #} else { - # $hash->{STATE} = "Normal"; - #} + $offset = $attr{$name}{$owg_fixed[$i]."offset"}; + $factor = $attr{$name}{$owg_fixed[$i]."factor"}; + $owg_low[$i] += $offset if ($offset ); + $owg_low[$i] *= $factor if ($factor ); + $owg_high[$i] += $offset if ($offset ); + $owg_high[$i] *= $factor if ($factor ); #-- put into READINGS - $hash->{READINGS}{$owg_channel[$i]."low"}{VAL} = $owg_low[$i]; - $hash->{READINGS}{$owg_channel[$i]."low"}{TIME} = $tn; - $hash->{READINGS}{$owg_channel[$i]."high"}{VAL} = $owg_high[$i]; - $hash->{READINGS}{$owg_channel[$i]."high"}{TIME} = $tn; + $hash->{READINGS}{$owg_channel[$i]."Low"}{VAL} = $owg_low[$i]; + $hash->{READINGS}{$owg_channel[$i]."Low"}{TIME} = $tn; + $hash->{READINGS}{$owg_channel[$i]."High"}{VAL} = $owg_high[$i]; + $hash->{READINGS}{$owg_channel[$i]."High"}{TIME} = $tn; $value .= sprintf "%s:[%4.2f,%4.2f] ",$owg_channel[$i],$owg_low[$i],$owg_high[$i]; } @@ -373,8 +409,13 @@ sub OWAD_Get($@) { } #-- process results + if( defined($ret) ){ + return "OWAD: Could not get values from device $name"; + } + $hash->{PRESENT} = 1; my $tn = TimeNow(); $value = ""; + my $value2 = ""; for (my $i=0;$i<4;$i++){ $value .= sprintf "%s: %s \n",$owg_channel[$i],$owg_status[$i]; @@ -416,6 +457,8 @@ sub OWAD_GetValues($@) { my $model = $hash->{OW_MODEL}; my $value = ""; my $ret = ""; + my $offset; + my $factor; #-- define warnings my $warn = "none"; @@ -425,12 +468,15 @@ sub OWAD_GetValues($@) { RemoveInternalTimer($hash); InternalTimer(time()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 1); + #-- reset presence + $hash->{PRESENT} = 0; + #-- Get readings, alarms and stati according to interface type my $interface= $hash->{IODev}->{TYPE}; if( $interface eq "OWX" ){ - OWXAD_GetPage($hash,"reading"); - OWXAD_GetPage($hash,"alarm"); - OWXAD_GetPage($hash,"status"); + $ret = OWXAD_GetPage($hash,"reading"); + $ret = OWXAD_GetPage($hash,"alarm"); + $ret = OWXAD_GetPage($hash,"status"); #}elsif( $interface eq "OWFS" ){ # $ret = OWFSAD_GetValues($hash); }else{ @@ -438,33 +484,33 @@ sub OWAD_GetValues($@) { } #-- process results + if( defined($ret) ){ + return "OWAD: Could not get values from device $name"; + } + $hash->{PRESENT} = 1; my $tn = TimeNow(); $value = ""; my $value2 =""; for (my $i=0;$i<4;$i++){ #-- correct values for proper offset, factor - $owg_val[$i] += $attr{$name}{$owg_channel[$i]."offset"} if ($attr{$name}{$owg_channel[$i]."offset"} ); - $owg_val[$i] *= $attr{$name}{$owg_channel[$i]."factor"} if ($attr{$name}{$owg_channel[$i]."factor"} ); + $offset = $attr{$name}{$owg_fixed[$i]."offset"}; + $factor = $attr{$name}{$owg_fixed[$i]."factor"}; + $owg_val[$i] += $offset if ($offset ); + $owg_val[$i] *= $factor if ($factor ); #-- correct alarm values for proper offset, factor - $owg_low[$i] += $attr{$name}{$owg_channel[$i]."offset"} if ($attr{$name}{$owg_channel[$i]."offset"} ); - $owg_low[$i] *= $attr{$name}{$owg_channel[$i]."factor"} if ($attr{$name}{$owg_channel[$i]."factor"} ); - $owg_high[$i] += $attr{$name}{$owg_channel[$i]."offset"} if ($attr{$name}{$owg_channel[$i]."offset"} ); - $owg_high[$i] *= $attr{$name}{$owg_channel[$i]."factor"} if ($attr{$name}{$owg_channel[$i]."factor"} ); - #-- Test for alarm condition - #if( ($owg_v1 <= $owg_v2) | ($owg_v1 >= $owg_v3) ){ - # $hash->{STATE} = "Alarmed"; - #} else { - # $hash->{STATE} = "Normal"; - #} + $owg_low[$i] += $offset if ($offset ); + $owg_low[$i] *= $factor if ($factor ); + $owg_high[$i] += $offset if ($offset ); + $owg_high[$i] *= $factor if ($factor ); #-- put into READINGS $hash->{READINGS}{$owg_channel[$i]}{VAL} = $owg_val[$i]; $hash->{READINGS}{$owg_channel[$i]}{TIME} = $tn; - $hash->{READINGS}{$owg_channel[$i]."low"}{VAL} = $owg_low[$i]; - $hash->{READINGS}{$owg_channel[$i]."low"}{TIME} = $tn; - $hash->{READINGS}{$owg_channel[$i]."high"}{VAL} = $owg_high[$i]; - $hash->{READINGS}{$owg_channel[$i]."high"}{TIME} = $tn; + $hash->{READINGS}{$owg_channel[$i]."Low"}{VAL} = $owg_low[$i]; + $hash->{READINGS}{$owg_channel[$i]."Low"}{TIME} = $tn; + $hash->{READINGS}{$owg_channel[$i]."High"}{VAL} = $owg_high[$i]; + $hash->{READINGS}{$owg_channel[$i]."High"}{TIME} = $tn; $value .= sprintf "%s: %5.3f ",$owg_channel[$i],$owg_val[$i]; $value2 .= sprintf "%s: L",$owg_channel[$i]; @@ -500,7 +546,7 @@ sub OWAD_GetValues($@) { # OWAD_Set - Set one value for device # # Parameter hash = hash of device addressed -# a = argument string +# a = argument array # ######################################################################################## @@ -509,26 +555,41 @@ sub OWAD_Set($@) { my $key = $a[1]; my $value = $a[2]; + + #-- for the selector: which values are possible + if (@a == 2){ + my $newkeys = join(" ", sort keys %sets); + for( my $i=0;$i<4;$i++ ){ + $newkeys .= " ".$owg_channel[$i]."Alarm"; + $newkeys .= " ".$owg_channel[$i]."Low"; + $newkeys .= " ".$owg_channel[$i]."High"; + } + return $newkeys ; + } + + #-- check syntax + return "OWAD: Set needs one parameter when setting this value" + if( int(@a)!=3 ); + + #-- check argument + if( !defined($sets{$a[1]}) && !($key =~ m/.*(Alarm|Low|High)/) ){ + return "OWAD: Set with unknown argument $a[1]"; + } + + #-- define vars my $ret = undef; my $channel = undef; my $channo = undef; + my $factor; + my $offset; my $condx; my $name = $hash->{NAME}; my $model = $hash->{OW_MODEL}; - - #-- for the selector: which values are possible - return join(" ", sort keys %sets) if(@a == 2); - #-- check syntax - return "OWAD: Set needs one parameter" - if(int(@a) != 3); - #-- check argument - return "OWAD: Set with unknown argument $a[1], choose one of ".join(",", sort keys %sets) - if(!defined($sets{$a[1]})); #-- set new timer interval if($key eq "interval") { # check value - return "OWAD: Set with too short time value, interval must be > 10" + return "OWAD: Set with short interval, must be > 10" if(int($value) < 10); # update timer $hash->{INTERVAL} = $value; @@ -536,62 +597,41 @@ sub OWAD_Set($@) { InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 1); return undef; } - - #-- set other values depending on interface type - my $interface= $hash->{IODev}->{TYPE}; - Log 4, "OWTEMP: Set $hash->{NAME} $key $value"; - + #-- find out which channel we have - $channel=$key; - if( $channel =~ s/(.*)(low|high)/$channel=$1/se ) { + my $tc =$key; + if( $tc =~ s/(.*)(Alarm|Low|High)/$channel=$1/se ) { for (my $i=0;$i<4;$i++){ - if( $channel eq $owg_channel[$i] ){ - $channo = $i; + if( $tc eq $owg_channel[$i] ){ + $channo = $i; + $channel = $tc; last; - } - } + } + } } + return "OWAD: Cannot determine channel from parameter $a[1]" + if( !(defined($channo))); + + #-- set these values depending on interface type + my $interface= $hash->{IODev}->{TYPE}; #-- check alarm values - if( $key =~ m/(.*)(low|high)/ ) { - #-- find upper and lower boundaries for given offset/factor - my $mmin = 0.0; - $mmin /= $attr{$name}{$owg_channel[$channo]."factor"} if ($attr{$name}{$owg_channel[$channo]."factor"} ); - $mmin -= $attr{$name}{$owg_channel[$channo]."offset"} if ($attr{$name}{$owg_channel[$channo]."offset"} ); - - my $mmax = $owg_range[$channo]/1000; - $mmax /= $attr{$name}{$owg_channel[$channo]."factor"} if ($attr{$name}{$owg_channel[$channo]."factor"} ); - $mmax -= $attr{$name}{$owg_channel[$channo]."offset"} if ($attr{$name}{$owg_channel[$channo]."offset"} ); - - return sprintf("OWAD: Set with wrong value $value for $key, range is [%3.1f,%3.1f]",$mmin,$mmax) - if($value < $mmin || $value > $mmax); - - #-- set alarm value in the device - if( $key =~ m/(.*)low/ ){ - $owg_low[$channo] = $value; - $owg_low[$channo] /= $attr{$name}{$owg_channel[$channo]."factor"} if ($attr{$name}{$owg_channel[$channo]."factor"} ); - $owg_low[$channo] -= $attr{$name}{$owg_channel[$channo]."offset"} if ($attr{$name}{$owg_channel[$channo]."offset"} ); - #-- round to those numbers understood by the device and backward into the value; - $owg_low[$channo] = int($owg_low[$channo]*255000/$owg_range[$channo])*$owg_range[$channo]/255000; - $value = $owg_low[$channo]; - $value += $attr{$name}{$owg_channel[$channo]."offset"} if ($attr{$name}{$owg_channel[$channo]."offset"} ); - $value *= $attr{$name}{$owg_channel[$channo]."factor"} if ($attr{$name}{$owg_channel[$channo]."factor"} ); - } else { - $owg_high[$channo] = $value; - $owg_high[$channo] /= $attr{$name}{$owg_channel[$channo]."factor"} if ($attr{$name}{$owg_channel[$channo]."factor"} ); - $owg_high[$channo] -= $attr{$name}{$owg_channel[$channo]."offset"} if ($attr{$name}{$owg_channel[$channo]."offset"} ); - #-- round to those numbers understood by the device and backward into the value; - $owg_high[$channo] = int($owg_high[$channo]*255000/$owg_range[$channo])*$owg_range[$channo]/255000; - $value = $owg_high[$channo]; - $value += $attr{$name}{$owg_channel[$channo]."offset"} if ($attr{$name}{$owg_channel[$channo]."offset"} ); - $value *= $attr{$name}{$owg_channel[$channo]."factor"} if ($attr{$name}{$owg_channel[$channo]."factor"} ); + if( $key =~ m/(.*)(Alarm)/ ) { + return "OWAD: Set with wrong value $value for $key, allowed is none/low/high/both" + if($value ne "none" && $value ne "low" && $value ne "high" && $value ne "both"); + if( $value eq "low" || $value eq "both" ){ + $owg_alarmlow[$channo]=1; + } else{ + $owg_alarmlow[$channo]=0; } - + if( $value eq "high" || $value eq "both" ){ + $owg_alarmhigh[$channo]=1; + } else{ + $owg_alarmhigh[$channo]=0; + } + #-- OWX interface if( $interface eq "OWX" ){ - $ret = OWXAD_SetPage($hash,"alarm"); - return $ret - if(defined($ret)); $ret = OWXAD_SetPage($hash,"status"); return $ret if(defined($ret)); @@ -603,59 +643,105 @@ sub OWAD_Set($@) { } else { return "OWAD: Set with wrong IODev type $interface"; } + }elsif( $key =~ m/(.*)(Low|High)/ ) { + $offset = $attr{$name}{$owg_fixed[$channo]."offset"}; + $factor = $attr{$name}{$owg_fixed[$channo]."factor"}; - #-- process results - my $tn = TimeNow(); - #-- set alarm value in the readings - if( $key =~ m/(.*)low/ ){ - $hash->{READINGS}{$owg_channel[$channo]."low"}{VAL} = $value; - $hash->{READINGS}{$owg_channel[$channo]."low"}{TIME} = $tn; - #-- Test for alarm condition - if ( $owg_low[$channo] > $owg_val[$channo] ){ - $owg_alarmlow[$channo] = 2 - if($owg_alarmlow[$channo] == 1); - } elsif ($owg_alarmlow[$channo] == 2) { - $condx = 1; - $owg_alarmlow[$channo] = 1; - } - } else { - $hash->{READINGS}{$owg_channel[$channo]."high"}{VAL} = $value; - $hash->{READINGS}{$owg_channel[$channo]."high"}{TIME} = $tn; - - #-- Test for new alarm condition - $condx = 0; - if ( $owg_high[$channo] < $owg_val[$channo] ){ - $owg_alarmhigh[$channo] = 2 - if($owg_alarmhigh[$channo] == 1); - } elsif($owg_alarmhigh[$channo] == 2) { - $condx = 1; - $owg_alarmhigh[$channo] = 1; - } + #-- find upper and lower boundaries for given offset/factor + my $mmin = 0.0; + + $mmin += $offset if ( $offset ); + $mmin *= $factor if ( $factor ); + + my $mmax = $owg_range[$channo]/1000; + $mmax += $offset if ( $offset ); + $mmax *= $factor if ( $factor ); + + return sprintf("OWAD: Set with wrong value $value for $key, range is [%3.1f,%3.1f]",$mmin,$mmax) + if($value < $mmin || $value > $mmax); + + $value /= $factor if ( $factor ); + $value -= $offset if ( $offset ); + #-- round to those numbers understood by the device and backward into the value; + my $value2 = int($value*255000/$owg_range[$channo])*$owg_range[$channo]/255000; + $value = $value2; + $value += $offset if ( $offset ); + $value *= $factor if ( $factor ); + + #-- set alarm value in the device + if( $key =~ m/(.*)Low/ ){ + $owg_low[$channo] = $value2; + } elsif( $key =~ m/(.*)High/ ){ + $owg_high[$channo] = $value2; } - #-- set up a new alarm string for the status display - my $value2 = ""; - for (my $i=0;$i<4;$i++){ - $value2 .= sprintf "%s: L",$owg_channel[$i]; - if( $owg_alarmlow[$i] == 0 ) { - $value2 .= "- "; - }elsif( $owg_alarmlow[$i] == 1 ) { - $value2 .= "+ "; - }else{ - $value2 .= "* "; - } - $value2 .= sprintf " H"; - if( $owg_alarmhigh[$i] == 0 ) { - $value2 .= "- "; - }elsif( $owg_alarmhigh[$i] == 1 ) { - $value2 .= "+ "; - }else{ - $value2 .= "* "; - } - } - $hash->{READINGS}{alarms}{VAL} = $value2; - $hash->{READINGS}{alarms}{TIME} = $tn; - } + #-- OWX interface + if( $interface eq "OWX" ){ + $ret = OWXAD_SetPage($hash,"alarm"); + return $ret + if(defined($ret)); + #-- OWFS interface + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSAD_SetValues($hash,@a); + # return $ret + # if(defined($ret)); + } else { + return "OWAD: Set with wrong IODev type $interface"; + } + } + + #-- process results + my $tn = TimeNow(); + #-- set alarm value in the readings + if( $key =~ m/(.*)Low/ ){ + $hash->{READINGS}{$owg_channel[$channo]."Low"}{VAL} = $value; + $hash->{READINGS}{$owg_channel[$channo]."Low"}{TIME} = $tn; + #-- Test for alarm condition, her ewith the raw values (uncorrected) + if ( $owg_low[$channo] > $owg_val[$channo] ){ + $owg_alarmlow[$channo] = 2 + if($owg_alarmlow[$channo] == 1); + } elsif ($owg_alarmlow[$channo] == 2) { + $condx = 1; + $owg_alarmlow[$channo] = 1; + } + } elsif( $key =~ m/(.*)High/ ){ + $hash->{READINGS}{$owg_channel[$channo]."High"}{VAL} = $value; + $hash->{READINGS}{$owg_channel[$channo]."High"}{TIME} = $tn; + #-- Test for new alarm condition + $condx = 0; + if( $channo && defined($owg_val[$channo]) ){ + if( $owg_high[$channo] < $owg_val[$channo] ){ + $owg_alarmhigh[$channo] = 2 + if($owg_alarmhigh[$channo] == 1); + } elsif($owg_alarmhigh[$channo] == 2) { + $condx = 1; + $owg_alarmhigh[$channo] = 1; + } + } + } + #-- set up a new alarm string for the status display + my $value2 = ""; + for (my $i=0;$i<4;$i++){ + $value2 .= sprintf "%s: L",$owg_channel[$i]; + if( $owg_alarmlow[$i] == 0 ) { + $value2 .= "- "; + }elsif( $owg_alarmlow[$i] == 1 ) { + $value2 .= "+ "; + }else{ + $value2 .= "* "; + } + $value2 .= sprintf " H"; + if( $owg_alarmhigh[$i] == 0 ) { + $value2 .= "- "; + }elsif( $owg_alarmhigh[$i] == 1 ) { + $value2 .= "+ "; + }else{ + $value2 .= "* "; + } + } + $hash->{READINGS}{alarms}{VAL} = $value2; + $hash->{READINGS}{alarms}{TIME} = $tn; + Log 4, "OWAD: Set $hash->{NAME} $key $value"; return undef; } @@ -669,7 +755,7 @@ sub OWAD_Set($@) { sub OWAD_Undef ($) { my ($hash) = @_; - delete($modules{OWTEMP}{defptr}{$hash->{OW_ID}}); + delete($modules{OWAD}{defptr}{$hash->{OW_ID}}); RemoveInternalTimer($hash); return undef; } @@ -905,6 +991,7 @@ sub OWXAD_SetPage($$) { for( $i=0;$i<4;$i++){ $select .= sprintf "%c\xFF\xFF\xFF",int($owg_low[$i]*255000/$owg_range[$i]); $select .= sprintf "%c\xFF\xFF\xFF",int($owg_high[$i]*255000/$owg_range[$i]); + #print "Setting alarm values to ".int($owg_low[$i]*255000/$owg_range[$i])." ".int($owg_high[$i]*255000/$owg_range[$i])."\n"; } #=============== set the status =============================== } elsif ( $page eq "status" ) { @@ -929,6 +1016,7 @@ sub OWXAD_SetPage($$) { } $select .= sprintf "%c\xFF\xFF\xFF",$sb1; $select .= sprintf "%c\xFF\xFF\xFF",$sb2; + #print "setting status bytes $sb1 $sb2\n"; } #=============== wrong value requested =============================== } else { @@ -946,83 +1034,4 @@ sub OWXAD_SetPage($$) { return undef; } -####################################################################################### -# -# OWXAD_SetValues - Implements SetFn function -# -# Parameter hash = hash of the device addressed here, a = argument array -# -######################################################################################## - -sub OWXAD_SetValues($@) { - my ($hash, @a) = @_; - - 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]; - - #-- get the old values - #$owg_v1 = $hash->{READINGS}{v1}{VAL}; - #$owg_v2 = $hash->{READINGS}{v2}{VAL}; - #$owg_v3 = $hash->{READINGS}{v3}{VAL}; - #$owg_v4 = $hash->{READINGS}{v4}{VAL}; - - #-- put into 2's complement formed (signed byte) - #my $tlp = $owg_v2 < 0 ? 128 - $owg_v2 : $owg_v2; - #my $thp = $owg_v3 < 0 ? 128 - $owg_v3 : $owg_v3; - - OWX_Reset($master); - - #-- issue the match ROM command \x55 and the write scratchpad command \x4E, - # followed by the write EEPROM command \x48 - # - # so far writing the EEPROM does not work properly. - # 1. \x48 directly appended to the write scratchpad command => command ok, no effect on EEPROM - # 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); - - #if( $res eq 0 ){ - # return "OWXAD: 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, "OWXAD_SetTemp: Device $romid not accessible in the second step"; - # return 0; - #} - - DoTrigger($name, undef) if($init_done); - return undef; -} - - - 1; diff --git a/contrib/1-Wire/21_OWID.pm b/contrib/1-Wire/21_OWID.pm new file mode 100644 index 000000000..21bd43868 --- /dev/null +++ b/contrib/1-Wire/21_OWID.pm @@ -0,0 +1,254 @@ +######################################################################################## +# +# OWID.pm +# +# FHEM module to commmunicate with 1-Wire ID-ROMS +# +# Attention: This module may communicate with the OWX module, +# but currently not with the 1-Wire File System OWFS +# +# Prefixes for subroutines of this module: +# OW = General 1-Wire routines Peter Henning) +# +# Prof. Dr. Peter A. Henning, 2012 +# +# Version 1.03 - March, 2012 +# +# Setup bus device in fhem.cfg as +# define OWID [] +# +# where may be replaced by any name string +# +# is a 1-Wire device type. If omitted, we assume this to be a DS2502 +# is a 12 character (6 byte) 1-Wire ROM ID +# without Family ID, e.g. A2D90D000800 +# +# Additional attributes are defined in fhem.cfg as +# +######################################################################################## +# +# This programm is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# The GNU General Public License can be found at +# http://www.gnu.org/copyleft/gpl.html. +# A copy is found in the textfile GPL.txt and important notices to the license +# from the author is found in LICENSE.txt distributed with these scripts. +# +# This script is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +######################################################################################## +package main; + +#-- Prototypes to make komodo happy +use vars qw{%attr %defs}; +use strict; +use warnings; +sub Log($$); + +#-- declare variables +my %gets = ( + "present" => "", + "id" => "" +); +my %sets = (); +my %updates = (); + +######################################################################################## +# +# The following subroutines are independent of the bus interface +# +# Prefix = OWID +# +######################################################################################## +# +# OWID_Initialize +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWID_Initialize ($) { + my ($hash) = @_; + + $hash->{DefFn} = "OWID_Define"; + $hash->{UndefFn} = "OWID_Undef"; + $hash->{GetFn} = "OWID_Get"; + $hash->{SetFn} = undef; + my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2502 loglevel:0,1,2,3,4,5 "; + $hash->{AttrList} = $attlist; +} + +######################################################################################### +# +# OWID_Define - Implements DefFn function +# +# Parameter hash = hash of device addressed, def = definition string +# +######################################################################################### + +sub OWID_Define ($$) { + my ($hash, $def) = @_; + + # define OWID [] + # e.g.: define flow OWID 525715020000 + my @a = split("[ \t][ \t]*", $def); + + my ($name,$model,$id,$scale,$ret); + + #-- default + $name = $a[0]; + $ret = ""; + + #-- check syntax + return "OWID: Wrong syntax, must be define OWID [] " + if(int(@a) < 2 || int(@a) > 4); + + #-- check if this is an old style definition, e.g. is missing + my $a2 = lc($a[2]); + my $a3 = defined($a[3]) ? lc($a[3]) : ""; + if( $a2 =~ m/^[0-9|a-f]{12}$/ ) { + $model = "DS2502"; + $id = $a[2]; + } elsif( $a3 =~ m/^[0-9|a-f]{12}$/ ) { + $model = $a[2]; + return "OWID: Wrong 1-Wire device model $model" + if( $model ne "DS2502"); + $id = $a[3]; + } else { + return "OWID: $a[0] ID $a[2] invalid, specify a 12 digit value"; + } + + #-- 1-Wire ROM identifier in the form "FF.XXXXXXXXXXXX.YY" + # YY must be determined from id + my $crc = sprintf("%02x",OWX_CRC("09.".$id."00")); + + #-- Define device internals + $hash->{ROM_ID} = "09.".$id.$crc; + $hash->{OW_ID} = $id; + $hash->{OW_FAMILY} = 9; + $hash->{PRESENT} = 0; + + #-- Couple to I/O device + AssignIoPort($hash); + Log 3, "OWID: Warning, no 1-Wire I/O device found for $name." + if(!defined($hash->{IODev}->{NAME})); + + $modules{OWID}{defptr}{$id} = $hash; + + #-- Take channel names from $owg_channel + #my $channels; + + #foreach my $a (sort keys %attr) { + # print "attr $a $attr{$a}\n"; + # foreach my $b (sort keys %{$attr{$a}}) { + # print "============> attr $a $b $attr{$a}{$b}\n"; + # } + #} + #if ( $channels ){ + # my $i=0; + # $channels =~ s/(\w+)/$owg_channel[$i++]=$1/gse; + #} + + #print "$name channels = ".join(" ",@owg_channel)."\n"; + + $hash->{STATE} = "Defined"; + Log 3, "OWID: Device $name defined."; + + #-- Initialization reading according to interface type + my $interface= $hash->{IODev}->{TYPE}; + #-- OWX interface + #if( $interface eq "OWX" ){ + # OWXAD_SetPage($hash,"alarm"); + # OWXAD_SetPage($hash,"status"); + #-- OWFS interface + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSAD_GetPage($hash,"reading"); + #-- Unknown interface + #}else{ + # return "OWID: Define with wrong IODev type $interface"; + #} + + #-- redefine attributes according to channel names + #my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2450 loglevel:0,1,2,3,4,5 ". + # "channels "; + #for( my $i=0;$i<4;$i++ ){ + # $attlist .= " ".$owg_channel[$i]."Offset"; + # $attlist .= " ".$owg_channel[$i]."Factor"; + # $attlist .= " ".$owg_channel[$i]."Scale"; + #} + #$hash->{AttrList} = $attlist; + + #-- Start timer for updates + #InternalTimer(time()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0); + + #-- InternalTimer blocks if init_done is not true + #my $oid = $init_done; + $hash->{STATE} = "Initialized"; + return undef; +} + +######################################################################################## +# +# OWID_Get - Implements GetFn function +# +# Parameter hash = hash of device addressed, a = argument array +# +######################################################################################## + +sub OWID_Get($@) { + my ($hash, @a) = @_; + + my $reading = $a[1]; + my $name = $hash->{NAME}; + my $model = $hash->{OW_MODEL}; + my $value = undef; + my $ret = ""; + my $offset; + my $factor; + + #-- check syntax + return "OWID: Get argument is missing @a" + if(int(@a) != 2); + + #-- check argument + return "OWID: Get with unknown argument $a[1], choose one of ".join(",", sort keys %gets) + if(!defined($gets{$a[1]})); + + #-- get id + if($a[1] eq "id") { + $value = $hash->{ROM_ID}; + return "$a[0] $reading => $value"; + } + + #-- get present + if($a[1] eq "present") { + #-- hash of the busmaster + my $master = $hash->{IODev}; + $value = OWX_Verify($master,$hash->{ROM_ID}); + $hash->{PRESENT} = $value; + return "$a[0] $reading => $value"; + } +} + +######################################################################################## +# +# OWID_Undef - Implements UndefFn function +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWID_Undef ($) { + my ($hash) = @_; + delete($modules{OWID}{defptr}{$hash->{OW_ID}}); + RemoveInternalTimer($hash); + return undef; +} + +1; diff --git a/contrib/1-Wire/21_OWTEMP.pm b/contrib/1-Wire/21_OWTEMP.pm index c6e73c12b..8b3706201 100644 --- a/contrib/1-Wire/21_OWTEMP.pm +++ b/contrib/1-Wire/21_OWTEMP.pm @@ -16,10 +16,10 @@ # Martin Fischer, 2011 # Prof. Dr. Peter A. Henning, 2012 # -# Version 1.02 - February 29, 2012 +# Version 1.03 - March, 2012 # # Setup bus device in fhem.cfg as -# define OWTEMP [] [interval] [alarminterval] +# define OWTEMP [] [interval] # # where may be replaced by any name string # @@ -28,7 +28,6 @@ # is a 12 character (6 byte) 1-Wire ROM ID # without Family ID, e.g. A2D90D000800 # [interval] is an optional query interval in seconds -# [alarminterval] as an additional parameter is ignored so far ! # # Additional attributes are defined in fhem.cfg as # @@ -63,48 +62,29 @@ use strict; use warnings; sub Log($$); -#-- declare variables -my $ownet; -my %gets = (); -my %sets = (); -my %updates = (); - #-- temperature globals my $owg_temp=0; my $owg_th=0; my $owg_tl=0; -%gets = ( +my %gets = ( + "id" => "", "present" => "", "interval" => "", "temperature" => "", - "temphigh" => "", - "templow" => "" + "alarm" => "" ); -%sets = ( - "interval" => "", - "temphigh" => "", - "templow" => "" +my %sets = ( + "interval" => "", + "tempHigh" => "", + "tempLow" => "" ); -%updates = ( +my %updates = ( "present" => "", "temperature" => "", - "templow" => "", - "temphigh" => "", -); - -my %dummy = ( - "crc8" => "4D", - "alias" => "dummy", - "locator" => "FFFFFFFFFFFFFFFF", - "power" => "0", - "present" => "1", - "temphigh" => "75", - "templow" => "10", - "type" => "DS18S20", - "warnings" => "none", + "alarm" => "" ); ######################################################################################## @@ -131,7 +111,7 @@ sub OWTEMP_Initialize ($) { #offset = a temperature offset added to the temperature reading for correction #scale = a unit of measure: C/F/K/R $hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 model:DS18S20 loglevel:0,1,2,3,4,5 ". - "offset scale:C,F,K,R"; + "tempOffset tempScale:Celsius,Fahrenheit,Kelvin,Reaumur"; } ######################################################################################## @@ -145,11 +125,11 @@ sub OWTEMP_Initialize ($) { sub OWTEMP_Define ($$) { my ($hash, $def) = @_; - # define OWTEMP [] [interval] [alarminterval] + # define OWTEMP [] [interval] # e.g.: define flow OWTEMP 525715020000 300 my @a = split("[ \t][ \t]*", $def); - my ($name,$model,$id,$interval,$alarminterval,$ret); + my ($name,$model,$id,$interval,$ret); my $tn = TimeNow(); #-- default @@ -158,19 +138,21 @@ sub OWTEMP_Define ($$) { $ret = ""; #-- check syntax - return "OWTEMP: Wrong syntax, must be define OWTEMP [] [interval] [alarminterval]" + return "OWTEMP: Wrong syntax, must be define OWTEMP [] [interval]" if(int(@a) < 2 || int(@a) > 6); #-- check if this is an old style definition, e.g. is missing my $a2 = lc($a[2]); my $a3 = defined($a[3]) ? lc($a[3]) : ""; - if( ($a2 eq "none") || ($a2 =~ m/^[0-9|a-f]{12}$/) ) { + if( ($a2 eq "none") || ($a3 eq "none") ) { + return "OWTEMP: ID = none is obsolete now, please redefine"; + } elsif( $a2 =~ m/^[0-9|a-f]{12}$/ ) { $model = "DS1820"; $id = $a[2]; if(int(@a)>=4) { $interval = $a[3]; } Log 1, "OWTEMP: Parameter [alarminterval] is obsolete now - must be set with I/O-Device" if(int(@a) == 5); - } elsif( ($a3 eq "none") || ($a3 =~ m/^[0-9|a-f]{12}$/) ) { + } elsif( $a3 =~ m/^[0-9|a-f]{12}$/ ) { $model = $a[2]; return "OWTEMP: Wrong 1-Wire device model $model" if( $model ne "DS1820"); @@ -179,7 +161,7 @@ sub OWTEMP_Define ($$) { Log 1, "OWTEMP: Parameter [alarminterval] is obsolete now - must be set with I/O-Device" if(int(@a) == 6); } else { - return "OWTEMP: $a[0] ID $a[2] invalid, specify a 12 digit value or set it to none for demo mode"; + return "OWTEMP: $a[0] ID $a[2] invalid, specify a 12 digit value"; } #-- 1-Wire ROM identifier in the form "FF.XXXXXXXXXXXX.YY" @@ -194,35 +176,25 @@ sub OWTEMP_Define ($$) { $hash->{OW_FAMILY} = 10; $hash->{PRESENT} = 0; - $modules{OWTEMP}{defptr}{$id} = $hash; - + #-- Couple to I/O device AssignIoPort($hash); Log 3, "OWTEMP: Warning, no 1-Wire I/O device found for $name." if(!defined($hash->{IODev}->{NAME})); + + $modules{OWTEMP}{defptr}{$id} = $hash; - #-- define dummy values for testing - if($hash->{OW_ID} eq "none") { - my $now = TimeNow(); - $dummy{address} = $hash->{OW_FAMILY}.$hash->{OW_ID}.$dummy{crc8}; - $dummy{family} = $hash->{OW_FAMILY}; - $dummy{id} = $hash->{OW_ID}; - $dummy{temperature} = "80.0000"; - foreach my $r (sort keys %gets) { - $hash->{READINGS}{$r}{TIME} = $tn; - $hash->{READINGS}{$r}{VAL} = $dummy{$r}; - Log 4, "OWTEMP: $hash->{NAME} $r: ".$dummy{$r}; - } #-- Initial readings temperature sensor - } else { - $hash->{READINGS}{temp}{VAL} = 0.0; - $hash->{READINGS}{templow}{VAL} = 0.0; - $hash->{READINGS}{temphigh}{VAL} = 0.0; - $hash->{READINGS}{temp}{TIME} = ""; - $hash->{READINGS}{templow}{TIME} = ""; - $hash->{READINGS}{temphigh}{TIME} = ""; - $hash->{STATE} = "Defined"; - Log 3, "OWTEMP: Device $name defined."; - } + $hash->{READINGS}{"temperature"}{VAL} = 0.0; + #$hash->{READINGS}{"temperature"}{UNIT} = "celsius"; + #$hash->{READINGS}{"temperature"}{TYPE} = "temperature"; + $hash->{READINGS}{"tempLow"}{VAL} = 0.0; + $hash->{READINGS}{"tempHigh"}{VAL} = 0.0; + $hash->{READINGS}{"temperature"}{TIME} = ""; + $hash->{READINGS}{"tempLow"}{TIME} = ""; + $hash->{READINGS}{"tempHigh"}{TIME} = ""; + $hash->{STATE} = "Defined"; + Log 3, "OWTEMP: Device $name defined."; + #-- Start timer for updates InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetValues", $hash, 0); @@ -247,28 +219,40 @@ sub OWTEMP_Get($@) { my $value = undef; my $ret = ""; - #-- check argument - return "OWTEMP: Get with unknown argument $a[1], choose one of ".join(",", sort keys %gets) - if(!defined($gets{$a[1]})); #-- check syntax return "OWTEMP: Get argument is missing @a" if(int(@a) != 2); - - #-- get interval - if($a[1] eq "interval") { - $value = $hash->{INTERVAL}; + + #-- check argument + return "OWTEMP: Get with unknown argument $a[1], choose one of ".join(",", sort keys %gets) + if(!defined($gets{$a[1]})); + + #-- get id + if($a[1] eq "id") { + $value = $hash->{ROM_ID}; return "$a[0] $reading => $value"; } #-- get present if($a[1] eq "present") { - $value = $hash->{PRESENT}; + #-- hash of the busmaster + my $master = $hash->{IODev}; + $value = OWX_Verify($master,$hash->{ROM_ID}); + $hash->{PRESENT} = $value; + return "$a[0] $reading => $value"; + } + #-- get interval + if($reading eq "interval") { + $value = $hash->{INTERVAL}; return "$a[0] $reading => $value"; } + + #-- reset presence + $hash->{PRESENT} = 0; #-- Get other values according to interface type my $interface= $hash->{IODev}->{TYPE}; - #-- OWX interface + #-- OWX interface if( $interface eq "OWX" ){ #-- not different from getting all values .. $ret = OWXTEMP_GetValues($hash); @@ -281,35 +265,44 @@ sub OWTEMP_Get($@) { } #-- process results + if( defined($ret) ){ + return "OWTEMP: Could not get values from device $name"; + } + $hash->{PRESENT} = 1; my $tn = TimeNow(); #-- correct for proper offset - $owg_temp += $attr{$name}{offset} if ($attr{$name}{offset} ); - #-- Test for alarm condition - if( ($owg_temp <= $owg_tl) | ($owg_temp >= $owg_th) ){ - $hash->{STATE} = "Alarmed"; - } else { - $hash->{STATE} = "Normal"; + my $offset = $attr{$name}{tempOffset}; + if( $offset ){ + $owg_temp += $offset; + #$owg_tl += $offset; + #$owg_tl += $offset; } #-- put into READINGS - $hash->{READINGS}{temp}{VAL} = $owg_temp; - $hash->{READINGS}{temp}{TIME} = $tn; - $hash->{READINGS}{templow}{VAL} = $owg_tl; - $hash->{READINGS}{templow}{TIME} = $tn; - $hash->{READINGS}{temphigh}{VAL} = $owg_th; - $hash->{READINGS}{temphigh}{TIME} = $tn; + $hash->{READINGS}{"temperature"}{VAL} = $owg_temp; + $hash->{READINGS}{"temperature"}{TIME} = $tn; + $hash->{READINGS}{"tempLow"}{VAL} = $owg_tl; + $hash->{READINGS}{"tempLow"}{TIME} = $tn; + $hash->{READINGS}{"tempHigh"}{VAL} = $owg_th; + $hash->{READINGS}{"tempHigh"}{TIME} = $tn; + + #-- Test for alarm condition + if( ($owg_temp <= $owg_tl) | ($owg_temp >= $owg_th) ){ + $hash->{STATE} = "Alarmed"; + $hash->{ALARM} = 1; + } else { + $hash->{STATE} = "Normal"; + $hash->{ALARM} = 0; + } #-- return the special reading - $reading = "temp" if( $reading eq "temperature"); - if(defined($hash->{READINGS}{$reading})) { - $value = $hash->{READINGS}{$reading}{VAL}; + if ($reading eq "temperature") { + return "OWTEMP: $name.temperature => $owg_temp"; + } elsif ($reading eq "alarm") { + return "OWTEMP: $name.alarm => L $owg_tl H $owg_th"; } - if(!defined($value)) { - Log GetLogLevel($name,4), "OWTEMP: Can't get value for $name.$reading"; - return "OWTEMP: Can't get value for $name.$reading"; - } - return "OWTEMP: $name.$reading => $value"; + return undef; } ####################################################################################### @@ -328,56 +321,57 @@ sub OWTEMP_GetValues($@) { my $value = ""; my $ret = ""; - #-- define warnings - $hash->{ALARM} = "0"; - #-- restart timer for updates RemoveInternalTimer($hash); InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetValues", $hash, 1); + #-- reset presence + $hash->{PRESENT} = 0; + + #-- Get values according to interface type my $interface= $hash->{IODev}->{TYPE}; - #-- real sensor - if($hash->{OW_ID} ne "none") { - $hash->{PRESENT} = 0; - #-- Get values according to interface type - my $interface= $hash->{IODev}->{TYPE}; - if( $interface eq "OWX" ){ - $ret = OWXTEMP_GetValues($hash); - }elsif( $interface eq "OWFS" ){ - $ret = OWFSTEMP_GetValues($hash); - }else{ - return "OWTEMP: GetValues with wrong IODev type $interface"; - } - #-- dummy sensor - } else { - $owg_temp = sprintf("%.4f",rand(85)); - $dummy{temperature} = $owg_temp; - $dummy{present} = "1"; - $hash->{PRESENT} = 1; + if( $interface eq "OWX" ){ + $ret = OWXTEMP_GetValues($hash); + }elsif( $interface eq "OWFS" ){ + $ret = OWFSTEMP_GetValues($hash); + }else{ + return "OWTEMP: GetValues with wrong IODev type $interface"; } - + #-- process results + if( defined($ret) ){ + return "OWTEMP: Could not get values from device $name"; + } + $hash->{PRESENT} = 1; my $tn = TimeNow(); #-- correct for proper offset - $owg_temp += $attr{$name}{offset} if ($attr{$name}{offset} ); - #-- Test for alarm condition - if( ($owg_temp <= $owg_tl) | ($owg_temp >= $owg_th) ){ - $hash->{STATE} = "Alarmed"; - } else { - $hash->{STATE} = "Normal"; + my $offset = $attr{$name}{tempOffset}; + if( $offset ){ + $owg_temp += $offset; + #$owg_tl += $offset; + #$owg_tl += $offset; } #-- put into READINGS - $hash->{READINGS}{temp}{VAL} = $owg_temp; - $hash->{READINGS}{temp}{TIME} = $tn; - $hash->{READINGS}{templow}{VAL} = $owg_tl; - $hash->{READINGS}{templow}{TIME} = $tn; - $hash->{READINGS}{temphigh}{VAL} = $owg_th; - $hash->{READINGS}{temphigh}{TIME} = $tn; + $hash->{READINGS}{"temperature"}{VAL} = $owg_temp; + $hash->{READINGS}{"temperature"}{TIME} = $tn; + $hash->{READINGS}{"tempLow"}{VAL} = $owg_tl; + $hash->{READINGS}{"tempLow"}{TIME} = $tn; + $hash->{READINGS}{"tempHigh"}{VAL} = $owg_th; + $hash->{READINGS}{"tempHigh"}{TIME} = $tn; + + #-- Test for alarm condition + if( ($owg_temp <= $owg_tl) | ($owg_temp >= $owg_th) ){ + $hash->{STATE} = "Alarmed"; + $hash->{ALARM} = 1; + } else { + $hash->{STATE} = "Normal"; + $hash->{ALARM} = 0; + } #--logging - my $rv = sprintf "temp: %3.1f templow: %3.0f temphigh: %3.0f",$owg_temp,$owg_tl,$owg_th; + my $rv = sprintf "temperature: %5.3f tLow: %3.0f tHigh: %3.0f",$owg_temp,$owg_tl,$owg_th; Log 5, $rv; $hash->{CHANGED}[0] = $rv; DoTrigger($name, undef); @@ -387,7 +381,7 @@ sub OWTEMP_GetValues($@) { ####################################################################################### # -# OWTEMP_Set - Set on values for device +# OWTEMP_Set - Set one value for device # # Parameter hash = hash of device addressed # a = argument string @@ -396,10 +390,6 @@ sub OWTEMP_GetValues($@) { sub OWTEMP_Set($@) { my ($hash, @a) = @_; - - my $name = $hash->{NAME}; - my $model = $hash->{OW_MODEL}; - my $path = "10.".$hash->{OW_ID}; #-- for the selector: which values are possible return join(" ", sort keys %sets) if(@a == 2); @@ -414,9 +404,12 @@ sub OWTEMP_Set($@) { my $key = $a[1]; my $value = $a[2]; my $ret = undef; + my $name = $hash->{NAME}; + my $model = $hash->{OW_MODEL}; + my $path = "10.".$hash->{OW_ID}; #-- set warnings - if($key eq "templow" || $key eq "temphigh") { + if($key eq "tempLow" || $key eq "tempHigh") { # check range return "OWTEMP: Set with wrong temperature value, range is -55°C - 125°C" if(int($value) < -55 || int($value) > 125); @@ -425,7 +418,7 @@ sub OWTEMP_Set($@) { #-- set new timer interval if($key eq "interval") { # check value - return "OWTEMP: Set with too short time value, interval must be > 10" + return "OWTEMP: Set with short interval, must be > 10" if(int($value) < 10); # update timer $hash->{INTERVAL} = $value; @@ -435,48 +428,54 @@ sub OWTEMP_Set($@) { } #-- set other values depending on interface type - Log 4, "OWTEMP: Set $hash->{NAME} $key $value"; - my $interface= $hash->{IODev}->{TYPE}; - #-- real sensor - if($hash->{OW_ID} ne "none") { - #-- OWX interface - if( $interface eq "OWX" ){ - $ret = OWXTEMP_SetValues($hash,@a); - return $ret - if(defined($ret)); - #-- OWFS interface - }elsif( $interface eq "OWFS" ){ - $ret = OWFSTEMP_SetValues($hash,@a); - return $ret - if(defined($ret)); - } else { - return "OWTEMP: Set with wrong IODev type $interface"; - } - #-- dummy sensor - } else { - $dummy{$key} = $value; - } + #-- careful: the input values have to be corrected + # with the proper offset + + #-- OWX interface + if( $interface eq "OWX" ){ + $ret = OWXTEMP_SetValues($hash,@a); + return $ret + if(defined($ret)); + #-- OWFS interface + }elsif( $interface eq "OWFS" ){ + $ret = OWFSTEMP_SetValues($hash,@a); + return $ret + if(defined($ret)); + } else { + return "OWTEMP: Set with wrong IODev type $interface"; + } + #-- process results my $tn = TimeNow(); - #-- correct for proper offset - $owg_temp += $attr{$name}{offset} if ($attr{$name}{offset} ); +#-- correct for proper offset + my $offset = $attr{$name}{tempOffset}; + if( $offset ){ + $owg_temp += $offset; + #$owg_tl += $offset; + #$owg_tl += $offset; + } + #-- Test for alarm condition if( ($owg_temp <= $owg_tl) | ($owg_temp >= $owg_th) ){ $hash->{STATE} = "Alarmed"; + $hash->{ALARM} = 1; } else { $hash->{STATE} = "Normal"; + $hash->{ALARM} = 0; } #-- put into READINGS - $hash->{READINGS}{temp}{VAL} = $owg_temp; - $hash->{READINGS}{temp}{TIME} = $tn; - $hash->{READINGS}{templow}{VAL} = $owg_tl; - $hash->{READINGS}{templow}{TIME} = $tn; - $hash->{READINGS}{temphigh}{VAL} = $owg_th; - $hash->{READINGS}{temphigh}{TIME} = $tn; + $hash->{READINGS}{"temperature"}{VAL} = $owg_temp; + $hash->{READINGS}{"temperature"}{TIME} = $tn; + $hash->{READINGS}{"tempLow"}{VAL} = $owg_tl; + $hash->{READINGS}{"tempLow"}{TIME} = $tn; + $hash->{READINGS}{"tempHigh"}{VAL} = $owg_th; + $hash->{READINGS}{"tempHigh"}{TIME} = $tn; + + Log 4, "OWTEMP: Set $hash->{NAME} $key $value"; return undef; } @@ -530,14 +529,14 @@ sub OWFSTEMP_GetValues($) } return undef; - } ####################################################################################### # # OWFSTEMP_SetValues - Implements SetFn function # -# Parameter hash = hash of the device addressed here, a = argument array +# Parameter hash = hash of device addressed +# a = argument array # ######################################################################################## @@ -570,7 +569,7 @@ sub OWXTEMP_GetValues($) { my ($hash) = @_; - #-- For now, switch off temperature conversion command + #-- For default, perform the conversion NOT now my $con=0; #-- ID of the device @@ -591,6 +590,11 @@ sub OWXTEMP_GetValues($) { 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 "parasitic") ){ + $con=1; + } #-- if the conversion has not been called before if( $con==1 ){ @@ -600,8 +604,8 @@ sub OWXTEMP_GetValues($) { if( OWX_Block($master,$select) eq 0 ){ return "OWXTEMP: Device $owx_dev not accessible"; } - #-- conversion needs some 950 ms - sleep(1); + #-- conversion needs some 950 ms - but we may also do it in shorter time ! + select(undef,undef,undef,1.0); } #-- NOW ask the specific device @@ -615,13 +619,13 @@ sub OWXTEMP_GetValues($) { 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); - my $k=ord(substr($res,$i,1))%16; - $res2.=sprintf "0x%1x%1x ",$j,$k; - } - Log 1, $res2; + #my $res2 = "====> OWXTEMP Received "; + #for(my $i=0;$i<19;$i++){ + # my $j=int(ord(substr($res,$i,1))/16); + # my $k=ord(substr($res,$i,1))%16; + # $res2.=sprintf "0x%1x%1x ",$j,$k; + #} + #Log 1, $res2; #-- process results my @data=split(//,$res); @@ -639,7 +643,7 @@ sub OWXTEMP_GetValues($) { $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]); - Log 1, "====> OWXTEMP Conversion result is temp = $owg_temp, delta $delta"; + # Log 1, "====> OWXTEMP Conversion result is temp = $owg_temp, delta $delta"; return undef; } else { @@ -651,7 +655,8 @@ sub OWXTEMP_GetValues($) { # # OWXTEMP_SetValues - Implements SetFn function # -# Parameter hash = hash of the device addressed here, a = argument array +# Parameter hash = hash of device addressed +# a = argument array # ######################################################################################## @@ -684,12 +689,12 @@ sub OWXTEMP_SetValues($@) { my $value = $a[2]; #-- get the old values - $owg_temp = $hash->{READINGS}{temp}{VAL}; - $owg_tl = $hash->{READINGS}{templow}{VAL}; - $owg_th = $hash->{READINGS}{temphigh}{VAL}; + $owg_temp = $hash->{READINGS}{"temperature"}{VAL}; + $owg_tl = $hash->{READINGS}{"tempLow"}{VAL}; + $owg_th = $hash->{READINGS}{"tempHigh"}{VAL}; - $owg_tl = int($value) if( $key eq "templow" ); - $owg_th = int($value) if( $key eq "temphigh" ); + $owg_tl = int($value) if( $key eq "tempLow" ); + $owg_th = int($value) if( $key eq "tempHigh" ); #-- put into 2's complement formed (signed byte) my $tlp = $owg_tl < 0 ? 128 - $owg_tl : $owg_tl;