From b628185c8f907ca3ea53c84246ecac17b79bb721 Mon Sep 17 00:00:00 2001 From: pahenning <> Date: Wed, 24 Oct 2012 18:55:50 +0000 Subject: [PATCH] git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@2012 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- contrib/1-Wire/00_OWX.pm | 15 +- contrib/1-Wire/21_OWAD.pm | 71 +-- contrib/1-Wire/21_OWCOUNT.pm | 9 +- contrib/1-Wire/21_OWID.pm | 6 +- contrib/1-Wire/21_OWLCD.pm | 14 +- contrib/1-Wire/21_OWMULTI.pm | 850 ++++++++++++++++++++++++++++++++++ contrib/1-Wire/21_OWSWITCH.pm | 190 +++++--- contrib/1-Wire/21_OWTHERM.pm | 20 +- 8 files changed, 1037 insertions(+), 138 deletions(-) create mode 100644 contrib/1-Wire/21_OWMULTI.pm diff --git a/contrib/1-Wire/00_OWX.pm b/contrib/1-Wire/00_OWX.pm index 57a564f3e..4e4b515cd 100644 --- a/contrib/1-Wire/00_OWX.pm +++ b/contrib/1-Wire/00_OWX.pm @@ -4,6 +4,7 @@ # # TODO: Abfangen, wenn das Serial Device nach Öffnung nicht existiert ??? # set init als rediscover ausführen. +# ungültige ID's von ungültigen devices => rauswerfen. # # FHEM module to commmunicate with 1-Wire bus devices # * via an active DS2480/DS2482/DS2490/DS9097U bus master interface attached to an USB port @@ -12,7 +13,7 @@ # Internally these interfaces are vastly different, read the corresponding Wiki pages # http://fhemwiki.de/wiki/Interfaces_f%C3%BCr_1-Wire # -# Version 2.22 - October, 2012 +# Version 2.24 - October, 2012 # # Prof. Dr. Peter A. Henning, 2012 # @@ -123,7 +124,7 @@ my $owx_LastDeviceFlag = 0; sub OWX_Initialize ($) { my ($hash) = @_; #-- Provider - $hash->{Clients} = ":OWAD:OWCOUNT:OWID:OWLCD:OWSWITCH:OWTHERM:"; + $hash->{Clients} = ":OWAD:OWCOUNT:OWID:OWLCD:OWMULTI:OWSWITCH:OWTHERM:"; #-- Normal Devices $hash->{DefFn} = "OWX_Define"; @@ -170,7 +171,7 @@ sub OWX_Define ($$) { my $msg = "OWX: Serial device $dev"; my $ret = DevIo_OpenDev($hash,0,undef); $owx_hwdevice = $hash->{USBDev}; - if($ret){ + if(!defined($owx_hwdevice)){ Log 1, $msg." not defined"; return "OWX: Can't open serial device $dev: $!" } else { @@ -673,16 +674,22 @@ sub OWX_Discover ($) { #-- Family 22 = Temperature sensor, assume DS1822 as default }elsif( $owx_f eq "22" ){ CommandDefine(undef,"$name OWTHERM DS1822 $owx_rnf"); + #-- Family 26 = Multisensor, assume DS2438 as default + }elsif( $owx_f eq "26" ){ + CommandDefine(undef,"$name OWMULTI DS2438 $owx_rnf"); #-- Family 28 = Temperature sensor, assume DS18B20 as default }elsif( $owx_f eq "28" ){ CommandDefine(undef,"$name OWTHERM DS18B20 $owx_rnf"); + #-- Family 29 = Switch, assume DS2408 as default + }elsif( $owx_f eq "29" ){ + CommandDefine(undef,"$name OWSWITCH DS2408 $owx_rnf"); #-- Family 3A = Switch, assume DS2413 as default }elsif( $owx_f eq "3A" ){ CommandDefine(undef,"$name OWSWITCH DS2413 $owx_rnf"); #-- Family FF = LCD display }elsif( $owx_f eq "FF" ){ CommandDefine(undef,"$name OWLCD $owx_rnf"); - #-- All unknown families are ID only + #-- All unknown families are ID only (ID-Chips have family id 09) } else { CommandDefine(undef,"$name OWID $owx_f $owx_rnf"); } diff --git a/contrib/1-Wire/21_OWAD.pm b/contrib/1-Wire/21_OWAD.pm index 3736c2d22..17a0caa2b 100644 --- a/contrib/1-Wire/21_OWAD.pm +++ b/contrib/1-Wire/21_OWAD.pm @@ -2,6 +2,8 @@ # # 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, @@ -14,7 +16,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 2.13 - July, 2012 +# Version 2.24 - October, 2012 # # Setup bus device in fhem.cfg as # @@ -40,6 +42,8 @@ # 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 green down triangle # attr stateAH0 "" = character string for denoting high normal condition, default is green up triangle # attr stateAL1 "" = character string for denoting low alarm condition, default is red down triangle @@ -148,7 +152,7 @@ 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 "; + "stateAL0 stateAL1 stateAH0 stateAH1 event:on-update,on-change "; for( my $i=0;$i<4;$i++ ){ $attlist .= " ".$owg_fixed[$i]."Name"; @@ -344,7 +348,7 @@ sub OWAD_FormatValues($) { #-- formats for output for (my $i=0;$i{READINGS}{"$owg_channel[$i]"}{OFFSET}; @@ -450,7 +454,7 @@ sub OWAD_Get($@) { #-- get id if($a[1] eq "id") { $value = $hash->{ROM_ID}; - return "$a[0] $reading => $value"; + return "$name.id => $value"; } #-- get present @@ -459,13 +463,13 @@ sub OWAD_Get($@) { my $master = $hash->{IODev}; $value = OWX_Verify($master,$hash->{ROM_ID}); $hash->{PRESENT} = $value; - return "$a[0] $reading => $value"; + return "$name.present => $value"; } #-- get interval if($a[1] eq "interval") { $value = $hash->{INTERVAL}; - return "$a[0] $reading => $value"; + return "$name.interval => $value"; } #-- reset presence @@ -592,12 +596,18 @@ sub OWAD_GetValues($) { return "OWAD: Could not get values from device $name"; } $hash->{PRESENT} = 1; - $value=OWAD_FormatValues($hash); - #--logging - Log 5, $value; - $hash->{CHANGED}[0] = $value; - DoTrigger($name, undef); + #-- 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; } @@ -805,9 +815,6 @@ 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, hash of the busmaster @@ -817,18 +824,16 @@ sub OWXAD_GetPage($$) { my ($i,$j,$k); #=============== 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 - $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"; - } - #-- conversion needs some 5 ms per channel - select(undef,undef,undef,0.02); - } + if( $page eq "reading") { + OWX_Reset($master); + #-- 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"; + } + #-- 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 $select="\xAA\x00\x00"; @@ -856,16 +861,18 @@ sub OWXAD_GetPage($$) { return "OWXAD: Device $owx_dev not accessible in reading $page page"; } - #-- reset the bus + #-- reset the bus OWX_Reset($master); #-- process results @data=split(//,$res); - if ( (@data != 22) ){ - Log 1, "OWXAD: Device $owx_dev returns invalid data of length ".int(@data); - return "OWXAD: Device $owx_dev returns invalid data of length ".int(@data); - } - + return "OWXAD: invalid data length, ".int(@data)." bytes" + if (@data != 22); + #return "invalid data" + # if (ord($data[17])<=0); + #return "invalid CRC" + # if (OWX_CRC8(substr($res,10,8),$data[18])==0); + #=============== get the voltage reading =============================== if( $page eq "reading"){ for( $i=0;$i{READINGS}{"$owg_channel[$i]"}{VAL}; my $oldtim = $hash->{READINGS}{"$owg_channel[$i]"}{TIME}; + $oldtim = "" if(!defined($oldtim)); #-- safeguard against the case where no previous measurement if( length($oldtim) > 0 ){ @@ -542,7 +543,7 @@ sub OWCOUNT_Get($@) { #-- get id if($a[1] eq "id") { $value = $hash->{ROM_ID}; - return "$a[0] $reading => $value"; + return "$name.id => $value"; } #-- get present @@ -551,13 +552,13 @@ sub OWCOUNT_Get($@) { my $master = $hash->{IODev}; $value = OWX_Verify($master,$hash->{ROM_ID}); $hash->{PRESENT} = $value; - return "$a[0] $reading => $value"; + return "$name.present => $value"; } #-- get interval if($a[1] eq "interval") { $value = $hash->{INTERVAL}; - return "$a[0] $reading => $value"; + return "$name.interval => $value"; } #-- reset presence diff --git a/contrib/1-Wire/21_OWID.pm b/contrib/1-Wire/21_OWID.pm index 56b88caa6..45c6c9135 100644 --- a/contrib/1-Wire/21_OWID.pm +++ b/contrib/1-Wire/21_OWID.pm @@ -12,7 +12,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 2.13 - July, 2012 +# Version 2.24 - October, 2012 # # Setup bus device in fhem.cfg as # @@ -181,7 +181,7 @@ sub OWID_Get($@) { #-- get id if($a[1] eq "id") { $value = $hash->{ROM_ID}; - return "$a[0] $reading => $value"; + return "$name.id => $value"; } #-- get present @@ -190,7 +190,7 @@ sub OWID_Get($@) { my $master = $hash->{IODev}; $value = OWX_Verify($master,$hash->{ROM_ID}); $hash->{PRESENT} = $value; - return "$a[0] $reading => $value"; + return "$name.present => $value"; } } diff --git a/contrib/1-Wire/21_OWLCD.pm b/contrib/1-Wire/21_OWLCD.pm index 0b7534df8..2f9c27cfc 100644 --- a/contrib/1-Wire/21_OWLCD.pm +++ b/contrib/1-Wire/21_OWLCD.pm @@ -12,7 +12,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 2.13 - July, 2012 +# Version 2.24 - October, 2012 # # Setup bus device in fhem.cfg as # @@ -228,7 +228,7 @@ sub OWLCD_Get($@) { #-- get id if($a[1] eq "id") { $value = $hash->{ROM_ID}; - return "$a[0] $reading => $value"; + return "$name.id => $value"; } #-- get present @@ -237,25 +237,25 @@ sub OWLCD_Get($@) { my $master = $hash->{IODev}; $value = OWX_Verify($master,$hash->{ROM_ID}); $hash->{PRESENT} = $value; - return "$a[0] $reading => $value"; + return "$name.present => $value"; } #-- get gpio states if($a[1] eq "gpio") { $value = OWXLCD_Get($hash,"gpio"); - return "$a[0] $reading => $value"; + return "$name.gpio => $value"; } #-- get gpio counters if($a[1] eq "counter") { $value = OWXLCD_Get($hash,"counter"); - return "$a[0] $reading => $value"; + return "$name.counter => $value"; } #-- get version if($a[1] eq "version") { $value = OWXLCD_Get($hash,"version"); - return "$a[0] $reading => $value"; + return "$name.version => $value"; } #-- get EEPROM content @@ -263,7 +263,7 @@ sub OWLCD_Get($@) { my $page = ($a[2] =~ m/\d/) ? int($a[2]) : 0; Log 1,"Calling GetMemory with page $page"; $value = OWXLCD_GetMemory($hash,$page); - return "$a[0] $reading $page => $value"; + return "$name $reading $page => $value"; } } diff --git a/contrib/1-Wire/21_OWMULTI.pm b/contrib/1-Wire/21_OWMULTI.pm new file mode 100644 index 000000000..1807c5819 --- /dev/null +++ b/contrib/1-Wire/21_OWMULTI.pm @@ -0,0 +1,850 @@ +######################################################################################## +# +# OWMULTI.pm +# +# 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, 2012 +# +# Version 2.24 - October, 2012 +# +# Setup bus device in fhem.cfg as +# +# define OWMULTI [] [interval] +# +# where may be replaced by any name string +# +# is a 1-Wire device type. If omitted, we assume this to be an +# DS2438 +# +# is a 12 character (6 byte) 1-Wire ROM ID +# without Family ID, e.g. A2D90D000800 +# [interval] is an optional query interval in seconds +# +# get id => OW_FAMILY.ROM_ID.CRC +# get present => 1 if device present, 0 if not +# get interval => query interval +# get reading => measurement value obtained from VFunction +# get temperature => temperature measurement +# get VDD => supply voltage measurement +# get V|raw => raw external voltage measurement +# +# set interval => set period for measurement +# +# 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 +# attr VUnit | = unit of measurement for the voltage channel | its abbreviation +# attr Vfunction = arbitrary functional expression involving the values VDD, V, T +# VDD is replaced by the measured supply voltage in Volt, +# V by the measured external voltage +# T by the measured and corrected temperature in its unit +# +######################################################################################## +# +# 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($$); + +#-- temperature and voltage globals - always the raw values from the device +my $owg_temp; +my $owg_volt; +my $owg_vdd; +my $owg_channel; + +my %gets = ( + "id" => "", + "present" => "", + "interval" => "", + "reading" => "", + "temperature" => "", + "VDD" => "", + "V" => "", + "raw" => "", +); + +my %sets = ( + "interval" => "", +); + +my %updates = ( + "present" => "", + "reading" => "", +); + +######################################################################################## +# +# The following subroutines are independent of the bus interface +# +# Prefix = OWMULTI +# +######################################################################################## +# +# OWMULTI_Initialize +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWMULTI_Initialize ($) { + my ($hash) = @_; + + $hash->{DefFn} = "OWMULTI_Define"; + $hash->{UndefFn} = "OWMULTI_Undef"; + $hash->{GetFn} = "OWMULTI_Get"; + $hash->{SetFn} = "OWMULTI_Set"; + #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 ". + "tempOffset tempUnit:C,Celsius,F,Fahrenheit,K,Kelvin ". + "VName VUnit VFunction"; + } + +######################################################################################## +# +# OWMULTI_Define - Implements DefFn function +# +# Parameter hash = hash of device addressed, def = definition string +# +######################################################################################## + +sub OWMULTI_Define ($$) { + my ($hash, $def) = @_; + + # define OWMULTI [] [interval] + # e.g.: define flow OWMULTI 525715020000 300 + my @a = split("[ \t][ \t]*", $def); + + my ($name,$model,$fam,$id,$crc,$interval,$ret); + my $tn = TimeNow(); + + #-- default + $name = $a[0]; + $interval = 300; + $ret = ""; + + #-- check syntax + return "OWMULTI: Wrong syntax, must be define OWMULTI [] [interval]" + if(int(@a) < 2 || int(@a) > 6); + + #-- check if this is an old style definition, e.g. is missing + my $a2 = $a[2]; + my $a3 = defined($a[3]) ? $a[3] : ""; + if( ($a2 eq "none") || ($a3 eq "none") ) { + return "OWMULTI: ID = none is obsolete now, please redefine"; + } elsif( $a2 =~ m/^[0-9|a-f|A-F]{12}$/ ) { + $model = "DS2438"; + $id = $a[2]; + if(int(@a)>=4) { $interval = $a[3]; } + Log 1, "OWMULTI: Parameter [alarminterval] is obsolete now - must be set with I/O-Device" + if(int(@a) == 5); + } elsif( $a3 =~ m/^[0-9|a-f|A-F]{12}$/ ) { + $model = $a[2]; + $id = $a[3]; + if(int(@a)>=5) { $interval = $a[4]; } + Log 1, "OWMULTI: Parameter [alarminterval] is obsolete now - must be set with I/O-Device" + if(int(@a) == 6); + } else { + return "OWMULTI: $a[0] ID $a[2] invalid, specify a 12 digit value"; + } + + #-- 1-Wire ROM identifier in the form "FF.XXXXXXXXXXXX.YY" + # FF = family id follows from the model + # YY must be determined from id + if( $model eq "DS2438" ){ + $fam = "26"; + }else{ + return "OWMULTI: Wrong 1-Wire device model $model"; + } + # determine CRC Code - only if this is a direct interface + $crc = defined($hash->{IODev}->{INTERFACE}) ? sprintf("%02x",OWX_CRC($fam.".".$id."00")) : "00"; + + #-- define device internals + $hash->{OW_ID} = $id; + $hash->{OW_FAMILY} = $fam; + $hash->{PRESENT} = 0; + $hash->{ROM_ID} = $fam.".".$id.$crc; + $hash->{INTERVAL} = $interval; + + #-- 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})); + $modules{OWMULTI}{defptr}{$id} = $hash; + $hash->{STATE} = "Defined"; + Log 3, "OWMULTI: Device $name defined."; + + #-- Start timer for initialization in a few seconds + InternalTimer(time()+10, "OWMULTI_InitializeDevice", $hash, 0); + + #-- Start timer for updates + InternalTimer(time()+$hash->{INTERVAL}, "OWMULTI_GetValues", $hash, 0); + + return undef; +} + +######################################################################################## +# +# OWMULTI_InitializeDevice - delayed setting of initial readings and channel names +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWMULTI_InitializeDevice($) { + my ($hash) = @_; + + my $name = $hash->{NAME}; + my @args; + + #-- 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_volt = 0.0; + $owg_vdd = 5.0; + #-- Set channel name, channel unit for voltage channel + my $cname = defined($attr{$name}{"VName"}) ? $attr{$name}{"VName"} : "voltage|voltage"; + my @cnama = split(/\|/,$cname); + if( int(@cnama)!=2){ + Log 1, "OWMULTI: Incomplete channel name specification $cname. Better use $cname|"; + push(@cnama,"unknown"); + } + + #-- unit + my $unit = defined($attr{$name}{"VUnit"}) ? $attr{$name}{"VUnit"} : "Volt|V"; + my @unarr= split(/\|/,$unit); + if( int(@unarr)!=2 ){ + Log 1, "OWMULTI: Incomplete channel unit specification $unit. Better use $unit|"; + push(@unarr,""); + } + + #-- put into readings + $owg_channel = $cnama[0]; + $hash->{READINGS}{"$owg_channel"}{TYPE} = $cnama[1]; + $hash->{READINGS}{"$owg_channel"}{UNIT} = $unarr[0]; + $hash->{READINGS}{"$owg_channel"}{UNITABBR} = $unarr[1]; + + #-- Initialize all the display stuff + OWMULTI_FormatValues($hash); + +} + +######################################################################################## +# +# OWMULTI_FormatValues - put together various format strings +# +# Parameter hash = hash of device addressed, fs = format string +# +######################################################################################## + +sub OWMULTI_FormatValues($) { + my ($hash) = @_; + + my $name = $hash->{NAME}; + my ($tunit,$toffset,$tfactor,$tabbr,$tval,$vfunc,$vval); + my ($value1,$value2) = ("",""); + + my $tn = TimeNow(); + + #-- attributes defined ? + $tunit = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : $hash->{READINGS}{"temperature"}{UNIT}; + $toffset = defined($attr{$name}{"tempOffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ; + $tfactor = 1.0; + + if( $tunit eq "Celsius" ){ + $tabbr = "°C"; + } elsif ($tunit eq "Kelvin" ){ + $tabbr = "K"; + $toffset += "273.16" + } elsif ($tunit eq "Fahrenheit" ){ + $tabbr = "°F"; + $toffset = ($toffset+32)/1.8; + $tfactor = 1.8; + } else { + $tabbr="?"; + Log 1, "OWMULTI_FormatValues: unknown unit $tunit"; + } + #-- these values are rather coplex 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; + + #-- 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 ? + $vfunc = defined($attr{$name}{"VFunction"}) ? $attr{$name}{"VFunction"} : "V"; + + #-- replace by proper values + $vfunc =~ s/VDD/\$owg_vdd/g; + $vfunc =~ s/V/\$owg_volt/g; + $vfunc =~ s/T/\$tval/g; + + #-- determine the measured value from the function + $vfunc = "\$owg_vdd = $owg_vdd; \$owg_volt = $owg_volt; \$tval = $tval; ".$vfunc; + $vfunc = eval($vfunc); + if( $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); + + #-- STATE + $hash->{STATE} = $value2; + + return $value1; +} + +######################################################################################## +# +# OWMULTI_Get - Implements GetFn function +# +# Parameter hash = hash of device addressed, a = argument array +# +######################################################################################## + +sub OWMULTI_Get($@) { + my ($hash, @a) = @_; + + my $reading = $a[1]; + my $name = $hash->{NAME}; + my $model = $hash->{OW_MODEL}; + my $value = undef; + my $ret = ""; + + #-- check syntax + return "OWMULTI: Get argument is missing @a" + if(int(@a) != 2); + + #-- check argument + return "OWMULTI: Get with unknown argument $a[1], choose one of ".join(",", sort keys %gets) + if(!defined($gets{$a[1]})); + + #-- get id + if($a[1] eq "id") { + $value = $hash->{ROM_ID}; + return "$name.id => $value"; + } + + #-- Get other values according to interface type + my $interface= $hash->{IODev}->{TYPE}; + + #-- get present + if($a[1] eq "present" ) { + #-- OWX interface + if( $interface eq "OWX" ){ + #-- hash of the busmaster + my $master = $hash->{IODev}; + $value = OWX_Verify($master,$hash->{ROM_ID}); + $hash->{PRESENT} = $value; + return "$name.present => $value"; + } else { + return "OWMULTI: Verification not yet implemented for interface $interface"; + } + } + + #-- get interval + if($reading eq "interval") { + $value = $hash->{INTERVAL}; + return "$name.interval => $value"; + } + + #-- reset presence + $hash->{PRESENT} = 0; + + #-- OWX interface + if( $interface eq "OWX" ){ + #-- not different from getting all values .. + $ret = OWXMULTI_GetValues($hash); + #-- OWFS interface not yet implemented + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSMULTI_GetValues($hash); + #-- Unknown interface + }else{ + return "OWMULTI: Get with wrong IODev type $interface"; + } + + #-- process results + if( defined($ret) ){ + return "OWMULTI: Could not get values from device $name, return was $ret"; + } + $hash->{PRESENT} = 1; + OWMULTI_FormatValues($hash); + + #-- return the special reading + if ($reading eq "reading") { + return "OWMULTI: $name.reading => ". + $hash->{READINGS}{"$owg_channel"}{VAL}; + } + if ($reading eq "temperature") { + return "OWMULTI: $name.temperature => ". + $hash->{READINGS}{"temperature"}{VAL}; + } + if ($reading eq "VDD") { + return "OWMULTI: $name.VDD => ". + $hash->{READINGS}{"VDD"}{VAL}; + } + if ( ($reading eq "V")|($reading eq "raw")) { + return "OWMULTI: $name.V => ". + $owg_volt; + } + return undef; +} + +####################################################################################### +# +# OWMULTI_GetValues - Updates the readings from device +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWMULTI_GetValues($@) { + my $hash = shift; + + my $name = $hash->{NAME}; + my $value = ""; + my $ret = ""; + + #-- restart timer for updates + RemoveInternalTimer($hash); + InternalTimer(time()+$hash->{INTERVAL}, "OWMULTI_GetValues", $hash, 1); + + #-- reset presence + $hash->{PRESENT} = 0; + + #-- Get values according to interface type + my $interface= $hash->{IODev}->{TYPE}; + if( $interface eq "OWX" ){ + #-- max 3 tries + for(my $try=0; $try<3; $try++){ + $ret = OWXMULTI_GetValues($hash); + last + if( !defined($ret) ); + } + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSTHERM_GetValues($hash); + }else{ + Log 3, "OWMULTI: GetValues with wrong IODev type $interface"; + return 1; + } + + #-- process results + if( defined($ret) ){ + Log 3, "OWMULTI: Could not get values from device $name, reason $ret"; + return 1; + } + $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; +} + +####################################################################################### +# +# OWMULTI_Set - Set one value for device +# +# Parameter hash = hash of device addressed +# a = argument string +# +######################################################################################## + +sub OWMULTI_Set($@) { + my ($hash, @a) = @_; + + #-- for the selector: which values are possible + return join(" ", sort keys %sets) if(@a == 2); + #-- check syntax + return "OWMULTI: Set needs one parameter" + if(int(@a) != 3); + #-- check argument + return "OWMULTI: Set with unknown argument $a[1], choose one of ".join(",", sort keys %sets) + if(!defined($sets{$a[1]})); + + #-- define vars + my $key = $a[1]; + my $value = $a[2]; + my $ret = undef; + my $name = $hash->{NAME}; + my $model = $hash->{OW_MODEL}; + + #-- set new timer interval + if($key eq "interval") { + # check value + return "OWMULTI: Set with short interval, must be > 1" + if(int($value) < 1); + # update timer + $hash->{INTERVAL} = $value; + RemoveInternalTimer($hash); + InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWMULTI_GetValues", $hash, 1); + return undef; + } + + #-- set other values depending on interface type + my $interface = $hash->{IODev}->{TYPE}; + my $offset = $hash->{tempf}{offset}; + my $factor = $hash->{tempf}{factor}; + + #-- find upper and lower boundaries for given offset/factor + my $mmin = (-55+$offset)*$factor; + my $mmax = (125+$offset)*$factor; + return sprintf("OWMULTI: 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 + $a[2] = int($value/$factor-$offset); + + #-- OWX interface + if( $interface eq "OWX" ){ + $ret = OWXMULTI_SetValues($hash,@a); + #-- OWFS interface not yet implemented + #}elsif( $interface eq "OWFS" ){ + # $ret = OWFSTHERM_SetValues($hash,@a); + # return $ret + # if(defined($ret)); + } else { + return "OWMULTI: Set with wrong IODev type $interface"; + } + + #-- process results - we have to reread the device + $hash->{PRESENT} = 1; + OWMULTI_GetValues($hash); + OWMULTI_FormatValues($hash); + Log 4, "OWMULTI: Set $hash->{NAME} $key $value"; + + return undef; +} + +######################################################################################## +# +# OWMULTI_Undef - Implements UndefFn function +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWMULTI_Undef ($) { + my ($hash) = @_; + + delete($modules{OWMULTI}{defptr}{$hash->{OW_ID}}); + RemoveInternalTimer($hash); + return undef; +} + +######################################################################################## +# +# The following subroutines in alphabetical order are only for a 1-Wire bus connected +# directly to the FHEM server +# +# Prefix = OWXMULTI +# +######################################################################################## +# +# OWXMULTI_GetValues - Get reading from one device +# +# Parameter hash = hash of device addressed +# +######################################################################################## + +sub OWXMULTI_GetValues($) { + + my ($hash) = @_; + + my ($i,$j,$k,$res,$res2); + + #-- ID of the device + my $owx_dev = $hash->{ROM_ID}; + #-- hash of the busmaster + my $master = $hash->{IODev}; + + #-- switch the device to current measurement off, VDD only + OWX_Reset($master); + #-- issue the match ROM command \x55 and the write scratchpad command + if( OWX_Complex($master,$owx_dev,"\x4E\x00\x08",0) eq 0 ){ + return "$owx_dev write status failed"; + } + + #-- copy scratchpad to register + OWX_Reset($master); + #-- issue the match ROM command \x55 and the copy scratchpad command + if( OWX_Complex($master,$owx_dev,"\x48\x00",0) eq 0){ + return "$owx_dev copy scratchpad failed"; + } + + #-- initiate temperature conversion + OWX_Reset($master); + #-- issue the match ROM command \x55 and the start conversion command + if( OWX_Complex($master,$owx_dev,"\x44",0) eq 0 ){ + return "$owx_dev temperature conversion failed"; + } + #-- conversion needs some 10 ms ! + select(undef,undef,undef,0.012); + + #-- initiate voltage conversion + OWX_Reset($master); + #-- issue the match ROM command \x55 and the start conversion command + if( OWX_Complex($master,$owx_dev,"\xB4",0) eq 0 ){ + return "$owx_dev voltage conversion failed"; + } + #-- conversion needs some 4 ms ! + select(undef,undef,undef,0.006); + + #-- from memory to scratchpad + OWX_Reset($master); + #-- issue the match ROM command \x55 and the recall memory command + if( OWX_Complex($master,$owx_dev,"\xB8\x00",0) eq 0 ){ + return "$owx_dev recall memory failed"; + } + #-- copy needs some 10 ms ! + select(undef,undef,undef,0.012); + + #-- NOW ask the specific device + OWX_Reset($master); + #-- 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 + + #-- temperature + my $lsb = ord($data[12]); + my $msb = ord($data[13]) & 127; + my $sign = ord($data[13]) & 128; + + #-- test with -55 degrees + #$lsb = 0; + #$sign = 1; + #$msb = 73; + + #-- 2's complement form = signed bytes + $owg_temp = $msb+ $lsb/256; + if( $sign !=0 ){ + $owg_temp = -128+$owg_temp; + } + + #-- voltage + $lsb = ord($data[14]); + $msb = ord($data[15]) & 3; + + #-- test with 5V + #$lsb = 244; + #$msb = 1; + + #-- supply voltage + $owg_vdd = ($msb*256+ $lsb)/100; + + #-- switch the device to current measurement off, V external only + OWX_Reset($master); + #-- issue the match ROM command \x55 and the write scratchpad command + if( OWX_Complex($master,$owx_dev,"\x4E\x00\x00",0) eq 0 ){ + return "$owx_dev write status failed"; + } + + #-- copy scratchpad to register + OWX_Reset($master); + #-- issue the match ROM command \x55 and the copy scratchpad command + if( OWX_Complex($master,$owx_dev,"\x48\x00",0) eq 0){ + return "$owx_dev copy scratchpad failed"; + } + + #-- initiate voltage conversion + OWX_Reset($master); + #-- issue the match ROM command \x55 and the start conversion command + if( OWX_Complex($master,$owx_dev,"\xB4",0) eq 0 ){ + return "$owx_dev voltage conversion failed"; + } + #-- conversion needs some 4 ms ! + select(undef,undef,undef,0.006); + + #-- from memory to scratchpad + OWX_Reset($master); + #-- issue the match ROM command \x55 and the recall memory command + if( OWX_Complex($master,$owx_dev,"\xB8\x00",0) eq 0 ){ + return "$owx_dev recall memory failed"; + } + #-- copy needs some 10 ms ! + select(undef,undef,undef,0.012); + + #-- NOW ask the specific device + OWX_Reset($master); + #-- 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; + + #-- test with 7.2 V + #$lsb = 208; + #$msb = 2; + + #-- external voltage + $owg_volt = ($msb*256+ $lsb)/100; + + return undef; + + #} else { + # return "OWXMULTI: Unknown device family $hash->{OW_FAMILY}\n"; + #} +} + +####################################################################################### +# +# OWXMULTI_SetValues - Implements SetFn function +# +# Parameter hash = hash of device addressed +# a = argument array +# +######################################################################################## + +sub OWXMULTI_SetValues($@) { + my ($hash, @a) = @_; + + my ($i,$j,$k); + + my $name = $hash->{NAME}; + #-- ID of the device + my $owx_dev = $hash->{ROM_ID}; + #-- hash of the busmaster + my $master = $hash->{IODev}; + + #-- define vars + my $key = $a[1]; + my $value = $a[2]; + + 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("\x4E%c%c\x48",0,0); + my $res=OWX_Complex($master,$owx_dev,$select,0); + + if( $res eq 0 ){ + return "OWXMULTI: Device $owx_dev not accessible"; + } + + DoTrigger($name, undef) if($init_done); + return undef; +} + + + +1; diff --git a/contrib/1-Wire/21_OWSWITCH.pm b/contrib/1-Wire/21_OWSWITCH.pm index 156f20900..bd4ece0d6 100644 --- a/contrib/1-Wire/21_OWSWITCH.pm +++ b/contrib/1-Wire/21_OWSWITCH.pm @@ -2,7 +2,7 @@ # # OWSWITCH.pm # -# FHEM module to commmunicate with 1-Wire adressable switches DS2413, DS206 +# 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 @@ -17,7 +17,7 @@ # # Prof. Dr. Peter A. Henning, 2012 # -# Version 2.22 - September, 2012 +# Version 2.24 - October, 2012 # # Setup bus device in fhem.cfg as # @@ -38,12 +38,12 @@ # note: 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 th eoutput. +# state of 0 = ON can also be due to an external shortening of the output. # 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) -# note: 1 = OFF, 0 = ON in normal usage. See also th enote above +# note: 1 = OFF, 0 = ON in normal usage. See also the note above # 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 # @@ -83,7 +83,7 @@ use warnings; sub Log($$); #-- channel name - fixed is the first array, variable the second -my @owg_fixed = ("A","B"); +my @owg_fixed = ("A","B","C","D","E","F","G","H"); my @owg_channel; #-- channel values - always the raw input resp. output values from the device my @owg_val; @@ -106,9 +106,14 @@ my %sets = ( my %updates = ( "present" => "", - "gpio" => "" + "gpio" => "" ); +my %cnumber = ( + "DS2413" => 2, + "DS2406" => 2, + "DS2408" => 8 + ); ######################################################################################## # @@ -131,14 +136,13 @@ sub OWSWITCH_Initialize ($) { $hash->{UndefFn} = "OWSWITCH_Undef"; $hash->{GetFn} = "OWSWITCH_Get"; $hash->{SetFn} = "OWSWITCH_Set"; - #Name = channel name - #Offset = an offset added to the reading - #Factor = a factor multiplied with (reading+offset) - #Unit = a unit of measure - my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2413,DS2406 loglevel:0,1,2,3,4,5 ". + + 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"; - for( my $i=0;$i{NAME}; #-- Set channel names, channel units - for( my $i=0;$i{READINGS}{"$owg_channel[$i]"}{TIME} = $tn; #-- insert comma - if( $i{ROM_ID}; - return "$a[0] $reading => $value"; + return "$name.id => $value"; } #-- get present @@ -385,13 +394,13 @@ sub OWSWITCH_Get($@) { my $master = $hash->{IODev}; $value = OWX_Verify($master,$hash->{ROM_ID}); $hash->{PRESENT} = $value; - return "$a[0] $reading => $value"; + return "$name.present => $value"; } #-- get interval if($a[1] eq "interval") { $value = $hash->{INTERVAL}; - return "$a[0] $reading => $value"; + return "$name.interval => $value"; } #-- reset presence @@ -405,19 +414,22 @@ sub OWSWITCH_Get($@) { if( $reading eq "input" ){ return "OWSWITCH: get needs parameter when reading input: " if( int(@a)<2 ); - #-- find out which channel we have - if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){ - }elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){ - } else { - return "OWSWITCH: invalid input address, must be A, B or defined channel name" + my $fnd=undef; + for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ + if( ($a[2] eq $owg_channel[$i]) || ($a[2] eq $owg_fixed[$i]) ){ + $fnd=$i; + last; + } } + return "OWSWITCH: invalid output address, must be A,B,... or defined channel name" + if( !defined($fnd) ); #-- OWX interface if( $interface eq "OWX" ){ $ret = OWXSWITCH_GetState($hash); #-- OWFS interface #}elsif( $interface eq "OWFS" ){ - # $ret = OWFSAD_GetPage($hash,"reading"); + # $ret = OWFSSWITCH_GetPage($hash,"reading"); #-- Unknown interface }else{ return "OWSWITCH: Get with wrong IODev type $interface"; @@ -426,13 +438,7 @@ sub OWSWITCH_Get($@) { OWSWITCH_FormatValues($hash); my @states = split(/,/,$hash->{STATE}); - if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){ - return $a[2]." = ".$states[0]; - }elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){ - return $a[2]." = ".$states[1]; - } else { - return "OWSWITCH: invalid input address, must be A, B or defined channel name" - } + return $a[2]." = ".$states[$fnd]; #-- get all states }elsif( $reading eq "gpio" ){ @@ -575,12 +581,15 @@ sub OWSWITCH_Set($@) { return "OWSWITCH: get needs parameter when writing output: " if( int(@a)<2 ); #-- find out which channel we have - if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){ - }elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){ - } else { - return "OWSWITCH: invalid output address, must be A, B or defined channel name" + my $fnd=undef; + for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ + if( ($a[2] eq $owg_channel[$i]) || ($a[2] eq $owg_fixed[$i]) ){ + $fnd=$i; + last; + } } - + return "OWSWITCH: invalid output address, must be A,B,... or defined channel name" + if( !defined($fnd) ); #-- prepare gpio value my $nval; if( lc($a[3]) eq "on" ){ @@ -593,11 +602,14 @@ sub OWSWITCH_Set($@) { #-- OWX interface if( $interface eq "OWX" ){ - $ret = OWXSWITCH_GetState($hash); - if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){ - $value = $owg_val[1]*2+$nval; - }elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){ - $value = 2*$nval+$owg_val[0]; + $ret = OWXSWITCH_GetState($hash); + $value = 0; + #-- vax or val ? + for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ + $value += ($owg_vax[$i]<<$i) + if( $i != $fnd ); + $value += ($nval<<$i) + if( $i == $fnd ); } $ret = OWXSWITCH_SetState($hash,$value); #-- OWFS interface @@ -611,13 +623,13 @@ sub OWSWITCH_Set($@) { #-- set state }elsif( $key eq "gpio" ){ #-- check value and write to device - return "OWSWITCH: Set with wrong value for gpio port, must be 0 <= gpio <= 3" - if( ! ((int($value) >= 0) && (int($value) <= 3)) ); + return "OWSWITCH: Set with wrong value for gpio port, must be 0 <= gpio <= ".(1 << $cnumber{$attr{$name}{"model"}} - 1) + if( ! ((int($value) >= 0) && (int($value) <= (1 << $cnumber{$attr{$name}{"model"}} -1 ))) ); if( $interface eq "OWX" ){ $ret = OWXSWITCH_SetState($hash,int($value)); #}elsif( $interface eq "OWFS" ){ - # $ret = OWFSAD_GetValues($hash); + # $ret = OWFSSWITCH_GetValues($hash); }else{ return "OWSWITCH: GetValues with wrong IODev type $interface"; } @@ -702,7 +714,7 @@ sub OWXSWITCH_GetState($) { } #-- family = 12 => DS2406 }elsif( $hash->{OW_FAMILY} eq "12" ) { - #=============== set gpio values =============================== + #=============== 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"); @@ -713,6 +725,20 @@ sub OWXSWITCH_GetState($) { 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"; } @@ -729,16 +755,16 @@ sub OWXSWITCH_GetState($) { #-- reset the bus OWX_Reset($master); - #my $ress = "OWXSWITCH_Get: three data bytes "; - # for($i=0;$i DS2413 if( $hash->{OW_FAMILY} eq "3A" ) { $owg_val[0] = ord($data[0]) & 1; @@ -752,6 +778,12 @@ sub OWXSWITCH_GetState($) { $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; + } } return undef } @@ -798,7 +830,7 @@ sub OWXSWITCH_SetState($$) { #-- family = 12 => DS2406 }elsif( $hash->{OW_FAMILY} eq "12" ) { #=============== set gpio values =============================== - # Wrriting the output state via the access channel command does + # 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 @@ -819,7 +851,24 @@ sub OWXSWITCH_SetState($$) { if( $res eq 0 ){ return "OWXSWITCH: Device $owx_dev not accessible in writing"; } - + $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 =============================== + #-- issue the match ROM command \x55 and the write gpio command + # \x5A plus the value byte and its complement + $select=sprintf("\x5A%c%c",$value,255-$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"; + } + } else { return "OWXSWITCH: Unknown device family $hash->{OW_FAMILY}\n"; } @@ -829,35 +878,32 @@ sub OWXSWITCH_SetState($$) { #-- process results @data=split(//,substr($res,10)); - #my $ress = "OWXSWITCH_Set: three data bytes "; - # for($i=0;$i 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 + #-- 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"; } - } - - #-- Put the new values in the system variables - #-- This holds only for DS2413 - - $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" ) { + if( $data[2] ne "\xAA"){ + return "OWXSWITCH: State could not be set for device $owx_dev"; + } return undef + } 1; diff --git a/contrib/1-Wire/21_OWTHERM.pm b/contrib/1-Wire/21_OWTHERM.pm index 1b6d4258c..c2c962cc3 100755 --- a/contrib/1-Wire/21_OWTHERM.pm +++ b/contrib/1-Wire/21_OWTHERM.pm @@ -15,7 +15,7 @@ # Prof. Dr. Peter A. Henning, 2012 # Martin Fischer, 2011 # -# Version 2.22 - October, 2012 +# Version 2.24 - October, 2012 # # Setup bus device in fhem.cfg as # @@ -376,7 +376,7 @@ sub OWTHERM_Get($@) { #-- get id if($a[1] eq "id") { $value = $hash->{ROM_ID}; - return "$a[0] $reading => $value"; + return "$name.id => $value"; } #-- Get other values according to interface type @@ -390,7 +390,7 @@ sub OWTHERM_Get($@) { my $master = $hash->{IODev}; $value = OWX_Verify($master,$hash->{ROM_ID}); $hash->{PRESENT} = $value; - return "$a[0] $reading => $value"; + return "$name.present => $value"; } else { return "OWTHERM: Verification not yet implemented for interface $interface"; } @@ -399,7 +399,7 @@ sub OWTHERM_Get($@) { #-- get interval if($reading eq "interval") { $value = $hash->{INTERVAL}; - return "$a[0] $reading => $value"; + return "$name.interval => $value"; } #-- reset presence @@ -696,19 +696,7 @@ sub OWXTHERM_GetValues($) { return "$owx_dev not accessible in 2nd step"; } - #if (length($res) == 10){ - # my $res2 = "====> OWXTHERM Received "; - # for(my $i=0;$i<19;$i++){ - # my $j=int(ord(substr($res,$i,1))/16); - # my $k=ord(substr($res,$i,1))%16; - # $res2.=sprintf "0x%1x%1x ",$j,$k; - # } - # Log 1, $res2; - #} - #-- process results - #$res="000000000".$res - # if(length($res)==10); my @data=split(//,$res); return "invalid data length, ".int(@data)." bytes" if (@data != 19);