diff --git a/contrib/1-Wire/00_OWX.pm b/contrib/1-Wire/00_OWX.pm index 501707374..0f89641cd 100644 --- a/contrib/1-Wire/00_OWX.pm +++ b/contrib/1-Wire/00_OWX.pm @@ -6,7 +6,7 @@ # via an active DS2480/DS2490/DS9097U bus master interface or # via a passive DS9097 interface # -# Version 1.01 - February 23, 2012 +# Version 1.02 - February 29, 2012 # # Prof. Dr. Peter A. Henning, 2011 # @@ -203,9 +203,13 @@ sub OWX_Convert($) { # # OWX_CRC - Check the CRC8 code of a device address in @owx_ROM_ID # +# Parameter romid = if not zero, return the CRC8 value instead of checking it +# ######################################################################################## -sub OWX_CRC () { +sub OWX_CRC ($) { + my ($romid) = @_; + my @crc8_table = ( 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, @@ -225,13 +229,75 @@ sub OWX_CRC () { 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53); my $crc8=0; - - for(my $i=0; $i<8; $i++){ - $crc8 = $crc8_table[ $crc8 ^ $owx_ROM_ID[$i] ]; - } - return $crc8; + + if( $romid eq "0" ){ + for(my $i=0; $i<8; $i++){ + $crc8 = $crc8_table[ $crc8 ^ $owx_ROM_ID[$i] ]; + } + return $crc8; + } else { + #-- from search string to byte id + $romid=~s/\.//g; + for(my $i=0;$i<8;$i++){ + $owx_ROM_ID[$i]=hex(substr($romid,2*$i,2)); + } + for(my $i=0; $i<7; $i++){ + $crc8 = $crc8_table[ $crc8 ^ $owx_ROM_ID[$i] ]; + } + return $crc8; + } } +######################################################################################## +# +# OWX_CRC16 - Calculate the CRC16 code of a string +# +# Parameter crc - previous CRC code, c next character +# +######################################################################################## + +sub OWX_CRC16($) { + my ($data) = @_; + + my $crc=0; + for( my $i=0; $i New CRC value = %x",$crc; + } + return $crc; +} + + +sub OWX_DOCRC16($$) { + my ($crc,$c) = @_; + + #-- polynomial for x^16 + x^15 + x^2 + 1 + my $mask = 0xA001; + + my $i; + for($i=0;$i<8;$i++) { + if(($crc ^ ord($c)) & 1) { + $crc=($crc>>1)^$mask; + } else { + $crc>>=1; + } + $c>>=1; + } + return ($crc); +} + +#//-------------------------------------------------------------------# + +#Aufruf der Funktion im Programm: + +#{ +#//... +# unsigned int DEVICE_CRC16=0; +# DEVICE_CRC16 = calcCRC16r (DEVICE_CRC16,chr,0xA001); +#//... +#} + + ######################################################################################## # @@ -312,26 +378,39 @@ sub OWX_Define ($$) { sub OWX_Detect ($) { my ($hash) = @_; - my ($i,$j,$k); + my ($i,$j,$k,$l,$res,$ret); #-- timing byte for DS2480 OWX_Query_2480($hash,"\xC1"); - #-- write 1-Wire bus (Fig. 2 of Maxim AN192) - my $res = OWX_Query_2480($hash,"\x17\x45\x5B\x0F\x91"); - #-- process 4/5-byte string for detection - if( $res eq "\x16\x44\x5A\x00\x93"){ - Log 1, "OWX: 1-Wire bus master DS2480 detected for the first time"; - $owx_interface="DS2480"; - return 1; - } elsif( $res eq "\x17\x45\x5B\x0F\x91"){ - Log 1, "OWX: 1-Wire bus master DS2480 re-detected"; - $owx_interface="DS2480"; - return 1; - } elsif( ($res eq "\x17\x0A\x5B\x0F\x02") || ($res eq "\x00\x17\x0A\x5B\x0F\x02") ){ - Log 1, "OWX: Passive 1-Wire bus interface DS9097 detected"; - $owx_interface="DS9097"; - return 1; - } else { + #-- 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"); + + #-- process 4/5-byte string for detection + if( $res eq "\x16\x44\x5A\x00\x93"){ + Log 1, "OWX: 1-Wire bus master DS2480 detected for the first time"; + $owx_interface="DS2480"; + $ret=1; + } elsif( $res eq "\x17\x45\x5B\x0F\x91"){ + Log 1, "OWX: 1-Wire bus master DS2480 re-detected"; + $owx_interface="DS2480"; + $ret=1; + } elsif( ($res eq "\x17\x0A\x5B\x0F\x02") || ($res eq "\x00\x17\x0A\x5B\x0F\x02") ){ + Log 1, "OWX: Passive 1-Wire bus interface DS9097 detected"; + $owx_interface="DS9097"; + $ret=1; + } else { + $ret=0; + } + last + if( $ret==1 ); + Log 1, "OWX: Trying again to detect an interface"; + #-- sleeping for some time + select(undef,undef,undef,0.5); + } + if( $ret == 0 ){ my $ress = "OWX: No 1-Wire bus interface detected, answer was "; for($i=0;$i{NAME}"); CommandAttr (undef,"$name room OWX"); push(@owx_names,$name); + } 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); } else { Log 1, "OWX: Undefined device family $owx_f"; } @@ -494,7 +581,7 @@ sub OWX_Initialize ($) { my ($hash) = @_; #-- Provider #$hash->{Clients} = ":OWCOUNT:OWHUB:OWLCD:OWMULTI:OWSWITCH:OWTEMP:"; - $hash->{Clients} = ":OWTEMP:"; + $hash->{Clients} = ":OWTEMP:OWAD:"; #-- Normal Devices $hash->{DefFn} = "OWX_Define"; @@ -586,7 +673,7 @@ sub OWX_Search ($$) { return 0; } #--check if we really found a device - if( OWX_CRC()!= 0){ + if( OWX_CRC(0)!= 0){ #-- reset the search Log 1, "OWX: Search CRC failed "; $owx_LastDiscrepancy = 0; @@ -705,25 +792,6 @@ sub OWX_Undef ($$) { return undef; } -######################################################################################## -# -# OBSOLETE subroutine OWX_Values - stub function for OWX_yy -# Necessary, because at time of first scheduling the OWX_yy subs are not yet knwon -# -# Parameter hash = hash of device addressed -# -######################################################################################## - - sub OWX_Values ($) { - my ($hash) = @_; - - my $fam; - foreach $fam (@owx_fams) { - } - my $res=OWXTEMP_Values($hash); - return $res; -} - ######################################################################################## # # OWX_Verify - Verify a particular device on the 1-Wire bus @@ -794,14 +862,7 @@ sub OWX_Block_2480 ($$) { } #-- write 1-Wire bus as a single string my $res =OWX_Query_2480($hash,$data2); - #-- process result - if( length($res) == length($data) ){ - Log 5, "OWX_Block: OK"; - return $res; - } else { - Log 3, "OWX_Block: DAS 2480 failure, received ".length($data)." bytes"; - return 0; - } + return $res; } ######################################################################################## @@ -900,7 +961,7 @@ sub OWX_Query_2480 ($$) { select(undef,undef,undef,0.04); #-- read the data - my ($count_in, $string_in) = $owx_serport->read(32); + my ($count_in, $string_in) = $owx_serport->read(48); if( $owx_debug > 1){ my $res = "OWX: Receiving "; @@ -941,7 +1002,7 @@ sub OWX_Reset_2480 ($) { $cmd = "\xE3"; } #-- Reset command \xC5 - $cmd = $cmd."\xC5"; + $cmd = $cmd."\xC1"; #-- write 1-Wire bus my $res =OWX_Query_2480($hash,$cmd); #-- process result @@ -1134,13 +1195,7 @@ sub OWX_Block_9097 ($$) { $res = OWX_TouchByte_9097($hash,ord(substr($data,$i,1))); $data2 = $data2.chr($res); } - #-- process result - if( length($data2) == length($data) ){ - return $data2; - } else { - Log 3, "OWX: DS9097 block failure, received ".length($data2)." bytes"; - return 0; - } + return $data2; } ######################################################################################## @@ -1190,7 +1245,7 @@ sub OWX_Query_9097 ($$) { select(undef,undef,undef,0.01); #-- read the data - my ($count_in, $string_in) = $owx_serport->read(32); + my ($count_in, $string_in) = $owx_serport->read(48); if( $owx_debug > 1){ my $res = "OWX: Receiving "; diff --git a/contrib/1-Wire/21_OWAD.pm b/contrib/1-Wire/21_OWAD.pm new file mode 100644 index 000000000..c0341a5bf --- /dev/null +++ b/contrib/1-Wire/21_OWAD.pm @@ -0,0 +1,1028 @@ +######################################################################################## +# +# OWAD.pm +# +# 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, +# +# Prefixes for subroutines of this module: +# OW = General 1-Wire routines Peter Henning) +# OWX = 1-Wire bus master interface (Peter Henning) +# OWFS = 1-Wire file system (??) +# +# Prof. Dr. Peter A. Henning, 2012 +# +# Version 1.02 - February 29, 2012 +# +# Setup bus device in fhem.cfg as +# define OWAD [] [interval] +# +# where may be replaced by any name string +# +# is a 1-Wire device type. If omitted, we assume this to be an +# DS2450 A/D converter +# is a 12 character (6 byte) 1-Wire ROM ID +# without Family ID, e.g. A2D90D000800 +# [interval] is an optional query interval in seconds +# +# Additional attributes are defined in fhem.cfg as +# +# attr offset = a offset added to the v1erature reading +# +######################################################################################## +# +# 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 $ownet; +my %gets = (); +my %sets = (); +my %updates = (); + +##-- value globals +my @owg_status; +#-- channel name - fixed for now +my @owg_channel = ("A","B","C","D"); +#-- channel values +my @owg_val; +#-- channel mode +my @owg_mode = ("input","input","input","input"); +#-- resolution in bit - fixed for now +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 values +my @owg_low = (0.0,0.0,0.0,0.0); +my @owg_high = (5.0,5.0,5.0,5.0); + +%gets = ( + "present" => "", + "interval" => "", + "reading" => "", + "alarm" => "", + "status" => "", +); + +%sets = ( + "interval" => "", + "Alow" => "", + "Ahigh" => "", + "Blow" => "", + "Bhigh" => "", + "Clow" => "", + "Chigh" => "", + "Dlow" => "", + "Dhigh" => "" +); + +%updates = ( + "present" => "", + "reading" => "", + "alarm" => "", + "status" => "" +); + + +######################################################################################## +# +# The following subroutines are independent of the bus interface +# +# Prefix = OWAD +# +######################################################################################## +# +# OWAD_Initialize +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWAD_Initialize ($) { + my ($hash) = @_; + + $hash->{DefFn} = "OWAD_Define"; + $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 "; +} + +######################################################################################### +# +# OWAD_Define - Implements DefFn function +# +# Parameter hash = hash of device addressed, def = definition string +# +######################################################################################### + +sub OWAD_Define ($$) { + my ($hash, $def) = @_; + + # define OWAD [] [interval] [alarminterval] + # e.g.: define flow OWAD 525715020000 300 + my @a = split("[ \t][ \t]*", $def); + + my ($name,$model,$id,$interval,$alarminterval,$scale,$ret); + + #-- default + $name = $a[0]; + $interval = 30; + $scale = ""; + $ret = ""; + + #-- check syntax + return "OWAD: Wrong syntax, must be define OWAD [] [interval]" + if(int(@a) < 2 || int(@a) > 5); + + #-- 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 = "DS2450"; + $id = $a[2]; + if(int(@a)>=4) { $interval = $a[3]; } + } elsif( $a3 =~ m/^[0-9|a-f]{12}$/ ) { + $model = $a[2]; + return "OWAD: Wrong 1-Wire device model $model" + if( $model ne "DS2450"); + $id = $a[3]; + } else { + return "OWAD: $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("20.".$id."00")); + + #-- Define device internals + $hash->{INTERVAL} = $interval; + $hash->{ROM_ID} = "20.".$id.$crc; + $hash->{OW_ID} = $id; + $hash->{OW_FAMILY} = 20; + $hash->{PRESENT} = 0; + + #-- Couple to I/O device + AssignIoPort($hash); + return "OWAD: 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}; + + #-- Initialization reading according to interface 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 "OWAD: Define with wrong IODev type $interface"; + } + + #-- Start timer for updates + InternalTimer(time()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 0); + + #-- InternalTimer blocks if init_done is not true + #my $oid = $init_done; + $hash->{STATE} = "Initialized"; + return undef; +} + +######################################################################################## +# +# OWAD_Get - Implements GetFn function +# +# Parameter hash = hash of device addressed, a = argument array +# +######################################################################################## + +sub OWAD_Get($@) { + my ($hash, @a) = @_; + + my $reading = $a[1]; + my $name = $hash->{NAME}; + my $model = $hash->{OW_MODEL}; + my $value = undef; + my $ret = ""; + + #-- 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); + + + #-- get interval + if($a[1] eq "interval") { + $value = $hash->{INTERVAL}; + 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}; + + #-- get reading according to interface type + if($a[1] eq "reading") { + #-- OWX interface + if( $interface eq "OWX" ){ + $ret = OWXAD_GetPage($hash,"reading"); + #-- OWFS interface + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSAD_GetPage($hash,"reading"); + #-- Unknown interface + }else{ + return "OWAD: Get with wrong IODev type $interface"; + } + + #-- process results + 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"; + #} + + #-- put into READINGS + $hash->{READINGS}{$owg_channel[$i]}{VAL} = $owg_val[$i]; + $hash->{READINGS}{$owg_channel[$i]}{TIME} = $tn; + $value .= sprintf "%s: %5.3f ",$owg_channel[$i],$owg_val[$i]; + } + return "OWAD: $name.$reading => $value"; + } + + #-- get alarm values according to interface type + if($a[1] eq "alarm") { + #-- OWX interface + if( $interface eq "OWX" ){ + $ret = OWXAD_GetPage($hash,"alarm"); + #-- OWFS interface + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSAD_GetPage($hash,"alarm"); + #-- Unknown interface + }else{ + return "OWAD: Get with wrong IODev type $interface"; + } + + #-- process results + 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"; + #} + + #-- 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; + + $value .= sprintf "%s:[%4.2f,%4.2f] ",$owg_channel[$i],$owg_low[$i],$owg_high[$i]; + } + return "OWAD: $name.$reading => $value"; + } + + #-- get status values according to interface type + if($a[1] eq "status") { + #-- OWX interface + if( $interface eq "OWX" ){ + $ret = OWXAD_GetPage($hash,"status"); + #-- OWFS interface + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSAD_GetPage($hash,"status"); + #-- Unknown interface + }else{ + return "OWAD: Get with wrong IODev type $interface"; + } + + #-- process results + my $tn = TimeNow(); + $value = ""; + my $value2 = ""; + for (my $i=0;$i<4;$i++){ + $value .= sprintf "%s: %s \n",$owg_channel[$i],$owg_status[$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; + return "OWAD: $name.$reading => \n$value"; + } +} + +####################################################################################### +# +# OWAD_GetValues - Updates the reading from one device +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWAD_GetValues($@) { + my $hash = shift; + + my $name = $hash->{NAME}; + my $model = $hash->{OW_MODEL}; + my $value = ""; + my $ret = ""; + + #-- define warnings + my $warn = "none"; + $hash->{ALARM} = "0"; + + #-- restart timer for updates + RemoveInternalTimer($hash); + InternalTimer(time()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 1); + + #-- 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"); + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSAD_GetValues($hash); + }else{ + return "OWAD: GetValues with wrong IODev type $interface"; + } + + #-- process results + 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"} ); + #-- 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"; + #} + + #-- 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; + $value .= sprintf "%s: %5.3f ",$owg_channel[$i],$owg_val[$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; + + #--logging + Log 5, $value; + $hash->{CHANGED}[0] = $value; + DoTrigger($name, undef); + + return undef; +} + +####################################################################################### +# +# OWAD_Set - Set one value for device +# +# Parameter hash = hash of device addressed +# a = argument string +# +######################################################################################## + +sub OWAD_Set($@) { + my ($hash, @a) = @_; + + my $key = $a[1]; + my $value = $a[2]; + my $ret = undef; + my $channel = undef; + my $channo = undef; + 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" + if(int($value) < 10); + # update timer + $hash->{INTERVAL} = $value; + RemoveInternalTimer($hash); + 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 ) { + for (my $i=0;$i<4;$i++){ + if( $channel eq $owg_channel[$i] ){ + $channo = $i; + last; + } + } + } + + #-- 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"} ); + } + + #-- 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)); + #-- 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 + 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; + } + } + #-- 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; + } + + return undef; +} + +######################################################################################## +# +# OWAD_Undef - Implements UndefFn function +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWAD_Undef ($) { + my ($hash) = @_; + delete($modules{OWTEMP}{defptr}{$hash->{OW_ID}}); + RemoveInternalTimer($hash); + return undef; +} + +######################################################################################## +# +# The following subroutines in alphabetical order are only for a 1-Wire bus connected +# via OWFS +# +# Prefix = OWFSAD +# +######################################################################################## + + + + + +######################################################################################## +# +# The following subroutines in alphabetical order are only for a 1-Wire bus connected +# directly to the FHEM server +# +# Prefix = OWXAD +# +######################################################################################## +# +# OWXAD_GetPage - Get one memory page from device +# +# Parameter hash = hash of device addressed +# page = "reading", "alarm" or "status" +# +######################################################################################## + +sub OWXAD_GetPage($$) { + + my ($hash,$page) = @_; + + #-- For now, switch on conversion command + my $con=1; + + my ($select, $res, $res2, $res3, @data); + + #-- 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)); + } + + #=============== 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); + if( $res eq 0 ){ + return "OWXAD: Device $owx_dev not accessible for conversion"; + } + #-- conversion needs some 5 ms per channel + 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); + #=============== 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); + #=============== 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); + #=============== wrong value requested =============================== + } else { + return "OWXAD: Wrong memory page requested"; + } + + #-- reset the bus + OWX_Reset($master); + #-- read the data + $res=OWX_Block($master,$select); + if( $res eq 0 ){ + return "OWXAD: Device $owx_dev not accessible in reading $page page"; + } + + #-- process results + @data=split(//,$res); + if ( (@data != 22) ){ + return "OWXAD: Device $owx_dev returns invalid data"; + } + + #=============== get the voltage reading =============================== + if( $page eq "reading"){ + for( $i=0;$i<4;$i++){ + $owg_val[$i]= int((ord($data[12+2*$i])+256*ord($data[13+2*$i]))/((1<<$owg_resoln[$i])-1) * $owg_range[$i])/1000; + } + #=============== get the alarm reading =============================== + } elsif ( $page eq "alarm" ) { + for( $i=0;$i<4;$i++){ + $owg_low[$i] = int(ord($data[12+2*$i])/255 * $owg_range[$i])/1000; + $owg_high[$i] = int(ord($data[13+2*$i])/255 * $owg_range[$i])/1000; + } + #=============== get the status reading =============================== + } elsif ( $page eq "status" ) { + my ($sb1,$sb2); + for( $i=0;$i<4;$i++){ + $sb1 = ord($data[12+2*$i]); + $sb2 = ord($data[12+2*$i+1]); + + #-- normal operation + if( $sb1 && 128) { + #-- put into globals + $owg_mode[$i] = "input"; + $owg_resoln[$i] = ($sb1 & 15) + 1 ; + $owg_range[$i] = ($sb2 & 1) ? 5100 : 2550; + #-- low alarm disabled + if( ($sb2 & 4)==0 ){ + $owg_alarmlow[$i] = 0; + }else { + #-- low alarm enabled and not set + if ( ($sb2 & 16)==0 ){ + $owg_alarmlow[$i] = 1; + #-- low alarm enabled and set + }else{ + $owg_alarmlow[$i] = 2; + } + } + #-- high alarm disabled + if( ($sb2 & 8)==0 ){ + $owg_alarmhigh[$i] = 0; + }else { + #-- high alarm enabled and not set + if ( ($sb2 & 32)==0 ){ + $owg_alarmhigh[$i] = 1; + #-- high alarm enabled and set + }else{ + $owg_alarmhigh[$i] = 2; + } + } + + #-- assemble status string + $owg_status[$i] = $owg_mode[$i].", "; + $owg_status[$i] .= "disabled ," + if ( !($sb2 && 128) ); + $owg_status[$i] .= sprintf "raw range %3.1f V, ",$owg_range[$i]/1000; + $owg_status[$i] .= sprintf "resolution %d bit, ",$owg_resoln[$i]; + $owg_status[$i] .= sprintf "low alarm disabled, " + if( $owg_alarmlow[$i]==0 ); + $owg_status[$i] .= sprintf "low alarm enabled, " + if( $owg_alarmlow[$i]==1 ); + $owg_status[$i] .= sprintf "alarmed low, " + if( $owg_alarmlow[$i]==2 ); + $owg_status[$i] .= sprintf "high alarm disabled" + if( $owg_alarmhigh[$i]==0 ); + $owg_status[$i] .= sprintf "high alarm enabled" + if( $owg_alarmhigh[$i]==1 ); + $owg_status[$i] .= sprintf "alarmed high" + if( $owg_alarmhigh[$i]==2 ); + + } else { + $owg_mode[$i] = "output"; + #-- assemble status string + $owg_status[$i] = $owg_mode[$i].", "; + $owg_status[$i] .= ($sb1 & 64 ) ? "ON" : "OFF"; + } + } + } + return undef +} + +######################################################################################## +# +# OWXAD_SetPage - Setup one memory page of device +# +# Parameter hash = hash of device addressed +# page = "alarm" or "status" +# +######################################################################################## + +sub OWXAD_SetPage($$) { + + my ($hash,$page) = @_; + + #-- For now, switch on conversion command + my $con=1; + + my ($select, $res, $res2, $res3, @data); + + #-- 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)); + } + + #=============== set the alarm values =============================== + if ( $page eq "alarm" ) { + #-- 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); + 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]); + } + #=============== set the status =============================== + } elsif ( $page eq "status" ) { + 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); + for( $i=0;$i<4;$i++){ + if( $owg_mode[$i] eq "input" ){ + #-- resolution (TODO: check !) + $sb1 = $owg_resoln[$i]-1; + #-- alarm enabled + $sb2 = ( $owg_alarmlow[$i] > 0 ) ? 4 : 0; + $sb2 += ( $owg_alarmhigh[$i] > 0 ) ? 8 : 0; + #-- range + $sb2 |= 1 + if( $owg_range[$i] > 2550 ); + } else { + $sb1 = 128; + $sb2 = 0; + } + $select .= sprintf "%c\xFF\xFF\xFF",$sb1; + $select .= sprintf "%c\xFF\xFF\xFF",$sb2; + } + #=============== wrong value requested =============================== + } else { + return "OWXAD: Wrong memory page write attempt"; + } + + OWX_Reset($master); + $res=OWX_Block($master,$select); + + #-- process results + if( $res eq 0 ){ + return "OWXAD: Device $owx_dev not accessible for initialization"; + } + + 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_OWTEMP.pm b/contrib/1-Wire/21_OWTEMP.pm index 2183b0214..c6e73c12b 100644 --- a/contrib/1-Wire/21_OWTEMP.pm +++ b/contrib/1-Wire/21_OWTEMP.pm @@ -16,7 +16,7 @@ # Martin Fischer, 2011 # Prof. Dr. Peter A. Henning, 2012 # -# Version 1.01 - February 23, 2012 +# Version 1.02 - February 29, 2012 # # Setup bus device in fhem.cfg as # define OWTEMP [] [interval] [alarminterval] @@ -52,6 +52,9 @@ # GNU General Public License for more details. # ######################################################################################## +# +# TODO: offset in alarm values +# package main; #-- Prototypes to make komodo happy @@ -71,32 +74,18 @@ my $owg_temp=0; my $owg_th=0; my $owg_tl=0; -# temperature scale from IODev -my $scale; - %gets = ( - #"address" => "", - #"alias" => "", - #"crc8" => "", - #"family" => "10", - #"id" => "", - #"locator" => "", - "interval" => "", "present" => "", + "interval" => "", "temperature" => "", "temphigh" => "", "templow" => "" - #, - #"type" => "", ); %sets = ( - #-- obsolete "alias" => "", + "interval" => "", "temphigh" => "", - "templow" => "", - "interval" => "" - #-- taken out into I/O-Device parameters, - #"alarminterval" => "", + "templow" => "" ); %updates = ( @@ -120,11 +109,32 @@ my %dummy = ( ######################################################################################## # -# The following subroutines in alphabetical order are independent of the bus interface +# The following subroutines are independent of the bus interface # # Prefix = OWTEMP # -######################################################################################### +######################################################################################## +# +# OWTEMP_Initialize +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWTEMP_Initialize ($) { + my ($hash) = @_; + + $hash->{DefFn} = "OWTEMP_Define"; + $hash->{UndefFn} = "OWTEMP_Undef"; + $hash->{GetFn} = "OWTEMP_Get"; + $hash->{SetFn} = "OWTEMP_Set"; + #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"; + } + +######################################################################################## # # OWTEMP_Define - Implements DefFn function # @@ -139,12 +149,12 @@ sub OWTEMP_Define ($$) { # e.g.: define flow OWTEMP 525715020000 300 my @a = split("[ \t][ \t]*", $def); - my ($name,$model,$id,$interval,$alarminterval,$scale,$ret); + my ($name,$model,$id,$interval,$alarminterval,$ret); + my $tn = TimeNow(); #-- default $name = $a[0]; $interval = 300; - $scale = ""; $ret = ""; #-- check syntax @@ -171,17 +181,15 @@ sub OWTEMP_Define ($$) { } else { return "OWTEMP: $a[0] ID $a[2] invalid, specify a 12 digit value or set it to none for demo mode"; } - + #-- 1-Wire ROM identifier in the form "FF.XXXXXXXXXXXX.YY" - # - # Careful: For now this is effectively only 14 characters = 7 byte long and - # must not be passed back to the 1-Wire bus. The 8th byte is the CRC code - # and will be appended in the first call of GetTemperatures - # TODO: should be replaced by a calculation of the CRC value ! + # YY must be determined from id + my $crc = sprintf("%02x",OWX_CRC("10.".$id."00")); + #-- define device internals $hash->{ALARM} = 0; $hash->{INTERVAL} = $interval; - $hash->{ROM_ID} = "10.".$id."00"; + $hash->{ROM_ID} = "10.".$id.$crc; $hash->{OW_ID} = $id; $hash->{OW_FAMILY} = 10; $hash->{PRESENT} = 0; @@ -192,24 +200,15 @@ sub OWTEMP_Define ($$) { Log 3, "OWTEMP: Warning, no 1-Wire I/O device found for $name." if(!defined($hash->{IODev}->{NAME})); - #-- get scale from I/O device - $scale = $attr{$hash->{IODev}->{NAME}}{"temp-scale"}; - # define scale for temperature values - $scale = "Celsius" if ($scale eq "C"); - $scale = "Fahrenheit" if ($scale eq "F"); - $scale = "Kelvin" if ($scale eq "K"); - $scale = "Rankine" if ($scale eq "R"); - $hash->{OW_SCALE} = $scale; - #-- 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 (".$hash->{OW_SCALE}.")"; + $dummy{temperature} = "80.0000"; foreach my $r (sort keys %gets) { - $hash->{READINGS}{$r}{TIME} = $now; + $hash->{READINGS}{$r}{TIME} = $tn; $hash->{READINGS}{$r}{VAL} = $dummy{$r}; Log 4, "OWTEMP: $hash->{NAME} $r: ".$dummy{$r}; } @@ -224,39 +223,12 @@ sub OWTEMP_Define ($$) { $hash->{STATE} = "Defined"; Log 3, "OWTEMP: Device $name defined."; } - # start timer for updates - InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetUpdate", $hash, 0); + #-- Start timer for updates + InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetValues", $hash, 0); - # initialize device - #$ret = OWFS_InitializeDevice($hash); - #return "OWFS Can't initialize Device $name" if (!defined($ret)); - #$hash->{STATE} = "Initialized"; - - #-- InternalTimer blocks if init_done is not true - #my $oid = $init_done; $hash->{STATE} = "Initialized"; return undef; } - -######################################################################################### -# -# OWTEMP_Initialize -# -# Parameter hash = hash of device addressed -# -######################################################################################## - -sub OWTEMP_Initialize ($) { - my ($hash) = @_; - - $hash->{DefFn} = "OWTEMP_Define"; - $hash->{UndefFn} = "OWTEMP_Undef"; - $hash->{GetFn} = "OWTEMP_Get"; - $hash->{SetFn} = "OWTEMP_Set"; - #offset = a temperature offset added to the temperature reading - $hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 model:DS18S20 loglevel:0,1,2,3,4,5 ". - "offset "; - } ######################################################################################## # @@ -268,8 +240,12 @@ sub OWTEMP_Initialize ($) { sub OWTEMP_Get($@) { my ($hash, @a) = @_; - my $name = $hash->{NAME}; - my $ret; + + my $reading = $a[1]; + my $name = $hash->{NAME}; + my $model = $hash->{OW_MODEL}; + my $value = undef; + my $ret = ""; #-- check argument return "OWTEMP: Get with unknown argument $a[1], choose one of ".join(",", sort keys %gets) @@ -278,17 +254,13 @@ sub OWTEMP_Get($@) { return "OWTEMP: Get argument is missing @a" if(int(@a) != 2); - # define vars - my $reading = $a[1]; - my $value = undef; - - # get interval + #-- get interval if($a[1] eq "interval") { $value = $hash->{INTERVAL}; return "$a[0] $reading => $value"; } - # get present + #-- get present if($a[1] eq "present") { $value = $hash->{PRESENT}; return "$a[0] $reading => $value"; @@ -342,38 +314,26 @@ sub OWTEMP_Get($@) { ####################################################################################### # -# OWTEMP_GetUpdate - Updates the reading from one device +# OWTEMP_GetValues - Updates the readings from device # # Parameter hash = hash of device addressed # ######################################################################################## -sub OWTEMP_GetUpdate($@) { - my $hash = shift; +sub OWTEMP_GetValues($@) { + my $hash = shift; - my $name = $hash->{NAME}; - my $model = $hash->{OW_MODEL}; - my $owx_dev = $hash->{ROM_ID}; - my $now = TimeNow(); + my $name = $hash->{NAME}; + my $model = $hash->{OW_MODEL}; my $value = ""; - my $temp = ""; my $ret = ""; - my $count = 0; #-- define warnings - my $warn = "none"; $hash->{ALARM} = "0"; #-- restart timer for updates - #if(!$hash->{LOCAL}) { - RemoveInternalTimer($hash); - InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetUpdate", $hash, 1); - #} - - # set new state - #($temp,undef) = split(" ",$hash->{READINGS}{temperature}{VAL}); - #$warn = $hash->{READINGS}{warnings}{VAL}; - #$hash->{STATE} = "T: $temp W: $warn"; + RemoveInternalTimer($hash); + InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetValues", $hash, 1); my $interface= $hash->{IODev}->{TYPE}; #-- real sensor @@ -386,7 +346,7 @@ sub OWTEMP_GetUpdate($@) { }elsif( $interface eq "OWFS" ){ $ret = OWFSTEMP_GetValues($hash); }else{ - return "OWTEMP: GetUpdate with wrong IODev type $interface"; + return "OWTEMP: GetValues with wrong IODev type $interface"; } #-- dummy sensor } else { @@ -427,7 +387,7 @@ sub OWTEMP_GetUpdate($@) { ####################################################################################### # -# OWTEMP_Set - Set values for one device +# OWTEMP_Set - Set on values for device # # Parameter hash = hash of device addressed # a = argument string @@ -436,6 +396,7 @@ sub OWTEMP_GetUpdate($@) { sub OWTEMP_Set($@) { my ($hash, @a) = @_; + my $name = $hash->{NAME}; my $model = $hash->{OW_MODEL}; my $path = "10.".$hash->{OW_ID}; @@ -469,7 +430,7 @@ sub OWTEMP_Set($@) { # update timer $hash->{INTERVAL} = $value; RemoveInternalTimer($hash); - InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWTEMP_GetUpdate", $hash, 1); + InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWTEMP_GetValues", $hash, 1); return undef; } @@ -530,7 +491,8 @@ sub OWTEMP_Set($@) { sub OWTEMP_Undef ($) { my ($hash) = @_; - #delete($modules{OWTEMP}{defptr}{$hash->{CODE}}); + + delete($modules{OWTEMP}{defptr}{$hash->{OW_ID}}); RemoveInternalTimer($hash); return undef; } @@ -608,7 +570,7 @@ sub OWXTEMP_GetValues($) { my ($hash) = @_; - #-- For now, switch of temperature conversion command + #-- For now, switch off temperature conversion command my $con=0; #-- ID of the device