From 5a898baf40ace06af8f4b9166047b36b8ffc27fb Mon Sep 17 00:00:00 2001 From: pahenning <> Date: Fri, 4 Jan 2013 12:12:41 +0000 Subject: [PATCH] git-svn-id: https://svn.fhem.de/fhem/trunk@2433 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/21_OWAD.pm | 658 +++++++++++++++++++-------------------- fhem/FHEM/21_OWID.pm | 97 +++--- fhem/FHEM/21_OWLCD.pm | 244 ++++++++------- fhem/FHEM/21_OWMULTI.pm | 364 ++++++++++------------ fhem/FHEM/21_OWSWITCH.pm | 591 +++++++++++++++++++---------------- fhem/FHEM/21_OWTHERM.pm | 393 +++++++++++------------ 6 files changed, 1154 insertions(+), 1193 deletions(-) diff --git a/fhem/FHEM/21_OWAD.pm b/fhem/FHEM/21_OWAD.pm index 7bf970ea3..6d600509a 100644 --- a/fhem/FHEM/21_OWAD.pm +++ b/fhem/FHEM/21_OWAD.pm @@ -2,24 +2,14 @@ # # OWAD.pm # -# WIESO UNINITIALIZED in 623FF -# # FHEM module to commmunicate with 1-Wire A/D converters DS2450 # -# 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) -# OWX = 1-Wire bus master interface (Peter Henning) -# OWFS = 1-Wire file system (??) -# # Prof. Dr. Peter A. Henning, 2012 -# -# Version 2.25 - October, 2012 -# -# Setup bus device in fhem.cfg as # +# $Id$ +# +######################################################################################## +# # define OWAD [] [interval] # # where may be replaced by any name string @@ -42,20 +32,19 @@ # Additional attributes are defined in fhem.cfg, in some cases per channel, where =A,B,C,D # Note: attributes are read only during initialization procedure - later changes are not used. # -# attr event on-change/on-update = when to write an event (default= on-update) -# -# attr stateAL0 "" = character string for denoting low normal condition, default is empty, -# overwritten by attribute setting green down triangle -# attr stateAH0 "" = character string for denoting high normal condition, default is empty, -# overwritten by attribute setting green up triangle -# attr stateAL1 "" = character string for denoting low alarm condition, default is l, -# overwritten by attributre setting red down triangle -# attr stateAH1 "" = character string for denoting high alarm condition, default is h, -# overwritten by attributre setting red up triangle +# attr stateAL0 "" = character string for denoting low normal condition, default is empty +# attr stateAH0 "" = character string for denoting high normal condition, default is empty +# attr stateAL1 "" = character string for denoting low alarm condition, default is down triangle +# attr stateAH1 "" = character string for denoting high alarm condition, default is up triangle # attr Name | = name for the channel | a type description for the measured value # attr Unit | = unit of measurement for this channel | its abbreviation +# +# ATTENTION: Usage of Offset/Factor is deprecated, replace by Function attribute # attr Offset = offset added to the reading in this channel # attr Factor = factor multiplied to (reading+offset) in this channel +# attr Function = arbitrary functional expression involving the values V=VA,VB,VC,VD +# VA is replaced by the measured voltage in channel A, etc. +# # attr Alarm = alarm setting in this channel, either both, low, high or none (default) # attr Low = measurement value (on the scale determined by offset and factor) for low alarm # attr High = measurement value (on the scale determined by offset and factor) for high alarm @@ -80,7 +69,6 @@ ######################################################################################## package main; -#-- Prototypes to make komodo happy use vars qw{%attr %defs}; use strict; use warnings; @@ -93,7 +81,7 @@ my $owg_state; my @owg_fixed = ("A","B","C","D"); my @owg_channel; #-- channel values - always the raw values from the device -my @owg_val; +my @owg_val=("","","",""); #-- channel mode - fixed for now my @owg_mode = ("input","input","input","input"); #-- resolution in bit - fixed for now @@ -101,8 +89,8 @@ my @owg_resoln = (16,16,16,16); #-- raw range in mV - fixed for now my @owg_range = (5100,5100,5100,5100); #-- alarm status 0 = disabled, 1 = enabled, but not alarmed, 2 = alarmed -my @owg_slow; -my @owg_shigh; +my @owg_slow=(0,0,0,0); +my @owg_shigh=(0,0,0,0); #-- alarm values - always the raw values committed to the device my @owg_vlow; my @owg_vhigh; @@ -154,12 +142,14 @@ sub OWAD_Initialize ($) { #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 ". - "stateAL0 stateAL1 stateAH0 stateAH1 event:on-update,on-change "; + "event-on-update-reading event-on-change-reading ". + "stateAL0 stateAL1 stateAH0 stateAH1"; 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]."Function"; $attlist .= " ".$owg_fixed[$i]."Unit"; $attlist .= " ".$owg_fixed[$i]."Alarm"; $attlist .= " ".$owg_fixed[$i]."Low"; @@ -225,11 +215,13 @@ sub OWAD_Define ($$) { #-- Couple to I/O device AssignIoPort($hash); - Log 3, "OWAD: Warning, no 1-Wire I/O device found for $name." - if(!defined($hash->{IODev}->{NAME})); + if( !defined($hash->{IODev}->{NAME}) | !defined($hash->{IODev}) | ($hash->{IODev}->{PRESENT} != 1) ){ + return "OWAD: Warning, no 1-Wire I/O device found for $name."; + } $modules{OWAD}{defptr}{$id} = $hash; - $hash->{STATE} = "Defined"; - Log 3, "OWAD: Device $name defined."; + #-- + readingsSingleUpdate($hash,"state","defined",1); + Log 3, "OWAD: Device $name defined."; #-- Initialization reading according to interface type my $interface= $hash->{IODev}->{TYPE}; @@ -256,20 +248,10 @@ sub OWAD_InitializeDevice($) { my $name = $hash->{NAME}; - #-- more colorful alarm signatures - CommandAttr (undef,"$name stateAL1 ") - if( !defined($attr{$name}{"stateAL1"} )); - CommandAttr (undef,"$name stateAH1 ") - if( !defined($attr{$name}{"stateAH1"} )); - CommandAttr (undef,"$name stateAL0 ") - if( !defined($attr{$name}{"stateAL0"} )); - CommandAttr (undef,"$name stateAH0 ") - if( !defined($attr{$name}{"stateAH0"} )); - #-- Initial readings - @owg_val = (0.0,0.0,0.0,0.0); - @owg_slow = (0,0,0,0); - @owg_shigh = (0,0,0,0); + @owg_val = ("".""."".""); + @owg_slow = ("".""."".""); + @owg_shigh = ("".""."".""); #-- Set channel names, channel units and alarm values for( my $i=0;$i"; push(@unarr,""); } - - #-- offset and scale factor - my $offset = defined($attr{$name}{$owg_fixed[$i]."Offset"}) ? $attr{$name}{$owg_fixed[$i]."Offset"} : 0.0; - my $factor = defined($attr{$name}{$owg_fixed[$i]."Factor"}) ? $attr{$name}{$owg_fixed[$i]."Factor"} : 1.0; + #-- put into readings $owg_channel[$i] = $cnama[0]; $hash->{READINGS}{"$owg_channel[$i]"}{TYPE} = $cnama[1]; $hash->{READINGS}{"$owg_channel[$i]"}{UNIT} = $unarr[0]; $hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR} = $unarr[1]; - $hash->{READINGS}{"$owg_channel[$i]"}{OFFSET} = $offset; - $hash->{READINGS}{"$owg_channel[$i]"}{FACTOR} = $factor; - #-- alarm + #-- Initial readings my $alarm = defined($attr{$name}{$owg_fixed[$i]."Alarm"}) ? $attr{$name}{$owg_fixed[$i]."Alarm"} : "none"; my $vlow = defined($attr{$name}{$owg_fixed[$i]."Low"}) ? $attr{$name}{$owg_fixed[$i]."Low"} : 0.0; my $vhigh = defined($attr{$name}{$owg_fixed[$i]."High"}) ? $attr{$name}{$owg_fixed[$i]."High"} : 5.0; @@ -310,10 +287,13 @@ sub OWAD_InitializeDevice($) { if( $alarm eq "high" || $alarm eq "both" ){ $owg_shigh[$i]=1; }; - $owg_vlow[$i] = ($vlow/$factor - $offset); - $owg_vhigh[$i] = ($vhigh/$factor - $offset); + $owg_vlow[$i] = $vlow; + $owg_vhigh[$i] = $vhigh; } + #-- Initialize all the display stuff + OWAD_FormatValues($hash); + #-- set status according to interface type my $interface= $hash->{IODev}->{TYPE}; @@ -331,8 +311,6 @@ sub OWAD_InitializeDevice($) { return "OWAD: InitializeDevice with wrong IODev type $interface"; } - #-- Initialize all the display stuff - OWAD_FormatValues($hash); } ######################################################################################## @@ -347,94 +325,131 @@ sub OWAD_FormatValues($) { my ($hash) = @_; my $name = $hash->{NAME}; - my ($offset,$factor,$vval,$vlow,$vhigh); - my ($value1,$value2,$value3) = ("","",""); + my ($offset,$factor,$vval,$vlow,$vhigh,$vfunc); + my $vfuncall = ""; + my $svalue = ""; + #-- insert initial values + for( my $k=0;$k{READINGS}{"$owg_channel[$i]"}{OFFSET}; - $factor = $hash->{READINGS}{"$owg_channel[$i]"}{FACTOR}; - #-- correct values for proper offset, factor - $vval = int(($owg_val[$i] + $offset)*$factor*1000)/1000;; - #-- put into READINGS - $hash->{READINGS}{"$owg_channel[$i]"}{VAL} = $vval; - $hash->{READINGS}{"$owg_channel[$i]"}{TIME} = $tn; - - #-- correct alarm values for proper offset, factor - $vlow = int(($owg_vlow[$i] + $offset)*$factor*1000)/1000; - $vhigh = int(($owg_vhigh[$i] + $offset)*$factor*1000)/1000; - - #-- put into READINGS - $hash->{READINGS}{$owg_channel[$i]."Low"}{VAL} = $vlow; - $hash->{READINGS}{$owg_channel[$i]."Low"}{TIME} = $tn; - $hash->{READINGS}{$owg_channel[$i]."High"}{VAL} = $vhigh; - $hash->{READINGS}{$owg_channel[$i]."High"}{TIME} = $tn; - - #-- string buildup for return value, STATE and alarm - $value1 .= sprintf( "%s: %5.3f %s", $owg_channel[$i], $vval,$hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR}); - $value2 .= sprintf( "%s: %5.2f %s ", $owg_channel[$i], $vval,$hash->{READINGS}{"$owg_channel[$i]"}{UNITABBR}); - $value3 .= sprintf( "%s: " , $owg_channel[$i]); - #-- Test for alarm condition - #-- alarm signature low - if( $owg_slow[$i] == 0 ) { - #$value2 .= " "; - $value3 .= "-"; - } else { - if( $vval > $vlow ){ - $owg_slow[$i] = 1; - $value2 .= $stateal0; - $value3 .= $stateal0; - } else { - $galarm = 1; - $owg_slow[$i] = 2; - $value2 .= $stateal1; - $value3 .= $stateal1; - } - } - #-- alarm signature high - if( $owg_shigh[$i] == 0 ) { - #$value2 .= " "; - $value3 .= "-"; - } else { - if( $vval < $vhigh ){ - $owg_shigh[$i] = 1; - $value2 .= $stateah0; - $value3 .= $stateah0; - } else { - $galarm = 1; - $owg_shigh[$i] = 2; - $value2 .= $stateah1; - $value3 .= $stateah1; - } - } + #-- skip a few things when the values are undefined or zero + if( !defined($owg_val[$i]) ){ + $svalue .= "$owg_channel[$i]: ???" + }else{ + if( $owg_val[$i] eq "" ){ + $svalue .= "$owg_channel[$i]: ???" + }else{ + + #-- when offset and scale factor are defined, we cannot have a function and vice versa + if( defined($attr{$name}{$owg_fixed[$i]."Offset"}) & defined($attr{$name}{$owg_fixed[$i]."Factor"}) ){ + my $offset = $attr{$name}{$owg_fixed[$i]."Offset"}; + my $factor = $attr{$name}{$owg_fixed[$i]."Factor"}; + $vfunc = "$factor*(V$owg_fixed[$i] + $offset)"; + #-- attribute VFunction defined + } elsif (defined($attr{$name}{$owg_fixed[$i]."Function"})){ + $vfunc = $attr{$name}{$owg_fixed[$i]."Function"}; + } else { + $vfunc = "V$owg_fixed[$i]"; + } + $hash->{tempf}{"$owg_fixed[$i]"}{function} = $vfunc; + + #-- replace by proper values (VA -> $owg_val[0] etc.) + for( my $k=0;$k{READINGS}{"$owg_channel[$i]"}{UNITABBR}); + + #-- alarm + my $alarm = defined($attr{$name}{$owg_fixed[$i]."Alarm"}) ? $attr{$name}{$owg_fixed[$i]."Alarm"} : "none"; + my $vlow = defined($attr{$name}{$owg_fixed[$i]."Low"}) ? $attr{$name}{$owg_fixed[$i]."Low"} : 0.0; + my $vhigh = defined($attr{$name}{$owg_fixed[$i]."High"}) ? $attr{$name}{$owg_fixed[$i]."High"} : 5.0; + if( $alarm eq "low" || $alarm eq "both" ){ + $owg_slow[$i]=1; + } + if( $alarm eq "high" || $alarm eq "both" ){ + $owg_shigh[$i]=1; + }; + #-- this needs to be fixed => HOW ??? + $owg_vlow[$i] = $vlow; + $owg_vhigh[$i] = $vhigh; + + #-- Test for alarm condition + #-- alarm signature low + if( $owg_slow[$i] == 0 ) { + } else { + if( $vval > $vlow ){ + $owg_slow[$i] = 1; + $svalue .= $stateal0; + } else { + $galarm = 1; + $owg_slow[$i] = 2; + $svalue .= $stateal1; + } + } + #-- alarm signature high + if( $owg_shigh[$i] == 0 ) { + } else { + if( $vval < $vhigh ){ + $owg_shigh[$i] = 1; + $svalue .= $stateah0; + } else { + $galarm = 1; + $owg_shigh[$i] = 2; + $svalue .= $stateah1; + } + } + + #-- put into READINGS + readingsBulkUpdate($hash,"$owg_channel[$i]",$vval); + readingsBulkUpdate($hash,"$owg_channel[$i]Low",$vlow); + readingsBulkUpdate($hash,"$owg_channel[$i]High",$vhigh); + } + } + #-- insert space if( $i{STATE} = $value2; - #-- alarm - $hash->{ALARM} = $galarm; - $hash->{READINGS}{alarms}{VAL} = $value3; - $hash->{READINGS}{alarms}{TIME} = $tn; - return $value1; + readingsBulkUpdate($hash,"state",$svalue); + readingsEndUpdate($hash,1); + + return $svalue; } ######################################################################################## @@ -451,6 +466,7 @@ sub OWAD_Get($@) { my $reading = $a[1]; my $name = $hash->{NAME}; my $model = $hash->{OW_MODEL}; + my $interface= $hash->{IODev}->{TYPE}; my ($value,$value2,$value3) = (undef,undef,undef); my $ret = ""; my $offset; @@ -489,7 +505,6 @@ sub OWAD_Get($@) { $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" ){ @@ -507,7 +522,7 @@ sub OWAD_Get($@) { return "OWAD: Could not get values from device $name"; } $hash->{PRESENT} = 1; - return "OWAD: $name.$reading => ".OWAD_FormatValues($hash); + return "OWAD: $name.reading => ".OWAD_FormatValues($hash); } #-- get alarm values according to interface type @@ -530,17 +545,17 @@ sub OWAD_Get($@) { $hash->{PRESENT} = 1; OWAD_FormatValues($hash); - #-- output string looks differently here + #-- assemble ouput string $value = ""; for (my $i=0;$i{READINGS}{$owg_channel[$i]."Low"}{VAL}, $hash->{READINGS}{$owg_channel[$i]."High"}{VAL}; } - return "OWAD: $name.$reading => $value"; + return "OWAD: $name.alarm => $value"; } - #-- get status values according to interface type + #-- get status values according to interface type if($a[1] eq "status") { #-- OWX interface if( $interface eq "OWX" ){ @@ -559,8 +574,35 @@ sub OWAD_Get($@) { } $hash->{PRESENT} = 1; OWAD_FormatValues($hash); - return "OWAD: $name.$reading => ".$hash->{READINGS}{alarms}{VAL}; + + #-- assemble output string + $value = ""; + for (my $i=0;$i ".$value; } + } ####################################################################################### @@ -576,6 +618,7 @@ sub OWAD_GetValues($) { my $name = $hash->{NAME}; my $model = $hash->{OW_MODEL}; + my $interface= $hash->{IODev}->{TYPE}; my $value = ""; my $ret = ""; my $offset; @@ -593,7 +636,6 @@ sub OWAD_GetValues($) { $hash->{PRESENT} = 0; #-- Get readings, alarms and stati according to interface type - my $interface= $hash->{IODev}->{TYPE}; if( $interface eq "OWX" ){ $ret = OWXAD_GetPage($hash,"reading"); $ret = OWXAD_GetPage($hash,"alarm"); @@ -606,21 +648,12 @@ sub OWAD_GetValues($) { #-- process results if( defined($ret) ){ - return "OWAD: Could not get values from device $name"; + return "OWAD: Could not get values from device $name, reason $ret"; } $hash->{PRESENT} = 1; - - #-- old state, new state - my $oldval = $hash->{STATE}; + $value=OWAD_FormatValues($hash); - my $newval = $hash->{STATE}; - #--logging depends on setting of the event-attribute Log 5, $value; - my $ev = defined($attr{$name}{"event"}) ? $attr{$name}{"event"} : "on-update"; - if( ($ev eq "on-update") || (($ev eq "on-change") && ($newval ne $oldval)) ){ - $hash->{CHANGED}[0] = $value; - DoTrigger($name, undef); - } return undef; } @@ -728,24 +761,24 @@ sub OWAD_Set($@) { 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"}; + #$offset = $attr{$name}{$owg_fixed[$channo]."Offset"}; + #$factor = $attr{$name}{$owg_fixed[$channo]."Factor"}; #-- find upper and lower boundaries for given offset/factor my $mmin = 0.0; - $mmin += $offset if ( $offset ); - $mmin *= $factor if ( $factor ); + #$mmin += $offset if ( $offset ); + #$mmin *= $factor if ( $factor ); my $mmax = $owg_range[$channo]/1000; - $mmax += $offset if ( $offset ); - $mmax *= $factor if ( $factor ); + #$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 ); + #$value /= $factor if ( $factor ); + #$value -= $offset if ( $offset ); #-- round to those numbers understood by the device my $value2 = int($value*255000/$owg_range[$channo])*$owg_range[$channo]/255000; @@ -842,7 +875,7 @@ sub OWXAD_GetPage($$) { #-- issue the match ROM command \x55 and the start conversion command $res= OWX_Complex($master,$owx_dev,"\x3C\x0F\x00\xFF\xFF",0); if( $res eq 0 ){ - return "OWXAD: Device $owx_dev not accessible for conversion"; + return "not accessible for conversion"; } #-- conversion needs some 5 ms per channel select(undef,undef,undef,0.02); @@ -862,47 +895,46 @@ sub OWXAD_GetPage($$) { $select="\xAA\x08\x00"; #=============== wrong value requested =============================== } else { - return "OWXAD: Wrong memory page requested"; + return "wrong memory page requested"; } #-- reset the bus OWX_Reset($master); #-- reading 9 + 3 + 8 data bytes and 2 CRC bytes = 22 bytes $res=OWX_Complex($master,$owx_dev,$select,10); - #Log 1, "OWXAD: Device $owx_dev returns data of length ".length($res); if( $res eq 0 ){ - return "OWXAD: Device $owx_dev not accessible in reading $page page"; + return "not accessible in reading $page page"; } #-- reset the bus OWX_Reset($master); #-- process results - @data=split(//,$res); - return "OWXAD: invalid data length, ".int(@data)." bytes" - if (@data != 22); + @data=split(//,substr($res,9)); + return "invalid data length, ".int(@data)." instead of 13 bytes" + if (@data != 13); #return "invalid data" # if (ord($data[17])<=0); - #return "invalid CRC" - # if (OWX_CRC8(substr($res,10,8),$data[18])==0); + return "invalid CRC" + if (OWX_CRC16(substr($res,9,11),$data[11],$data[12])==0); #=============== get the voltage reading =============================== if( $page eq "reading"){ for( $i=0;$i 0 ) ? 4 : 0; - $sb2 += ( $owg_shigh[$i] > 0 ) ? 8 : 0; + #-- alarm enabled + if( defined($owg_slow[$i]) ){ + $sb2 = ( $owg_slow[$i] ne 0 ) ? 4 : 0; + } + if( defined($owg_shigh[$i]) ){ + $sb2 += ( $owg_shigh[$i] ne 0 ) ? 8 : 0; + } #-- range $sb2 |= 1 if( $owg_range[$i] > 2550 ); @@ -1038,143 +1055,126 @@ sub OWXAD_SetPage($$) { =pod =begin html - -

OWAD

-
    FHEM module to commmunicate with 1-Wire A/D converters

    Note:
    This - 1-Wire module so far works only with the OWX interface module. Please define an OWX device first.
    -
    Example
    -
      - define OWX_AD OWAD 724610000000 45 -
      - attr OWX_AD DAlarm high -
      - attr OWX_AD DFactor 31.907097 -
      - attr OWX_AD DHigh 50.0 -
      - attr OWX_AD DName relHumidity|humidity -
      - attr OWX_AD DOffset -0.8088 -
      - attr OWX_AD DUnit percent|% -
      -

    - - Define -
      - define <name> OWAD [<model>] <id> [<interval>] -

      Define a 1-Wire A/D converter.

      -
    • - [<model>]
      Defines the A/D converter model (and thus - 1-Wire family id), currently the following values are permitted:
        -
      • model DS2450 with family id 20 (default if the model parameter is - omitted)
      • -
      -
    • -
    • - <id> -
      12-character unique ROM id of the converter device without family id and - CRC code
    • -
    • - <interval> -
      Measurement interval in seconds. The default is 300 seconds.
    • -
      -
    -
    - - Set - -
    - - Get - -
    - - Attributes -
      -
    • attr <name> stateAL0 - <string> -
      character string for denoting low normal condition, default is green down - triangle, e.g. the code <span - style="color:green">&#x25BE;</span> leading to the sign -
    • -
    • attr <name> stateAH0 - <string> -
      character string for denoting high alarm condition, default is green - upward triangle, e.g. the code <span - style="color:green">&#x25B4;</span> leading to the sign -
    • -
    • attr <name> stateAL1 - <string> -
      character string for denoting low alarm condition, default is red down - triangle, e.g. the code <span style="color:red">&#x25BE;</span> - leading to the sign
    • -
    • attr <name> stateAH1 - <string> -
      character string for denoting high alarm condition, default is red upward - triangle, e.g. the code <span style="color:red">&#x25B4;</span> - leading to the sign -
    • -
    For each of the following attributes, the channel identification A,B,C,D may be - used.
      -
    • attr <name> <channel>Name - <string>|<string> -
      name for the channel | a type description for the measured value.
    • -
    • attr <name> <channel>Unit - <string>|<string> -
      unit of measurement for this channel | its abbreviation.
    • -
    • attr <name> <channel>Offset - <float> -
      offset added to the reading in this channel.
    • -
    • attr <name> <channel>Factor - <float> -
      factor multiplied to (reading+offset) in this channel.
    • -
    • attr <name> <channel>Alarm - <string> -
      alarm setting in this channel, either both, low, high or none (default).
    • -
    • attr <name> <channel>Low - <float> -
      measurement value (on the scale determined by offset and factor) for low - alarm.
    • -
    • attr <name> <channel>High - <float> -
      measurement value (on the scale determined by offset and factor) for high - alarm.
    • -
    • attr <name> event on-change|on-update - This attribte work similarly, but not identically to the standard event-on-update-change/event-on-update-reading attribute. -
      • event on-update (default) will write a notify/FileLog event any time a measurement is received.
      • -
      • event on-change will write a notify/FileLog event only when a measurement is different from the previous one.
      • +

        FHEM module to commmunicate with 1-Wire A/D converters

        Note:
        This + 1-Wire module so far works only with the OWX interface module. Please define an OWX device first.

        +

        Example

        +

        + define OWX_AD OWAD 724610000000 45 +
        + attr OWX_AD DAlarm high +
        + attr OWX_AD DFactor 31.907097 +
        + attr OWX_AD DHigh 50.0 +
        + attr OWX_AD DName RelHumidity|humidity +
        + attr OWX_AD DOffset -0.8088 +
        + attr OWX_AD DUnit percent|% +
        +


        + +

        Define

        +

        + define <name> OWAD [<model>] <id> [<interval>] +

        Define a 1-Wire A/D converter.

        +
          +
        • + [<model>]
          Defines the A/D converter model (and thus 1-Wire + family id), currently the following values are permitted:
            +
          • model DS2450 with family id 20 (default if the model parameter is + omitted)
          -
        • -
        • Standard attributes alias, comment, eventMap, loglevel, webCmd
        • -
        -
      - +
    • +
    • + <id> +
      12-character unique ROM id of the converter device without family id and CRC + code
    • +
    • + <interval> +
      Measurement interval in seconds. The default is 300 seconds.
    • +
    +
    + +

    Set

    + +
    + +

    Get

    + +
    + +

    Attributes

    + For each of the following attributes, the channel identification A,B,C,D may be used. =end html =cut diff --git a/fhem/FHEM/21_OWID.pm b/fhem/FHEM/21_OWID.pm index 78f33f94c..b4ee3dabc 100644 --- a/fhem/FHEM/21_OWID.pm +++ b/fhem/FHEM/21_OWID.pm @@ -4,17 +4,11 @@ # # FHEM module to commmunicate with general 1-Wire ID-ROMS # -# Attention: This module may communicate with the OWX module, -# but currently not with the 1-Wire File System OWFS +# Prof. Dr. Peter A. Henning # -# Prefixes for subroutines of this module: -# OW = General 1-Wire routines Peter Henning) +# $Id$ # -# Prof. Dr. Peter A. Henning, 2012 -# -# Version 2.24 - October, 2012 -# -# Setup bus device in fhem.cfg as +######################################################################################## # # define OWID # @@ -49,7 +43,6 @@ ######################################################################################## package main; -#-- Prototypes to make komodo happy use vars qw{%attr %defs}; use strict; use warnings; @@ -136,18 +129,18 @@ sub OWID_Define ($$) { #-- 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})); - + if( !defined($hash->{IODev}->{NAME}) | !defined($hash->{IODev}) | ($hash->{IODev}->{PRESENT} != 1) ){ + return "OWID: Warning, no 1-Wire I/O device found for $name."; + } $modules{OWID}{defptr}{$id} = $hash; - - $hash->{STATE} = "Defined"; - Log 3, "OWID: Device $name defined."; + #-- + readingsSingleUpdate($hash,"state","Defined",1); + Log 3, "OWTHERM: Device $name defined."; #-- Initialization reading according to interface type my $interface= $hash->{IODev}->{TYPE}; - - $hash->{STATE} = "Initialized"; + #-- + readingsSingleUpdate($hash,"state","Initialized",1); return undef; } @@ -213,41 +206,39 @@ sub OWID_Undef ($) { =pod =begin html - - -

    OWID

    -
      FHEM module for 1-Wire devices that know only their unique ROM ID
      -
      Note:
      This 1-Wire module so far works only with the OWX interface module. - Please define an OWX device first.
      -
      Example
      -
        - define ROM1 OWX_ID OWCOUNT CE780F000000 + +

        OWID

        +

        FHEM module for 1-Wire devices that know only their unique ROM ID
        +
        Note:
        This 1-Wire module so far works only with the OWX interface module. + Please define an OWX device first.

        +

        Example


        +

        + define ROM1 OWX_ID OWCOUNT CE780F000000 +
        +


        + +

        Define

        +

        + define <name> OWID <id> +

        Define a 1-Wire device.

        +

        +
          +
        • + <id> +
          12-character unique ROM id of the converter device without family id and CRC + code
        • +

        -

      - - Define -
        - define <name> OWID <id> -

        Define a 1-Wire device.

        -
      • - <id> -
        12-character unique ROM id of the converter device without family id and - CRC code
      • -
      -
      - - Get - -
      -
    - + +

    Get

    + =end html =cut diff --git a/fhem/FHEM/21_OWLCD.pm b/fhem/FHEM/21_OWLCD.pm index 0e37bf54c..900f07ae8 100644 --- a/fhem/FHEM/21_OWLCD.pm +++ b/fhem/FHEM/21_OWLCD.pm @@ -4,17 +4,11 @@ # # FHEM module to commmunicate with the 1-Wire LCD hardware # -# Attention: This module may communicate with the OWX module, -# but currently not with the 1-Wire File System OWFS +# Prof. Dr. Peter A. Henning # -# Prefixes for subroutines of this module: -# OW = General 1-Wire routines Peter Henning +# $Id$ # -# Prof. Dr. Peter A. Henning, 2012 -# -# Version 2.24 - October, 2012 -# -# Setup bus device in fhem.cfg as +######################################################################################## # # define OWLCD # @@ -62,7 +56,6 @@ ######################################################################################## package main; -#-- Prototypes to make komodo happy use vars qw{%attr %defs}; use strict; use warnings; @@ -171,13 +164,13 @@ sub OWLCD_Define ($$) { #-- Couple to I/O device AssignIoPort($hash); - Log 3, "OWLCD: Warning, no 1-Wire I/O device found for $name." - if(!defined($hash->{IODev}->{NAME})); - + if( !defined($hash->{IODev}->{NAME}) | !defined($hash->{IODev}) | ($hash->{IODev}->{PRESENT} != 1) ){ + return "OWLCD: Warning, no 1-Wire I/O device found for $name."; + } $modules{OWLCD}{defptr}{$id} = $hash; $hash->{STATE} = "Defined"; - Log 3, "OWLCD: Device $name defined."; + Log 3, "OWLCD: Device $name defined."; #-- Initialization reading according to interface type my $interface= $hash->{IODev}->{TYPE}; @@ -419,9 +412,10 @@ sub OWLCD_Set($@) { #-- set a single LCD line if($key eq "line") { + $value = OWXLCD_Trans($value); return "OWLCD: Wrong line number, choose 0..".$lcdlines if( ( 0 > $line ) || ($line > ($lcdlines-1)) ); - return "OWLCD: Wrong line length, must be < ".$lcdchars + return "OWLCD: Wrong line length, must be <= ".$lcdchars if( length($value) > $lcdchars ); #-- check value and write to device OWXLCD_SetLine($hash,$line,$value); @@ -907,20 +901,9 @@ sub OWXLCD_SetLine($$$) { $res2 = ""; $line = int($line); $msg = defined($msg) ? $msg : ""; - #-- replace umlaut chars for special codepage - $msg =~ s/ä/\x7B/g; - $msg =~ s/ö/\x7C/g; - $msg =~ s/ü/\x7E/g; - $msg =~ s/Ä/\x5B/g; - $msg =~ s/Ö/\x5C/g; - $msg =~ s/Ü/\x5E/g; - $msg =~ s/ß/\xBE/g; - #--take out degree sign - if( $msg =~ m/.*\°\;.*/ ) { - my @ma = split(/\°\;/,$msg); - $msg = $ma[0]."\x80".$ma[1]; - } + $msg = OWXLCD_Trans($msg); + #-- ID of the device, hash of the busmaster my $owx_dev = $hash->{ROM_ID}; my $master = $hash->{IODev}; @@ -986,6 +969,34 @@ sub OWXLCD_SetLine($$$) { } +######################################################################################## +# +# OWXLCD_Trans - String translation helper +# +# Parameter msg = data string to be written +# +######################################################################################## + +sub OWXLCD_Trans($) { + + my ($msg) = @_; + + #-- replace umlaut chars for special codepage + $msg =~ s/ä/\x7B/g; + $msg =~ s/ö/\x7C/g; + $msg =~ s/ü/\x7E/g; + $msg =~ s/Ä/\x5B/g; + $msg =~ s/Ö/\x5C/g; + $msg =~ s/Ü/\x5E/g; + $msg =~ s/ß/\xBE/g; + #--take out degree sign + if( $msg =~ m/.*\°\;.*/ ) { + my @ma = split(/\°\;/,$msg); + $msg = $ma[0]."\x80".$ma[1]; + } + return $msg; +} + ######################################################################################## # # OWXLCD_SetMemory - set internal nonvolatile memory @@ -1038,94 +1049,93 @@ sub OWXLCD_SetMemory($$$) { =pod =begin html - - -

    OWLCD

    - - + +

    Define

    +

    + define <name> OWLCD <id> +

    Define a 1-Wire LCD device.

    +
      +
    • + <id> +
      12-character unique ROM id of the converter device without family id and CRC + code
    • +
    +
    + +

    Set

    + +
    + +

    Get

    + +
    + +

    Attributes

    + =end html -=cut +=cut \ No newline at end of file diff --git a/fhem/FHEM/21_OWMULTI.pm b/fhem/FHEM/21_OWMULTI.pm index 142a06006..94cb7e2c1 100644 --- a/fhem/FHEM/21_OWMULTI.pm +++ b/fhem/FHEM/21_OWMULTI.pm @@ -4,15 +4,11 @@ # # FHEM module to commmunicate with 1-Wire chip DS2438Z - Smart Battery Monitor # -# Prefixes for subroutines of this module: -# OW = General 1-Wire routines (Martin Fischer, Peter Henning) -# OWX = 1-Wire bus master interface (Peter Henning) +# Prof. Dr. Peter A. Henning # -# Prof. Dr. Peter A. Henning, 2012 -# -# Version 2.24 - October, 2012 -# -# Setup bus device in fhem.cfg as +# $Id$ +# +######################################################################################## # # define OWMULTI [] [interval] # @@ -38,8 +34,6 @@ # Additional attributes are defined in fhem.cfg # Note: attributes "tempXXXX" are read during every update operation. # -# attr event on-change/on-update = when to write an event (default= on-update) -# # attr tempOffset = temperature offset in degree Celsius added to the raw temperature reading # attr tempUnit = unit of measurement, e.g. Celsius/Kelvin/Fahrenheit or C/K/F, default is Celsius # attr VName | = name for the channel | a type description for the measured value @@ -69,7 +63,6 @@ ######################################################################################## package main; -#-- Prototypes to make komodo happy use vars qw{%attr %defs}; use strict; use warnings; @@ -125,7 +118,7 @@ sub OWMULTI_Initialize ($) { #tempOffset = a temperature offset added to the temperature reading for correction #tempUnit = a unit of measure: C/F/K $hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 loglevel:0,1,2,3,4,5 ". - "event:on-update,on-change ". + "event-on-update-reading event-on-change-reading ". "tempOffset tempUnit:C,Celsius,F,Fahrenheit,K,Kelvin ". "VName VUnit VFunction"; } @@ -198,10 +191,12 @@ sub OWMULTI_Define ($$) { #-- Couple to I/O device AssignIoPort($hash); - Log 3, "OWMULTI: Warning, no 1-Wire I/O device found for $name." - if(!defined($hash->{IODev}->{NAME})); + if( !defined($hash->{IODev}->{NAME}) | !defined($hash->{IODev}) | ($hash->{IODev}->{PRESENT} != 1) ){ + return "OWMULTI: Warning, no 1-Wire I/O device found for $name."; + } $modules{OWMULTI}{defptr}{$id} = $hash; - $hash->{STATE} = "Defined"; + #-- + readingsSingleUpdate($hash,"state","defined",1); Log 3, "OWMULTI: Device $name defined."; #-- Start timer for initialization in a few seconds @@ -231,10 +226,10 @@ sub OWMULTI_InitializeDevice($) { $hash->{READINGS}{"temperature"}{UNIT} = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : "Celsius"; $hash->{READINGS}{"temperature"}{TYPE} = "temperature"; - #-- Initial readings temperature sensor - $owg_temp = 0.0; - $owg_volt = 0.0; - $owg_vdd = 5.0; + #-- Initial readings + $owg_temp = ""; + $owg_volt = ""; + $owg_vdd = ""; #-- Set channel name, channel unit for voltage channel my $cname = defined($attr{$name}{"VName"}) ? $attr{$name}{"VName"} : "voltage|voltage"; my @cnama = split(/\|/,$cname); @@ -275,9 +270,7 @@ sub OWMULTI_FormatValues($) { my $name = $hash->{NAME}; my ($tunit,$toffset,$tfactor,$tabbr,$tval,$vfunc,$vval); - my ($value1,$value2) = ("",""); - - my $tn = TimeNow(); + my $svalue = ""; #-- attributes defined ? $tunit = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : $hash->{READINGS}{"temperature"}{UNIT}; @@ -297,24 +290,23 @@ sub OWMULTI_FormatValues($) { $tabbr="?"; Log 1, "OWMULTI_FormatValues: unknown unit $tunit"; } - #-- these values are rather coplex to obtain, therefore save them in the hash + #-- these values are rather complex to obtain, therefore save them in the hash $hash->{READINGS}{"temperature"}{UNIT} = $tunit; $hash->{READINGS}{"temperature"}{UNITABBR} = $tabbr; $hash->{tempf}{offset} = $toffset; $hash->{tempf}{factor} = $tfactor; + #-- no change in any value if invalid reading + return if( $owg_temp eq ""); + #-- correct values for proper offset, factor $tval = ($owg_temp + $toffset)*$tfactor; - - #-- put into READINGS - $hash->{READINGS}{"temperature"}{VAL} = $tval; - $hash->{READINGS}{"temperature"}{TIME} = $tn; my $cname = defined($attr{$name}{"VName"}) ? $attr{$name}{"VName"} : "voltage|voltage"; my @cnama = split(/\|/,$cname); $owg_channel=$cnama[0]; - #-- attribute VFunction defined ? + #-- attribute VFunction defined ? $vfunc = defined($attr{$name}{"VFunction"}) ? $attr{$name}{"VFunction"} : "V"; #-- replace by proper values @@ -324,27 +316,30 @@ sub OWMULTI_FormatValues($) { #-- determine the measured value from the function $vfunc = "\$owg_vdd = $owg_vdd; \$owg_volt = $owg_volt; \$tval = $tval; ".$vfunc; + #Log 1, "vfunc= ".$vfunc; $vfunc = eval($vfunc); - if( $vfunc ne "" ){ + if( !$vfunc ){ + $vval = 0.0; + } elsif( $vfunc ne "" ){ $vval = int( $vfunc*1000 )/1000; } else { - $vval = 0.0; + } - #-- put into READINGS - $hash->{READINGS}{"$owg_channel"}{VAL} = $vval; - $hash->{READINGS}{"$owg_channel"}{TIME} = $tn; - $hash->{READINGS}{"VDD"}{VAL} = $owg_vdd; - $hash->{READINGS}{"VDD"}{TIME} = $tn; - #-- string buildup for return value, STATE - $value1 .= sprintf( "%s: %5.3f %s temperature %5.3f %s VDD %5.2f V", $owg_channel, $vval,$hash->{READINGS}{"$owg_channel"}{UNITABBR},$tval,$tabbr,$owg_vdd); - $value2 .= sprintf( "%s: %5.2f %s (T: %5.2f %s)", $owg_channel, $vval,$hash->{READINGS}{"$owg_channel"}{UNITABBR},$tval,$tabbr); - + $svalue .= sprintf( "%s: %5.2f %s (T: %5.2f %s)", $owg_channel, $vval,$hash->{READINGS}{"$owg_channel"}{UNITABBR},$tval,$tabbr); + + #-- put into READINGS + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"$owg_channel",$vval); + readingsBulkUpdate($hash,"VDD",$owg_vdd); + readingsBulkUpdate($hash,"temperature",$tval); + #-- STATE - $hash->{STATE} = $value2; + readingsBulkUpdate($hash,"state",$svalue); + readingsEndUpdate($hash,1); - return $value1; + return $svalue; } ######################################################################################## @@ -418,7 +413,7 @@ sub OWMULTI_Get($@) { #-- process results if( defined($ret) ){ - return "OWMULTI: Could not get values from device $name, return was $ret"; + return "OWMULTI: Could not get values from device $name, reason $ret"; } $hash->{PRESENT} = 1; OWMULTI_FormatValues($hash); @@ -475,7 +470,7 @@ sub OWMULTI_GetValues($@) { if( !defined($ret) ); } #}elsif( $interface eq "OWFS" ){ - # $ret = OWFSTHERM_GetValues($hash); + # $ret = OWFSMULTI_GetValues($hash); }else{ Log 3, "OWMULTI: GetValues with wrong IODev type $interface"; return 1; @@ -488,18 +483,9 @@ sub OWMULTI_GetValues($@) { } $hash->{PRESENT} = 1; - #-- old state, new state - my $oldval = $hash->{STATE}; $value=OWMULTI_FormatValues($hash); - my $newval = $hash->{STATE}; - #--logging depends on setting of the event-attribute Log 5, $value; - my $ev = defined($attr{$name}{"event"}) ? $attr{$name}{"event"} : "on-update"; - if( ($ev eq "on-update") || (($ev eq "on-change") && ($newval ne $oldval)) ){ - $hash->{CHANGED}[0] = $value; - DoTrigger($name, undef); - } - + return undef; } @@ -562,7 +548,7 @@ sub OWMULTI_Set($@) { $ret = OWXMULTI_SetValues($hash,@a); #-- OWFS interface not yet implemented #}elsif( $interface eq "OWFS" ){ - # $ret = OWFSTHERM_SetValues($hash,@a); + # $ret = OWFSMULTI_SetValues($hash,@a); # return $ret # if(defined($ret)); } else { @@ -671,31 +657,23 @@ sub OWXMULTI_GetValues($) { if( $res eq 0 ){ return "$owx_dev not accessible in 2nd step"; } - - # $res2 = "====> OWXMULTI Received "; - # for(my $i=0;$i DS2438 #-- temperature - my $lsb = ord($data[12]); - my $msb = ord($data[13]) & 127; - my $sign = ord($data[13]) & 128; + my $lsb = ord($data[3]); + my $msb = ord($data[4]) & 127; + my $sign = ord($data[4]) & 128; #-- test with -55 degrees #$lsb = 0; @@ -709,8 +687,8 @@ sub OWXMULTI_GetValues($) { } #-- voltage - $lsb = ord($data[14]); - $msb = ord($data[15]) & 3; + $lsb = ord($data[5]); + $msb = ord($data[6]) & 3; #-- test with 5V #$lsb = 244; @@ -756,35 +734,25 @@ sub OWXMULTI_GetValues($) { #-- issue the match ROM command \x55 and the read scratchpad command \xBE #-- reading 9 + 2 + 9 data bytes = 20 bytes $res=OWX_Complex($master,$owx_dev,"\xBE\x00",9); - #Log 1,"OWXMULTI: data length from reading device is ".length($res)." bytes"; #-- process results if( $res eq 0 ){ return "$owx_dev not accessible in 2nd step"; } - - # $res2 = "====> OWXMULTI Received "; - # for(my $i=0;$i DS2438 - #-- voltage - $lsb = ord($data[14]); - $msb = ord($data[15]) & 3; + $lsb = ord($data[5]); + $msb = ord($data[6]) & 3; #-- test with 7.2 V #$lsb = 208; @@ -845,118 +813,112 @@ sub OWXMULTI_SetValues($@) { return undef; } - - 1; =pod =begin html + +

    OWMULTI

    +

    FHEM module to commmunicate with 1-Wire multi-sensors, currently the DS2438 smart battery + monitor

    Note:
    This 1-Wire module so far works only with the OWX + interface module. Please define an OWX device first.

    +

    Example

    +

    + define OWX_M OWMULTI 7C5034010000 45 +
    + attr OWX_M VName relHumidity|humidity +
    + attr OWX_M VUnit percent|% +
    + attr OWX_M VFunction (161.29 * V / VDD - 25.8065)/(1.0546 - 0.00216 * T) +
    +


    + +

    Define

    +

    + define <name> OWMULTI [<model>] <id> [<interval>] +

    Define a 1-Wire multi-sensor

    +
      +
    • + [<model>]
      Defines the sensor model (and thus 1-Wire family + id), currently the following values are permitted:
        +
      • model DS2438 with family id 26 (default if the model parameter is omitted). + Measured is a temperature value, an external voltage and the current supply + voltage
      • +
      +
    • +
    • + <id> +
      12-character unique ROM id of the converter device without family id and CRC + code
    • +
    • + <interval> +
      Measurement interval in seconds. The default is 300 seconds.
    • +
    +
    + +

    Set

    + +
    + +

    Get

    + +
    + +

    Attributes

    + =end html -=cut +=cut \ No newline at end of file diff --git a/fhem/FHEM/21_OWSWITCH.pm b/fhem/FHEM/21_OWSWITCH.pm index 0c462b8e5..32dab9ead 100644 --- a/fhem/FHEM/21_OWSWITCH.pm +++ b/fhem/FHEM/21_OWSWITCH.pm @@ -4,22 +4,11 @@ # # FHEM module to commmunicate with 1-Wire adressable switches DS2413, DS206, DS2408 # -# Attention: This module may communicate with the OWX module, -# but currently not with the 1-Wire File System OWFS +# Prof. Dr. Peter A. Henning # -# TODO: Kanalattribute ändern zur Laufzeit. +# $Id$ # -# -# 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 2.25 - October, 2012 -# -# Setup bus device in fhem.cfg as +######################################################################################## # # define OWSWITCH [] [interval] # @@ -42,16 +31,17 @@ # get gpio => values for channels # # set interval => set period for measurement -# set output ON|OFF => set value for channel (name A, B or defined channel name) +# set output on|off|on-for-timer |on-for-timer +# => set value for channel (name A, B or defined channel name) # note: 1 = OFF, 0 = ON in normal usage. See also the note above +# ON-for-timer/OFF-for-timer will set the desired value only for seconds +# and then will return to the opposite value. # set gpio value => set values for channels (3 = both OFF, 1 = B ON 2 = A ON 0 = both ON) # set init yes => re-initialize device # # Additional attributes are defined in fhem.cfg, in some cases per channel, where =A,B # Note: attributes are read only during initialization procedure - later changes are not used. # -# attr event on-change/on-update = when to write an event (default= on-update) -# # attr stateS = character string denoting external shortening condition, default is (ext) # overwritten by an attribute setting "red angled arrow downwward" # @@ -78,7 +68,6 @@ ######################################################################################## package main; -#-- Prototypes to make komodo happy use vars qw{%attr %defs}; use strict; use warnings; @@ -140,7 +129,8 @@ sub OWSWITCH_Initialize ($) { $hash->{SetFn} = "OWSWITCH_Set"; my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2413,DS2406,DS2408 loglevel:0,1,2,3,4,5 ". - "event:on-update,on-change stateS "; + "event-on-update-reading event-on-change-reading ". + "stateS "; #TODO: correct number of channels @@ -221,17 +211,19 @@ sub OWSWITCH_Define ($$) { #-- Couple to I/O device AssignIoPort($hash); - Log 3, "OWSWITCH: Warning, no 1-Wire I/O device found for $name." - if(!defined($hash->{IODev}->{NAME})); + if( !defined($hash->{IODev}->{NAME}) | !defined($hash->{IODev}) | ($hash->{IODev}->{PRESENT} != 1) ){ + return "OWSWITCH: Warning, no 1-Wire I/O device found for $name."; + } $modules{OWSWITCH}{defptr}{$id} = $hash; - $hash->{STATE} = "Defined"; - Log 3, "OWSWITCH: Device $name defined."; + #-- + readingsSingleUpdate($hash,"state","defined",1); + Log 3, "OWSWITCH: Device $name defined."; #-- Initialization reading according to interface type my $interface= $hash->{IODev}->{TYPE}; #-- Start timer for initialization in a few seconds - InternalTimer(time()+1, "OWSWITCH_InitializeDevice", $hash, 0); + InternalTimer(time()+10, "OWSWITCH_InitializeDevice", $hash, 0); #-- Start timer for updates InternalTimer(time()+$hash->{INTERVAL}, "OWSWITCH_GetValues", $hash, 0); @@ -251,16 +243,12 @@ sub OWSWITCH_InitializeDevice($) { my ($hash) = @_; my $name = $hash->{NAME}; - - #-- more colorful shortening signature - CommandAttr (undef,"$name stateS ") - if( !defined($attr{$name}{"stateS"} )); - + #-- Set channel names, channel units for( my $i=0;$i<$cnumber{$attr{$name}{"model"}} ;$i++) { - #-- Initial readings OFF + #-- Initial readings ERR $owg_val[$i] = 1; - $owg_vax[$i] = 1; + $owg_vax[$i] = 0; #-- name my $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : $owg_fixed[$i]."|onoff"; my @cnama = split(/\|/,$cname); @@ -315,13 +303,14 @@ sub OWSWITCH_FormatValues($) { my ($hash) = @_; my $name = $hash->{NAME}; - my ($offset,$factor,$vval,$vvax,$vstr,$cname,@cnama,@unarr); - my ($value1,$value2,$value3) = ("","",""); - - my $tn = TimeNow(); + my ($offset,$factor,$vval,$vvax,$vstr,$cname,@cnama,@unarr,$valid); + my $svalue = ""; #-- external shortening signature - my $sname = defined($attr{$name}{"stateS"}) ? $attr{$name}{"stateS"} : "(ext)"; + my $sname = defined($attr{$name}{"stateS"}) ? $attr{$name}{"stateS"} : "☇"; + + #-- put into READINGS + readingsBeginUpdate($hash); #-- formats for output for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ @@ -338,28 +327,28 @@ sub OWSWITCH_FormatValues($) { @unarr= split(/\|/,$hash->{READINGS}{"$owg_channel[$i]"}{UNIT}); $vstr = $unarr[$vval]; - $vstr .= $sname if( ($vval == 0) && ($vvax == 1) ); - $vstr = "ERR" if( ($vval == 1) && ($vvax == 0) ); - $value1 .= sprintf( "%s: %s", $owg_channel[$i], $vstr); - $value2 .= sprintf( "%s: %s ", $owg_channel[$i], $vstr); - $value3 .= sprintf( "%s: " , $owg_channel[$i]); - - #-- put into READINGS - $hash->{READINGS}{"$owg_channel[$i]"}{VAL} = $vstr; - $hash->{READINGS}{"$owg_channel[$i]"}{TIME} = $tn; - - #-- insert comma - if( $i<$cnumber{$attr{$name}{"model"}}-1 ){ - $value1 .= " "; - $value2 .= ", "; - $value3 .= ", "; + #-- put into readings only when valid + if( ($vval == 1) && ($vvax == 0) ){ + $vstr ="???" + }else{ + $vstr.= $sname if( ($vval == 0) && ($vvax == 1) ); + readingsBulkUpdate($hash,"$owg_channel[$i]",$vstr); + } + $svalue .= sprintf( "%s: %s" , $owg_channel[$i], $vstr); + + #-- insert space + if( $i<($cnumber{$attr{$name}{"model"}}-1) ){ + $svalue .= " "; } + } + #-- STATE - $hash->{STATE} = $value2; + readingsBulkUpdate($hash,"state",$svalue); + readingsEndUpdate($hash,1); - return $value1; + return $svalue; } ######################################################################################## @@ -463,7 +452,7 @@ sub OWSWITCH_Get($@) { } #-- process results if( defined($ret) ){ - return "OWSWITCH: Could not get values from device $name"; + return "OWSWITCH: Could not get values from device $name, reason $ret"; } $hash->{PRESENT} = 1; return "OWSWITCH: $name.$reading => ".OWSWITCH_FormatValues($hash); @@ -498,29 +487,32 @@ sub OWSWITCH_GetValues($) { #-- Get readings according to interface type my $interface= $hash->{IODev}->{TYPE}; if( $interface eq "OWX" ){ - $ret = OWXSWITCH_GetState($hash); + #-- max 3 tries + for(my $try=0; $try<3; $try++){ + $ret = OWXSWITCH_GetState($hash); + last + if( !defined($ret) ); + } #}elsif( $interface eq "OWFS" ){ # $ret = OWFSSWITCH_GetValues($hash); }else{ - return "OWSWITCH: GetValues with wrong IODev type $interface"; + Log 3, "OWSWITCH: GetValues with wrong IODev type $interface"; + return 1; } #-- process results if( defined($ret) ){ - return "OWSWITCH: Could not get values from device $name"; + for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ + $owg_val[$i] = 1; + $owg_vax[$i] = 0; + } + Log 3, "OWSWITCH: Could not get values from device $name, reason $ret"; + return 1; } $hash->{PRESENT} = 1; - #-- old state, new state - my $oldval = $hash->{STATE}; - $value=OWSWITCH_FormatValues($hash); - my $newval = $hash->{STATE}; - #--logging depends on setting of the event-attribute + + $value = OWSWITCH_FormatValues($hash); Log 5, $value; - my $ev = defined($attr{$name}{"event"}) ? $attr{$name}{"event"} : "on-update"; - if( ($ev eq "on-update") || (($ev eq "on-change") && ($newval ne $oldval)) ){ - $hash->{CHANGED}[0] = $value; - DoTrigger($name, undef); - } return undef; } @@ -578,7 +570,6 @@ sub OWSWITCH_Set($@) { InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWSWITCH_GetValues", $hash, 1); return undef; } - #-- Set readings according to interface type my $interface= $hash->{IODev}->{TYPE}; @@ -598,16 +589,40 @@ sub OWSWITCH_Set($@) { } return "OWSWITCH: invalid output address, must be A,B,... or defined channel name" if( !defined($fnd) ); + #-- prepare gpio value my $nval; + my $ntim; + my $nstr=""; if( lc($a[3]) eq "on" ){ $nval = 0; }elsif( lc($a[3]) eq "off" ){ $nval = 1; + }elsif( lc($a[3]) =~ m/for-timer/ ){ + if( !($a[4] =~ m/\d\d\:\d\d\:\d\d/) ){ + if( !($a[4] =~ m/\d{1,4}/ )){ + return "OWSWITCH: Wrong data value $a[4], must be time format xx:xx:zz or integer"; + } else { + $ntim = sprintf("%02d:%02d:%02d",int($a[4]/3600),int( ($a[4] % 3600)/60 ),$a[4] %60); + } + } else { + $ntim= $a[4]; + } + if( lc($a[3]) eq "on-for-timer" ){ + $nval = 0; + $nstr = "$a[0] $a[1] $a[2] off"; + }elsif( lc($a[3]) eq "off-for-timer" ){ + $nval = 1; + $nstr = "$a[0] $a[1] $a[2] on"; + } }else{ - return "OWSWITCH: Wrong data value $a[3], must be ON or OFF"; + return "OWSWITCH: Wrong data value $a[3], must be on, off, on-for-timer or off-for-timer"; } - + + if ($nstr ne ""){ + fhem("define ".$a[0].".".$owg_fixed[$fnd]."Timer at +".$ntim." set ".$nstr); + } + #-- OWX interface if( $interface eq "OWX" ){ $ret = OWXSWITCH_GetState($hash); @@ -708,8 +723,70 @@ sub OWXSWITCH_GetState($) { my ($i,$j,$k); + #-- family = 12 => DS2406 + if( $hash->{OW_FAMILY} eq "12" ) { + #=============== get gpio values =============================== + #-- issue the match ROM command \x55 and the access channel command + # \xF5 plus the two byte channel control and the value + #-- reading 9 + 3 + 1 data bytes + 2 CRC bytes = 15 bytes + $select=sprintf("\xF5\xDD\xFF"); + #-- reset the bus + OWX_Reset($master); + #-- read the data + $res=OWX_Complex($master,$owx_dev,$select,4); + if( $res eq 0 ){ + return "not accessible in reading"; + } + + #-- reset the bus + OWX_Reset($master); + + #-- process results + @data=split(//,substr($res,9)); + return "invalid data length, ".int(@data)." instead of 7 bytes" + if (@data != 7); + return "invalid CRC" + if ( OWX_CRC16(substr($res,9,5),$data[5],$data[6]) == 0); + + $owg_val[0] = (ord($data[3])>>2) & 1; + $owg_vax[0] = ord($data[3]) & 1; + $owg_val[1] = (ord($data[3])>>3) & 1; + $owg_vax[1] = (ord($data[3])>>1) & 1; + + #-- family = 29 => DS2408 + }elsif( $hash->{OW_FAMILY} eq "29" ) { + #=============== get gpio values =============================== + #-- issue the match ROM command \x55 and the read PIO rtegisters command + # \xF5 plus the two byte channel target address + #-- reading 9 + 3 + 8 data bytes + 2 CRC bytes = 22 bytes + $select=sprintf("\xF0\x88\x00"); + #-- reset the bus + OWX_Reset($master); + #-- read the data + $res=OWX_Complex($master,$owx_dev,$select,10); + if( $res eq 0 ){ + return "not accessible in reading"; + } + + #-- reset the bus + OWX_Reset($master); + + #-- process results + @data=split(//,substr($res,9)); + return "invalid data length, ".int(@data)." instead of 13 bytes" + if (@data != 13); + return "invalid data" + if (ord($data[9])!=255); + return "invalid CRC" + if( OWX_CRC16(substr($res,9,11),$data[11],$data[12]) == 0); + + for(my $i=0;$i<8;$i++){ + $owg_val[$i] = (ord($data[2])>>$i) & 1; + $owg_vax[$i] = (ord($data[3])>>$i) & 1; + } + #-- family = 3A => DS2413 - if( $hash->{OW_FAMILY} eq "3A" ) { + }elsif( $hash->{OW_FAMILY} eq "3A" ) { #=============== get gpio values =============================== #-- issue the match ROM command \x55 and the read gpio command # \xF5 plus 2 empty bytes @@ -718,79 +795,35 @@ sub OWXSWITCH_GetState($) { #-- read the data $res=OWX_Complex($master,$owx_dev,"\xF5",2); if( $res eq 0 ){ - return "OWXSWITCH: Device $owx_dev not accessible in reading"; + return "not accessible in reading"; } - #-- family = 12 => DS2406 - }elsif( $hash->{OW_FAMILY} eq "12" ) { - #=============== get gpio values =============================== - #-- issue the match ROM command \x55 and the access channel command - # \xF5 plus the two byte channel control and the value - $select=sprintf("\xF5\xDC\xFF"); - #-- reset the bus - OWX_Reset($master); - #-- read the data - $res=OWX_Complex($master,$owx_dev,$select,1); - if( $res eq 0 ){ - return "OWXSWITCH: Device $owx_dev not accessible in writing"; - } - #-- family = 29 => DS2408 - }elsif( $hash->{OW_FAMILY} eq "29" ) { - #=============== get gpio values =============================== - #-- issue the match ROM command \x55 and the read PIO rtegisters command - # \xF5 plus the two byte channel target address - #-- reading 9 + 3 + 10 data bytes = 22 bytes - $select=sprintf("\xF0\x88\x00"); - #-- reset the bus - OWX_Reset($master); - #-- read the data - $res=OWX_Complex($master,$owx_dev,$select,10); - if( $res eq 0 ){ - return "OWXSWITCH: Device $owx_dev not accessible in writing"; - } - } else { - return "OWXSWITCH: Unknown device family $hash->{OW_FAMILY}\n"; - } - - #-- process results - @data=split(//,substr($res,10)); - #return "invalid data length" - # if (@data != 22); - #return "invalid data" - # if (ord($data[17])<=0); - #return "invalid CRC" - # if (OWX_CRC8(substr($res,10,8),$data[18])==0); - - #-- reset the bus - OWX_Reset($master); - - # note: value 1 corresponds to OFF, 0 to ON normally - # note: val = input value, vax = output value - #-- family = 3A => DS2413 - if( $hash->{OW_FAMILY} eq "3A" ) { - $owg_val[0] = ord($data[0]) & 1; - $owg_vax[0] = (ord($data[0])>>1) & 1; - $owg_val[1] = (ord($data[0])>>2) & 1; - $owg_vax[1] = (ord($data[0])>>3) & 1; - #-- family = 12 => DS2406 - }elsif( $hash->{OW_FAMILY} eq "12" ) { - $owg_val[0] = (ord($data[2])>>2) & 1; - $owg_vax[0] = ord($data[2]) & 1; - $owg_val[1] = (ord($data[2])>>3) & 1; - $owg_vax[1] = (ord($data[2])>>1) & 1; - #-- family = 29 => DS2408 - }elsif( $hash->{OW_FAMILY} eq "29" ) { - for(my $i=0;$i<8;$i++){ - $owg_val[$i] = (ord($data[2])>>$i) & 1; - $owg_vax[$i] = (ord($data[3])>>$i) & 1; - } + #-- reset the bus + OWX_Reset($master); + + #-- process results + @data=split(//,substr($res,9)); + return "invalid data length, ".int(@data)." instead of 3 bytes" + if (@data != 3); + return "invalid data" + if ( (15- (ord($data[1])>>4)) != (ord($data[1]) & 15) ); + + # note: value 1 corresponds to OFF, 0 to ON normally + # note: val = input value, vax = output value + $owg_val[0] = ord($data[1]) & 1; + $owg_vax[0] = (ord($data[1])>>1) & 1; + $owg_val[1] = (ord($data[1])>>2) & 1; + $owg_vax[1] = (ord($data[1])>>3) & 1; + + } else { + return "unknown device family $hash->{OW_FAMILY}\n"; } return undef } ######################################################################################## # -# OWXSWITCH_SetPage - Set gpio ports of device +# OWXSWITCH_SetState - Set gpio ports of device # # Parameter hash = hash of device addressed # value = integer value for device outputs @@ -814,31 +847,20 @@ sub OWXSWITCH_SetState($$) { my ($i,$j,$k); - #-- family = 3A => DS2413 - if( $hash->{OW_FAMILY} eq "3A" ) { - #=============== set gpio values =============================== - #-- issue the match ROM command \x55 and the write gpio command - # \x5A plus the value byte and its complement - $select=sprintf("\x5A%c%c",252+$value,3-$value); - #-- reset the bus - OWX_Reset($master); - #-- read the data - $res=OWX_Complex($master,$owx_dev,$select,1); - if( $res eq 0 ){ - return "OWXSWITCH: Device $owx_dev not accessible in writing"; - } + #-- family = 12 => DS2406 - }elsif( $hash->{OW_FAMILY} eq "12" ) { + if( $hash->{OW_FAMILY} eq "12" ) { #=============== set gpio values =============================== # Writing the output state via the access channel command does # not work contrary to documentation. Using the write status command #-- issue the match ROM command \x55 and the read status command # \xAA at address TA1 = \x07 TA2 = \x00 + #-- reading 9 + 3 + 1 data bytes + 2 CRC bytes = 15 bytes #-- reset the bus OWX_Reset($master); #-- read the data - $res = OWX_Complex($master,$owx_dev,"\xAA\x07\x00",1); - my $stat = substr($res,10,1); + $res = OWX_Complex($master,$owx_dev,"\xAA\x07\x00",3); + my $stat = ord(substr($res,10,1)); my $statneu = ( $stat & 159 ) | (($value<<5) & 96) ; #-- issue the match ROM command \x55 and the write status command # \x55 at address TA1 = \x07 TA2 = \x00 @@ -851,10 +873,23 @@ sub OWXSWITCH_SetState($$) { if( $res eq 0 ){ return "OWXSWITCH: Device $owx_dev not accessible in writing"; } + #-- reset the bus + OWX_Reset($master); + + #-- process results + @data=split(//,substr($res,9)); + + #-- very crude check - should be CRC + if( int(@data) != 6){ + return "OWXSWITCH: State could not be set for device $owx_dev"; + } + + #-- put into local buffer $owg_val[0] = $value % 2; $owg_vax[0] = $owg_val[0]; $owg_val[1] = int($value / 2); $owg_vax[1] = $owg_val[1]; + #-- family = 29 => DS2408 }elsif( $hash->{OW_FAMILY} eq "29" ) { #=============== set gpio values =============================== @@ -868,34 +903,44 @@ sub OWXSWITCH_SetState($$) { if( $res eq 0 ){ return "OWXSWITCH: Device $owx_dev not accessible in writing"; } - - } else { - return "OWXSWITCH: Unknown device family $hash->{OW_FAMILY}\n"; - } - #-- reset the bus - OWX_Reset($master); - - #-- process results - @data=split(//,substr($res,10)); - - #-- family = 3A => DS2413 - if( $hash->{OW_FAMILY} eq "3A" ) { - if( $data[2] ne "\xAA"){ - return "OWXSWITCH: State could not be set for device $owx_dev"; - } - #-- family = 12 => DS2406 - }elsif( $hash->{OW_FAMILY} eq "12" ) { - #-- very crude check - should be CRC - if( int(@data) != 5){ - return "OWXSWITCH: State could not be set for device $owx_dev"; - } - #-- family = 29 => DS2408 - }elsif( $hash->{OW_FAMILY} eq "29" ) { + + #-- process results + @data=split(//,substr($res,10)); + if( $data[2] ne "\xAA"){ return "OWXSWITCH: State could not be set for device $owx_dev"; } - } - return undef + #-- reset the bus + OWX_Reset($master); + + #-- family = 3A => DS2413 + }elsif( $hash->{OW_FAMILY} eq "3A" ) { + #=============== set gpio values =============================== + #-- issue the match ROM command \x55 and the write gpio command + # \x5A plus the value byte and its complement + $select=sprintf("\x5A%c%c",252+$value,3-$value); + #-- reset the bus + OWX_Reset($master); + #-- read the data + $res=OWX_Complex($master,$owx_dev,$select,1); + if( $res eq 0 ){ + return "OWXSWITCH: Device $owx_dev not accessible in writing"; + } + #-- reset the bus + OWX_Reset($master); + + #-- process results + @data=split(//,substr($res,10)); + + if( $data[2] ne "\xAA"){ + return "OWXSWITCH: State could not be set for device $owx_dev"; + } + + }else { + return "OWXSWITCH: Unknown device family $hash->{OW_FAMILY}\n"; + } + + return undef; } @@ -903,105 +948,103 @@ sub OWXSWITCH_SetState($$) { =pod =begin html - - -

    OWSWITCH

    -
      FHEM module to commmunicate with 1-Wire Programmable Switches

      Note:
      - This 1-Wire module so far works only with the OWX interface module. Please define an OWX device first.
      -
      Example
      -
        - define OWX_S OWSWITCH DS2413 B5D502000000 60 + +

        OWSWITCH

        +

        FHEM module to commmunicate with 1-Wire Programmable Switches

        Note:
        + This 1-Wire module so far works only with the OWX interface module. Please define an OWX device first.

        +

        Example

        +

        + define OWX_S OWSWITCH DS2413 B5D502000000 60 +
        + attr OWX_S AName Lampe|light +
        + attr OWX_S AUnit AN|AUS +
        +


        - attr OWX_S AName Lampe|light + +

        Define

        +

        + define <name> OWSWITCH [<model>] <id> [<interval>] +

        Define a 1-Wire switch.

        +
          +
        • + [<model>]
          Defines the switch model (and thus 1-Wire family + id), currently the following values are permitted:
            +
          • model DS2413 with family id 3A (default if the model parameter is omitted). + 2 Channel switch with onboard memory
          • +
          • model DS2406 with family id 12. 2 Channel switch
          • +
          • model DS2408 with family id 29. 8 Channel switch
          • +
          +
        • +
        • + <id> +
          12-character unique ROM id of the converter device without family id and CRC + code
        • +
        • + <interval> +
          Measurement interval in seconds. The default is 300 seconds.
        • +
        + +

        Set

        +
        - attr OWX_S AUnit AN|AUS + +

        Get

        +
          +
        • + get <name> id +
          Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC
        • +
        • + get <name> present + +
          Returns 1 if this 1-Wire device is present, otherwise 0.
        • +
        • + get <name> interval
          Returns measurement interval in + seconds.
        • +
        • + get <name> input <channel-name>
          state for + channel (A,B, ... or defined channel name) This value reflects the measured value, + not necessarily the one set as output state, because the output transistors are open + collector switches. A measured state of 1 = OFF therefore corresponds to an output + state of 1 = OFF, but a measured state of 0 = ON can also be due to an external + shortening of the output.
        • +
        • + get <name> gpio
          Obtain state of all channels
        • +

        -
      -
      - - Define -
        - define <name> OWSWITCH [<model>] <id> - [<interval>] -

        Define a 1-Wire switch.

        -
      • - [<model>]
        Defines the switch model (and thus 1-Wire - family id), currently the following values are permitted:
          -
        • model DS2413 with family id 3A (default if the model parameter is - omitted). 2 Channel switch with onboard memory
        • -
        • model DS2406 with family id 12. 2 Channel switch
        • -
        • model DS2406 with family id 29. 8 Channel switch
        • -
        -
      • -
      • - <id> -
        12-character unique ROM id of the converter device without family id and - CRC code
      • -
      • - <interval> -
        Measurement interval in seconds. The default is 300 seconds.
      • -
      -
      - - Set - -
      - - Get -
        -
      • - get <name> id -
        Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC
      • -
      • - get <name> present - -
        Returns 1 if this 1-Wire device is present, otherwise 0.
      • -
      • - get <name> interval
        Returns measurement interval - in seconds.
      • -
      • - get <name> input <channel-name>
        - state for channel (A,B, ... or defined channel name) - This value reflects the measured value, not necessarily the one set as - output state, because the output transistors are open collector switches. A measured - state of 1 = OFF therefore corresponds to an output state of 1 = OFF, but a measured - state of 0 = ON can also be due to an external shortening of the output.
      • -
      • - get <name> gpio
        Obtain state of all - channels
      • -
      -
      - - Attributes For each of the following attributes, the channel - identification A,B,... may be used. -
    - + +

    Attributes

    For each of the following attributes, the channel identification A,B,... + may be used. =end html =cut diff --git a/fhem/FHEM/21_OWTHERM.pm b/fhem/FHEM/21_OWTHERM.pm index b8d3d9137..1ecb9a55d 100755 --- a/fhem/FHEM/21_OWTHERM.pm +++ b/fhem/FHEM/21_OWTHERM.pm @@ -4,20 +4,13 @@ # # FHEM module to commmunicate with 1-Wire temperature sensors DS1820, DS18S20, DS18B20, DS1822 # -# Attention: This module may communicate with the OWX module, -# and also with the 1-Wire File System OWFS +# Prof. Dr. Peter A. Henning # -# Prefixes for subroutines of this module: -# OW = General 1-Wire routines (Martin Fischer, Peter Henning) -# OWFS = 1-Wire file system (Martin Fischer) -# OWX = 1-Wire bus master interface (Peter Henning) +# $Id$ # -# Prof. Dr. Peter A. Henning, 2012 -# Martin Fischer, 2011 -# -# Version 2.24 - October, 2012 -# -# Setup bus device in fhem.cfg as +# Disclaimer: No code of the former OWTEMP module is contained here +# +######################################################################################## # # define OWTHERM [] [interval] # @@ -43,12 +36,8 @@ # Additional attributes are defined in fhem.cfg # Note: attributes "tempXXXX" are read during every update operation. # -# attr event on-change/on-update = when to write an event (default= on-update) -# -# attr stateAL "" = character string for denoting low alarm condition, default is (-), -# overwritten by attribute setting red down triangle -# attr stateAH "" = character string for denoting high alarm condition, default is (+), -# overwritten by attribute setting red up triangle +# attr stateAL "" = character string for denoting low alarm condition, default is down triangle +# attr stateAH "" = character string for denoting high alarm condition, default is up triangle # attr tempOffset = temperature offset in degree Celsius added to the raw temperature reading # attr tempUnit = unit of measurement, e.g. Celsius/Kelvin/Fahrenheit or C/K/F, default is Celsius # attr tempLow = value for low alarm @@ -74,7 +63,6 @@ ######################################################################################## package main; -#-- Prototypes to make komodo happy use vars qw{%attr %defs}; use strict; use warnings; @@ -133,10 +121,10 @@ sub OWTHERM_Initialize ($) { #tempOffset = a temperature offset added to the temperature reading for correction #tempUnit = a unit of measure: C/F/K $hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 loglevel:0,1,2,3,4,5 ". - "event:on-update,on-change ". + "event-on-update-reading event-on-change-reading ". "stateAL stateAH ". "tempOffset tempUnit:C,Celsius,F,Fahrenheit,K,Kelvin ". - "tempLow tempHigh"; + "tempLow tempHigh"; } ######################################################################################## @@ -210,12 +198,14 @@ sub OWTHERM_Define ($$) { $hash->{ROM_ID} = $fam.".".$id.$crc; $hash->{INTERVAL} = $interval; - #-- Couple to I/O device + #-- Couple to I/O device, exit if not possible AssignIoPort($hash); - Log 3, "OWTHERM: Warning, no 1-Wire I/O device found for $name." - if(!defined($hash->{IODev}->{NAME})); + if( !defined($hash->{IODev}->{NAME}) | !defined($hash->{IODev}) | ($hash->{IODev}->{PRESENT} != 1) ){ + return "OWTHERM: Warning, no 1-Wire I/O device found for $name."; + } $modules{OWTHERM}{defptr}{$id} = $hash; - $hash->{STATE} = "Defined"; + #-- + readingsSingleUpdate($hash,"state","defined",1); Log 3, "OWTHERM: Device $name defined."; #-- Start timer for initialization in a few seconds @@ -241,28 +231,25 @@ sub OWTHERM_InitializeDevice($) { my $name = $hash->{NAME}; my @args; - #-- more colorful alarm signatures - CommandAttr (undef,"$name stateAL ") - if( !defined($attr{$name}{"stateAL"} )); - CommandAttr (undef,"$name stateAH ") - if( !defined($attr{$name}{"stateAH"} )); - #-- unit attribute defined ? - $hash->{READINGS}{"temperature"}{UNIT} = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : "Celsius"; $hash->{READINGS}{"temperature"}{TYPE} = "temperature"; #-- Initial readings temperature sensor - $owg_temp = 0.0; - $owg_tl = defined($attr{$name}{"tempLow"}) ? $attr{$name}{"tempLow"} : 0.0; - $owg_th = defined($attr{$name}{"tempHigh"}) ? $attr{$name}{"tempHigh"} : 100.0; - #-- Initialize all the display stuff - OWTHERM_FormatValues($hash); - #-- alarm - @args = ($name,"tempLow",$owg_tl); - OWTHERM_Set($hash,@args); - @args = ($name,"tempHigh",$owg_th); - OWTHERM_Set($hash,@args); + $owg_temp = ""; + $owg_tl = defined($attr{$name}{"tempLow"}) ? $attr{$name}{"tempLow"} : ""; + $owg_th = defined($attr{$name}{"tempHigh"}) ? $attr{$name}{"tempHigh"} : ""; + #-- Output formatting because of reading attributes + OWTHERM_FormatValues($hash); + #-- set status + if ($owg_tl ne ""){ + @args = ($name,"tempLow",$owg_tl); + OWTHERM_Set($hash,@args); + } + if ($owg_th ne ""){ + @args = ($name,"tempHigh",$owg_th); + OWTHERM_Set($hash,@args); + } } ######################################################################################## @@ -278,16 +265,14 @@ sub OWTHERM_FormatValues($) { my $name = $hash->{NAME}; my ($unit,$offset,$factor,$abbr,$vval,$vlow,$vhigh,$statef); - my ($value1,$value2,$value3) = ("","",""); - - my $tn = TimeNow(); + my $svalue = ""; #-- attributes defined ? - $stateal = defined($attr{$name}{stateAL}) ? $attr{$name}{stateAL} : "(-)"; - $stateah = defined($attr{$name}{stateAH}) ? $attr{$name}{stateAH} : "(+)"; - $unit = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : $hash->{READINGS}{"temperature"}{UNIT}; - $offset = defined($attr{$name}{"tempOffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ; - $factor = 1.0; + $stateal = defined($attr{$name}{stateAL}) ? $attr{$name}{stateAL} : "▾"; + $stateah = defined($attr{$name}{stateAH}) ? $attr{$name}{stateAH} : "▴"; + $unit = $hash->{READINGS}{"temperature"}{UNIT} = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : "Celsius"; + $offset = defined($attr{$name}{"tempOffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ; + $factor = 1.0; if( $unit eq "Celsius" ){ $abbr = "°C"; @@ -300,57 +285,51 @@ sub OWTHERM_FormatValues($) { $factor = 1.8; } else { $abbr="?"; - Log 1, "OWTHERM_FormatValues: unknown unit $unit"; + Log 3, "OWTHERM_FormatValues: unknown unit $unit"; } - #-- these values are rather coplex to obtain, therefore save them in the hash + #-- these values are rather complex to obtain, therefore save them in the hash $hash->{READINGS}{"temperature"}{UNIT} = $unit; $hash->{READINGS}{"temperature"}{UNITABBR} = $abbr; $hash->{tempf}{offset} = $offset; $hash->{tempf}{factor} = $factor; + #-- no change in any value if invalid reading + return if( $owg_temp eq ""); + #-- correct values for proper offset, factor $vval = ($owg_temp + $offset)*$factor; - - #-- put into READINGS - $hash->{READINGS}{"temperature"}{VAL} = $vval; - $hash->{READINGS}{"temperature"}{TIME} = $tn; #-- correct alarm values for proper offset, factor $vlow = ($owg_tl + $offset)*$factor; $vhigh = ($owg_th + $offset)*$factor; - - #-- put into READINGS - $hash->{READINGS}{"tempLow"}{VAL} = $vlow; - $hash->{READINGS}{"tempLow"}{TIME} = $tn; - $hash->{READINGS}{"tempHigh"}{VAL} = $vhigh; - $hash->{READINGS}{"tempHigh"}{TIME} = $tn; #-- formats for output $statef = "%5.2f ".$abbr; - $value1 = "temperature: ".sprintf($statef,$vval); - $value2 = sprintf($statef,$vval); - $hash->{ALARM} = 1; + $svalue = "temperature: ".sprintf($statef,$vval); #-- Test for alarm condition + $hash->{ALARM} = 1; if( ($vval <= $vlow) && ( $vval >= $vhigh ) ){ - $value2 .= " ".$stateal.$stateah; - $value3 .= " ".$stateal.$stateah; + $svalue .= " ".$stateal.$stateah; }elsif( $vval <= $vlow ){ - $value2 .= " ".$stateal; - $value3 .= " ".$stateal; + $svalue .= " ".$stateal; }elsif( $vval >= $vhigh ){ - $value2 .= " ".$stateah; - $value3 .= " ".$stateah; + $svalue .= " ".$stateah; } else { $hash->{ALARM} = 0; } + #-- put into READINGS + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"temperature",$vval); + readingsBulkUpdate($hash,"tempLow",$vlow); + readingsBulkUpdate($hash,"tempHigh",$vhigh); + #-- STATE - $hash->{STATE} = $value2; - #-- alarm - #$hash->{READINGS}{alarms}{VAL} = $value3; - #$hash->{READINGS}{alarms}{TIME} = $tn; - return $value1; + readingsBulkUpdate($hash,"state",$svalue); + readingsEndUpdate($hash,1); + + return $svalue; } ######################################################################################## @@ -485,17 +464,8 @@ sub OWTHERM_GetValues($@) { } $hash->{PRESENT} = 1; - #-- old state, new state - my $oldval = $hash->{STATE}; $value=OWTHERM_FormatValues($hash); - my $newval = $hash->{STATE}; - #--logging depends on setting of the event-attribute Log 5, $value; - my $ev = defined($attr{$name}{"event"}) ? $attr{$name}{"event"} : "on-update"; - if( ($ev eq "on-update") || (($ev eq "on-change") && ($newval ne $oldval)) ){ - $hash->{CHANGED}[0] = $value; - DoTrigger($name, undef); - } return undef; } @@ -540,7 +510,7 @@ sub OWTHERM_Set($@) { return undef; } - #-- set other values depending on interface type + #-- set tempLow or tempHigh my $interface = $hash->{IODev}->{TYPE}; my $offset = $hash->{tempf}{offset}; my $factor = $hash->{tempf}{factor}; @@ -551,7 +521,7 @@ sub OWTHERM_Set($@) { return sprintf("OWTHERM: Set with wrong value $value for $key, range is [%3.1f,%3.1f]",$mmin,$mmax) if($value < $mmin || $value > $mmax); - #-- seems to be ok, put into the device + #-- seems to be ok, put into the device after correcting for offset and factor $a[2] = int($value/$factor-$offset); #-- OWX interface @@ -664,7 +634,7 @@ sub OWXTHERM_GetValues($) { my ($hash) = @_; - my ($i,$j,$k); + my ($i,$j,$k,@data); #-- For default, perform the conversion NOT now my $con=1; @@ -702,25 +672,25 @@ sub OWXTHERM_GetValues($) { } #-- process results - my @data=split(//,$res); - return "invalid data length, ".int(@data)." bytes" - if (@data != 19); + @data=split(//,substr($res,9)); + return "invalid data length, ".int(@data)." instead of 10 bytes" + if (@data != 10); return "invalid data" - if (ord($data[17])<=0); + if (ord($data[8])<=0); return "invalid CRC" - if (OWX_CRC8(substr($res,10,8),$data[18])==0); + if (OWX_CRC8(substr($res,10,8),$data[9])==0); #-- this must be different for the different device types # family = 10 => DS1820, DS18S20 if( $hash->{OW_FAMILY} eq "10" ) { - my $count_remain = ord($data[16]); - my $count_perc = ord($data[17]); + my $count_remain = ord($data[7]); + my $count_perc = ord($data[8]); my $delta = -0.25 + ($count_perc - $count_remain)/$count_perc; - my $lsb = ord($data[10]); + my $lsb = ord($data[1]); my $msb = 0; - my $sign = ord($data[11]) & 255; + my $sign = ord($data[2]) & 255; #-- test with -25 degrees #$lsb = 12*16+14; @@ -733,16 +703,16 @@ sub OWXTHERM_GetValues($) { $owg_temp = -128+$owg_temp; } - $owg_th = ord($data[12]) > 127 ? 128-ord($data[12]) : ord($data[12]); - $owg_tl = ord($data[13]) > 127 ? 128-ord($data[13]) : ord($data[13]); + $owg_th = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]); + $owg_tl = ord($data[4]) > 127 ? 128-ord($data[4]) : ord($data[4]); return undef; } elsif ( ($hash->{OW_FAMILY} eq "22") || ($hash->{OW_FAMILY} eq "28") ) { - my $lsb = ord($data[10]); - my $msb = ord($data[11]) & 7; - my $sign = ord($data[11]) & 248; + my $lsb = ord($data[1]); + my $msb = ord($data[2]) & 7; + my $sign = ord($data[2]) & 248; #-- test with -55 degrees #$lsb = 9*16; @@ -754,8 +724,8 @@ sub OWXTHERM_GetValues($) { if( $sign !=0 ){ $owg_temp = -128+$owg_temp; } - $owg_th = ord($data[12]) > 127 ? 128-ord($data[12]) : ord($data[12]); - $owg_tl = ord($data[13]) > 127 ? 128-ord($data[13]) : ord($data[13]); + $owg_th = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]); + $owg_tl = ord($data[4]) > 127 ? 128-ord($data[4]) : ord($data[4]); return undef; @@ -815,129 +785,114 @@ sub OWXTHERM_SetValues($@) { return undef; } - - 1; =pod =begin html - - -

    OWTHERM

    -
      FHEM module to commmunicate with 1-Wire bus digital thermometer devices

      - Note:
      This is the only 1-Wire module which so far works with both the OWFS and the - OWX interface module. Please define an OWFS device or an OWX device first.
      -
      Example
      -
        - define OWX_T OWTHERM DS18B20 E8D09B030000 300 -
        - attr OWX_T tempUnit Kelvin -
        -

      - - Define -
        - define <name> OWTHERM [<model>] <id> - [<interval>] + +

        OWTHERM

        +

        FHEM module to commmunicate with 1-Wire bus digital thermometer devices

        + Note:
        This is the only 1-Wire module which so far works with both the OWFS and the + OWX interface module. Please define an OWFS device or an OWX device first.
        +

        +

        Example

        +

        + define OWX_T OWTHERM DS18B20 E8D09B030000 300 +
        + attr OWX_T tempUnit Kelvin +
        +


        + +

        Define

        + define <name> OWTHERM [<model>] <id> [<interval>]

        Define a 1-Wire digital thermometer device.

        -
      • - [<model>]
        Defines the thermometer model (and thus - 1-Wire family id) currently the following values are permitted:
          -
        • model DS1820 with family id 10 (default if the model parameter is - omitted)
        • -
        • model DS1822 with family id 22
        • -
        • model DS18B20 with family id 28
        • -
        -
      • -
      • +

        + [<model>]
        Defines the thermometer model (and thus 1-Wire family + id) currently the following values are permitted:

        +
          +
        • model DS1820 with family id 10 (default if the model parameter is omitted)
        • +
        • model DS1822 with family id 22
        • +
        • model DS18B20 with family id 28
        • +
        +

        <id> -
        12-character unique ROM id of the thermometer device without family id and - CRC code

      • -
      • +
        12-character unique ROM id of the thermometer device without family id and CRC + code

        +

        <interval> -
        Temperature measurement interval in seconds. The default is 300 seconds.

      • +
        Temperature measurement interval in seconds. The default is 300 seconds.


        Example:
        define Temp1 OWTHERM 14B598010800 300
        -
      -
      - - Set - -
      - - Get - -
      - - Attributes - -
    - +
    + +

    Set

    + +
    + +

    Get

    + +
    + +

    Attributes

    + =end html =cut