2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-05-04 20:17:45 +00:00

git-svn-id: https://svn.fhem.de/fhem/trunk@2433 2b470e98-0d58-463d-a4d8-8e2adae1ed80

This commit is contained in:
pahenning 2013-01-04 12:12:41 +00:00
parent 2cac0b8811
commit 5a898baf40
6 changed files with 1154 additions and 1193 deletions

View File

@ -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 <name> OWAD [<model>] <ROM_ID> [interval]
#
# where <name> may be replaced by any name string
@ -42,20 +32,19 @@
# Additional attributes are defined in fhem.cfg, in some cases per channel, where <channel>=A,B,C,D
# Note: attributes are read only during initialization procedure - later changes are not used.
#
# attr <name> event on-change/on-update = when to write an event (default= on-update)
#
# attr <name> stateAL0 "<string>" = character string for denoting low normal condition, default is empty,
# overwritten by attribute setting green down triangle
# attr <name> stateAH0 "<string>" = character string for denoting high normal condition, default is empty,
# overwritten by attribute setting green up triangle
# attr <name> stateAL1 "<string>" = character string for denoting low alarm condition, default is l,
# overwritten by attributre setting red down triangle
# attr <name> stateAH1 "<string>" = character string for denoting high alarm condition, default is h,
# overwritten by attributre setting red up triangle
# attr <name> stateAL0 "<string>" = character string for denoting low normal condition, default is empty
# attr <name> stateAH0 "<string>" = character string for denoting high normal condition, default is empty
# attr <name> stateAL1 "<string>" = character string for denoting low alarm condition, default is down triangle
# attr <name> stateAH1 "<string>" = character string for denoting high alarm condition, default is up triangle
# 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
#
# ATTENTION: Usage of Offset/Factor is deprecated, replace by Function attribute
# 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>Function <string> = arbitrary functional expression involving the values V<channel>=VA,VB,VC,VD
# VA is replaced by the measured voltage in channel A, etc.
#
# 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
@ -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 <span style=\"color:red\">&#x25BE;</span>")
if( !defined($attr{$name}{"stateAL1"} ));
CommandAttr (undef,"$name stateAH1 <span style=\"color:red\">&#x25B4;</span>")
if( !defined($attr{$name}{"stateAH1"} ));
CommandAttr (undef,"$name stateAL0 <span style=\"color:green\">&#x25BE;</span>")
if( !defined($attr{$name}{"stateAL0"} ));
CommandAttr (undef,"$name stateAH0 <span style=\"color:green\">&#x25B4;</span>")
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<int(@owg_fixed);$i++) {
@ -288,19 +270,14 @@ sub OWAD_InitializeDevice($) {
Log 1, "OWAD: Incomplete channel unit specification $unit. Better use $unit|<abbreviation>";
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<int(@owg_fixed);$k++ ){
$vfuncall .= "\$owg_val[$k]=$owg_val[$k];";
}
my $galarm = 0;
my $tn = TimeNow();
#-- alarm signatures
my $stateal1 = defined($attr{$name}{stateAL1}) ? $attr{$name}{stateAL1} : "l";
my $stateah1 = defined($attr{$name}{stateAH1}) ? $attr{$name}{stateAH1} : "h";
my $stateal1 = defined($attr{$name}{stateAL1}) ? $attr{$name}{stateAL1} : "&#x25BE;";
my $stateah1 = defined($attr{$name}{stateAH1}) ? $attr{$name}{stateAH1} : "&#x25B4;";
my $stateal0 = defined($attr{$name}{stateAL0}) ? $attr{$name}{stateAL0} : "";
my $stateah0 = defined($attr{$name}{stateAH0}) ? $attr{$name}{stateAH0} : "";
#-- put into READINGS
readingsBeginUpdate($hash);
#-- formats for output
for (my $i=0;$i<int(@owg_fixed);$i++){
my $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : $owg_fixed[$i]."|voltage";
my @cnama = split(/\|/,$cname);
$owg_channel[$i]=$cnama[0];
$offset = $hash->{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<int(@owg_fixed);$k++ ){
my $sstr = "V$owg_fixed[$k]";
$vfunc =~ s/$sstr/\$owg_val[$k]/g;
}
#-- insert comma
#-- 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;
#-- determine the measured value from the function
$vfunc = $vfuncall.$vfunc;
#Log 1, "After completion vfunc= ".$vfunc;
$vfunc = eval($vfunc);
if( !$vfunc ){
$vval = 0.0;
} elsif( $vfunc ne "" ){
$vval = int( $vfunc*1000 )/1000;
}
#Log 1," And finally after evaluation $vfunc";
#-- string buildup for return value, STATE and alarm
$svalue .= sprintf( "%s: %5.3f %s", $owg_channel[$i], $vval,$hash->{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<int(@owg_fixed)-1 ){
$value1 .= " ";
$value2 .= ", ";
$value3 .= ", ";
$svalue .= " ";
}
}
#-- STATE
$hash->{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<int(@owg_fixed);$i++){
$value .= sprintf "%s:[%4.2f,%4.2f] ",$owg_channel[$i],
$hash->{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<int(@owg_fixed);$i++){
$value .= $owg_channel[$i].": ".$owg_mode[$i].", ";
#$value .= "disabled ,"
# if ( !($sb2 && 128) );
$value .= sprintf "raw range %3.1f V, ",$owg_range[$i]/1000;
$value .= sprintf "resolution %d bit, ",$owg_resoln[$i];
$value .= sprintf "low alarm disabled, "
if( $owg_slow[$i]==0 );
$value .= sprintf "low alarm enabled, "
if( $owg_slow[$i]==1 );
$value .= sprintf "alarmed low, "
if( $owg_slow[$i]==2 );
$value .= sprintf "high alarm disabled"
if( $owg_shigh[$i]==0 );
$value .= sprintf "high alarm enabled"
if( $owg_shigh[$i]==1 );
$value .= sprintf "alarmed high"
if( $owg_shigh[$i]==2 );
#-- insert space
if( $i<int(@owg_fixed)-1 ){
$value .= "\n";
}
}
return "OWAD: $name.status => ".$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<int(@owg_fixed);$i++){
$owg_val[$i]= int((ord($data[12+2*$i])+256*ord($data[13+2*$i]))/((1<<$owg_resoln[$i])-1) * $owg_range[$i])/1000;
$owg_val[$i]= int((ord($data[3+2*$i])+256*ord($data[4+2*$i]))/((1<<$owg_resoln[$i])-1) * $owg_range[$i])/1000;
}
#=============== get the alarm reading ===============================
} elsif ( $page eq "alarm" ) {
for( $i=0;$i<int(@owg_fixed);$i++){
$owg_vlow[$i] = int(ord($data[12+2*$i])/255 * $owg_range[$i])/1000;
$owg_vhigh[$i] = int(ord($data[13+2*$i])/255 * $owg_range[$i])/1000;
$owg_vlow[$i] = int(ord($data[3+2*$i])/255 * $owg_range[$i])/1000;
$owg_vhigh[$i] = int(ord($data[4+2*$i])/255 * $owg_range[$i])/1000;
}
#=============== get the status reading ===============================
} elsif ( $page eq "status" ) {
my ($sb1,$sb2);
for( $i=0;$i<int(@owg_fixed);$i++){
$sb1 = ord($data[12+2*$i]);
$sb2 = ord($data[12+2*$i+1]);
$sb1 = ord($data[3+2*$i]);
$sb2 = ord($data[3+2*$i+1]);
#-- normal operation
if( $sb1 && 128) {
@ -934,26 +966,7 @@ sub OWXAD_GetPage($$) {
$owg_shigh[$i] = 2;
}
}
#-- assemble status string
$owg_status[$i] = $owg_mode[$i].", ";
$owg_status[$i] .= "disabled ,"
if ( !($sb2 && 128) );
$owg_status[$i] .= sprintf "raw range %3.1f V, ",$owg_range[$i]/1000;
$owg_status[$i] .= sprintf "resolution %d bit, ",$owg_resoln[$i];
$owg_status[$i] .= sprintf "low alarm disabled, "
if( $owg_slow[$i]==0 );
$owg_status[$i] .= sprintf "low alarm enabled, "
if( $owg_slow[$i]==1 );
$owg_status[$i] .= sprintf "alarmed low, "
if( $owg_slow[$i]==2 );
$owg_status[$i] .= sprintf "high alarm disabled"
if( $owg_shigh[$i]==0 );
$owg_status[$i] .= sprintf "high alarm enabled"
if( $owg_shigh[$i]==1 );
$owg_status[$i] .= sprintf "alarmed high"
if( $owg_shigh[$i]==2 );
#-- output operation
} else {
$owg_mode[$i] = "output";
#-- assemble status string
@ -991,13 +1004,13 @@ sub OWXAD_SetPage($$) {
#-- issue the match ROM command \x55 and the set alarm page command
# \x55\x10\x00 reading 8 data bytes and 2 CRC bytes
$select="\x55\x10\x00";
for( $i=0;$i<4;$i++){
for( $i=0;$i<int(@owg_fixed);$i++){
$select .= sprintf "%c\xFF\xFF\xFF",int($owg_vlow[$i]*255000/$owg_range[$i]);
$select .= sprintf "%c\xFF\xFF\xFF",int($owg_vhigh[$i]*255000/$owg_range[$i]);
}
#=============== set the status ===============================
} elsif ( $page eq "status" ) {
my ($sb1,$sb2);
my ($sb1,$sb2)=(0,0);
#-- issue the match ROM command \x55 and the set status memory page command
# \x55\x08\x00 reading 8 data bytes and 2 CRC bytes
$select="\x55\x08\x00";
@ -1005,9 +1018,13 @@ sub OWXAD_SetPage($$) {
if( $owg_mode[$i] eq "input" ){
#-- resolution (TODO: check !)
$sb1 = $owg_resoln[$i]-1;
#-- alarm enabled
$sb2 = ( $owg_slow[$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
<a name="OWAD"></a>
<h3>OWAD</h3>
<ul>FHEM module to commmunicate with 1-Wire A/D converters<br /><br /> Note:<br /> This
1-Wire module so far works only with the OWX interface module. Please define an <a
href="#OWX">OWX</a> device first. <br />
<br /><b>Example</b><br />
<ul>
<code>define OWX_AD OWAD 724610000000 45</code>
<br />
<code>attr OWX_AD DAlarm high</code>
<br />
<code>attr OWX_AD DFactor 31.907097</code>
<br />
<code>attr OWX_AD DHigh 50.0</code>
<br />
<code>attr OWX_AD DName relHumidity|humidity</code>
<br />
<code>attr OWX_AD DOffset -0.8088</code>
<br />
<code>attr OWX_AD DUnit percent|%</code>
<br />
</ul><br />
<a name="OWADdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; OWAD [&lt;model&gt;] &lt;id&gt; [&lt;interval&gt;]</code>
<br /><br /> Define a 1-Wire A/D converter.<br /><br />
<li>
<code>[&lt;model&gt;]</code><br /> Defines the A/D converter model (and thus
1-Wire family id), currently the following values are permitted: <ul>
<li>model DS2450 with family id 20 (default if the model parameter is
omitted)</li>
</ul>
</li>
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and
CRC code </li>
<li>
<code>&lt;interval&gt;</code>
<br />Measurement interval in seconds. The default is 300 seconds. </li>
<br />
</ul>
<br />
<a name="OWADset">
<b>Set</b></a>
<ul>
<li><a name="owad_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds. </li>
</ul>
<br />
<a name="OWADget">
<b>Get</b></a>
<ul>
<li><a name="owad_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owad_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owad_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval
in seconds. </li>
<li><a name="owad_reading">
<code>get &lt;name&gt; reading</code></a><br />Obtain the measuement values. </li>
<li><a name="owad_alarm">
<code>get &lt;name&gt; alarm</code></a><br />Obtain the alarm values. </li>
<li><a name="owad_status">
<code>get &lt;name&gt; status</code></a><br />Obtain the i/o status values.
</li>
</ul>
<br />
<a name="OWADattr">
<b>Attributes</b></a>
<ul>
<li><a name="owad_stateAL0"><code>attr &lt;name&gt; stateAL0
&lt;string&gt;</code></a>
<br />character string for denoting low normal condition, default is green down
triangle, e.g. the code &lt;span
style="color:green"&gt;&amp;#x25BE;&lt;/span&gt; leading to the sign <span
style="color:green">&#x25BE;</span>
</li>
<li><a name="owad_stateAH0"><code>attr &lt;name&gt; stateAH0
&lt;string&gt;</code></a>
<br />character string for denoting high alarm condition, default is green
upward triangle, e.g. the code &lt;span
style="color:green"&gt;&amp;#x25B4;&lt;/span&gt; leading to the sign <span
style="color:green">&#x25B4;</span>
</li>
<li><a name="owad_stateAL1"><code>attr &lt;name&gt; stateAL1
&lt;string&gt;</code></a>
<br />character string for denoting low alarm condition, default is red down
triangle, e.g. the code &lt;span style="color:red"&gt;&amp;#x25BE;&lt;/span&gt;
leading to the sign <span style="color:red">&#x25BE;</span></li>
<li><a name="owad_stateAH1"><code>attr &lt;name&gt; stateAH1
&lt;string&gt;</code></a>
<br />character string for denoting high alarm condition, default is red upward
triangle, e.g. the code &lt;span style="color:red"&gt;&amp;#x25B4;&lt;/span&gt;
leading to the sign <span style="color:red">&#x25B4;</span>
</li>
</ul> For each of the following attributes, the channel identification A,B,C,D may be
used. <ul>
<li><a name="owad_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
&lt;string&gt;|&lt;string&gt;</code></a>
<br />name for the channel | a type description for the measured value. </li>
<li><a name="owad_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit
&lt;string&gt;|&lt;string&gt;</code></a>
<br />unit of measurement for this channel | its abbreviation. </li>
<li><a name="owad_coffset"><code>attr &lt;name&gt; &lt;channel&gt;Offset
&lt;float&gt;</code></a>
<br />offset added to the reading in this channel. </li>
<li><a name="owad_cfactor"><code>attr &lt;name&gt; &lt;channel&gt;Factor
&lt;float&gt;</code></a>
<br />factor multiplied to (reading+offset) in this channel. </li>
<li><a name="owad_calarm"><code>attr &lt;name&gt; &lt;channel&gt;Alarm
&lt;string&gt;</code></a>
<br />alarm setting in this channel, either both, low, high or none (default). </li>
<li><a name="owad_clow"><code>attr &lt;name&gt; &lt;channel&gt;Low
&lt;float&gt;</code></a>
<br />measurement value (on the scale determined by offset and factor) for low
alarm. </li>
<li><a name="owad_chigh"><code>attr &lt;name&gt; &lt;channel&gt;High
&lt;float&gt;</code></a>
<br />measurement value (on the scale determined by offset and factor) for high
alarm. </li>
<li><a name="owad_event"><code>attr &lt;name&gt; event on-change|on-update
</code></a>This attribte work similarly, but not identically to the standard event-on-update-change/event-on-update-reading attribute.
<ul><li><code>event on-update</code> (default) will write a notify/FileLog event any time a measurement is received.</li>
<li><code>event on-change</code> will write a notify/FileLog event only when a measurement is different from the previous one.</li>
<p>FHEM module to commmunicate with 1-Wire A/D converters<br /><br /> Note:<br /> This
1-Wire module so far works only with the OWX interface module. Please define an <a
href="#OWX">OWX</a> device first. <br /></p>
<br /><h4>Example</h4>
<p>
<code>define OWX_AD OWAD 724610000000 45</code>
<br />
<code>attr OWX_AD DAlarm high</code>
<br />
<code>attr OWX_AD DFactor 31.907097</code>
<br />
<code>attr OWX_AD DHigh 50.0</code>
<br />
<code>attr OWX_AD DName RelHumidity|humidity</code>
<br />
<code>attr OWX_AD DOffset -0.8088</code>
<br />
<code>attr OWX_AD DUnit percent|%</code>
<br />
</p><br />
<a name="OWADdefine"></a>
<h4>Define</h4>
<p>
<code>define &lt;name&gt; OWAD [&lt;model&gt;] &lt;id&gt; [&lt;interval&gt;]</code>
<br /><br /> Define a 1-Wire A/D converter.<br /><br /></p>
<ul>
<li>
<code>[&lt;model&gt;]</code><br /> Defines the A/D converter model (and thus 1-Wire
family id), currently the following values are permitted: <ul>
<li>model DS2450 with family id 20 (default if the model parameter is
omitted)</li>
</ul>
</li>
<li>Standard attributes alias, comment, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>, <a href="#webCmd">webCmd</a></li>
</ul>
</ul>
</li>
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and CRC
code </li>
<li>
<code>&lt;interval&gt;</code>
<br />Measurement interval in seconds. The default is 300 seconds. </li>
</ul>
<br />
<a name="OWADset"></a>
<h4>Set</h4>
<ul>
<li><a name="owad_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds. </li>
</ul>
<br />
<a name="OWADget"></a>
<h4>Get</h4>
<ul>
<li><a name="owad_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owad_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owad_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval in
seconds. </li>
<li><a name="owad_reading">
<code>get &lt;name&gt; reading</code></a><br />Obtain the measuement values. </li>
<li><a name="owad_alarm">
<code>get &lt;name&gt; alarm</code></a><br />Obtain the alarm values. </li>
<li><a name="owad_status">
<code>get &lt;name&gt; status</code></a><br />Obtain the i/o status values.
</li>
</ul>
<br />
<a name="OWADattr"></a>
<h4>Attributes</h4>
<ul>
<li><a name="owad_stateAL0"><code>attr &lt;name&gt; stateAL0 &lt;string&gt;</code></a>
<br />character string for denoting low normal condition, default is empty </li>
<li><a name="owad_stateAH0"><code>attr &lt;name&gt; stateAH0 &lt;string&gt;</code></a>
<br />character string for denoting high normal condition, default is empty </li>
<li><a name="owad_stateAL1"><code>attr &lt;name&gt; stateAL1 &lt;string&gt;</code></a>
<br />character string for denoting low alarm condition, default is down triangle,
e.g. the code &amp;#x25BE; leading to the sign &#x25BE;</li>
<li><a name="owad_stateAH1"><code>attr &lt;name&gt; stateAH1 &lt;string&gt;</code></a>
<br />character string for denoting high alarm condition, default is upward
triangle, e.g. the code &amp;#x25B4; leading to the sign &#x25B4; </li>
</ul> For each of the following attributes, the channel identification A,B,C,D may be used. <ul>
<li><a name="owad_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
&lt;string&gt;|&lt;string&gt;</code></a>
<br />name for the channel | a type description for the measured value. </li>
<li><a name="owad_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit
&lt;string&gt;|&lt;string&gt;</code></a>
<br />unit of measurement for this channel | its abbreviation. </li>
<li><a name="owad_coffset"><b>deprecated</b>: <code>attr &lt;name&gt; &lt;channel&gt;Offset
&lt;float&gt;</code></a>
<br />offset added to the reading in this channel. </li>
<li><a name="owad_cfactor"><b>deprecated</b>: <code>attr &lt;name&gt; &lt;channel&gt;Factor
&lt;float&gt;</code></a>
<br />factor multiplied to (reading+offset) in this channel. </li>
<li><a name="owad_cfunction"> <code>attr &lt;name&gt; &lt;channel&gt;Function
&lt;string&gt;</code></a>
<br />arbitrary functional expression involving the values VA,VB,VC,VD. VA is replaced by
the measured voltage in channel A, etc. This attribute allows linearization of measurement
curves as well as the mixing of various channels. <b>Replacement for Offset/Factor !</b>
<li><a name="owad_calarm"><code>attr &lt;name&gt; &lt;channel&gt;Alarm
&lt;string&gt;</code></a>
<br />alarm setting in this channel, either both, low, high or none (default). </li>
<li><a name="owad_clow"><code>attr &lt;name&gt; &lt;channel&gt;Low
&lt;float&gt;</code></a>
<br />measurement value (on the scale determined by offset and factor) for low
alarm. </li>
<li><a name="owad_chigh"><code>attr &lt;name&gt; &lt;channel&gt;High
&lt;float&gt;</code></a>
<br />measurement value (on the scale determined by offset and factor) for high
alarm. </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
</ul>
=end html
=cut

View File

@ -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 <name> OWID <FAM_ID> <ROM_ID>
#
@ -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
<a name="OWID"></a>
<h3>OWID</h3>
<ul>FHEM module for 1-Wire devices that know only their unique ROM ID<br />
<br />Note:<br /> This 1-Wire module so far works only with the OWX interface module.
Please define an <a href="#OWX">OWX</a> device first. <br />
<br /><b>Example</b><br />
<ul>
<code>define ROM1 OWX_ID OWCOUNT CE780F000000</code>
<a name="OWID"></a>
<h3>OWID</h3>
<p>FHEM module for 1-Wire devices that know only their unique ROM ID<br />
<br />Note:<br /> This 1-Wire module so far works only with the OWX interface module.
Please define an <a href="#OWX">OWX</a> device first. <br /></p>
<br /><h4>Example</h4><br />
<p>
<code>define ROM1 OWX_ID OWCOUNT CE780F000000</code>
<br />
</p><br />
<a name="OWIDdefine"></a>
<h4>Define</h4>
<p>
<code>define &lt;name&gt; OWID &lt;id&gt; </code>
<br /><br /> Define a 1-Wire device.<br /><br />
</p>
<ul>
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and CRC
code </li>
</ul>
<br />
</ul><br />
<a name="OWIDdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; OWID &lt;id&gt; </code>
<br /><br /> Define a 1-Wire device.<br /><br />
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and
CRC code </li>
</ul>
<br />
<a name="OWIDget">
<b>Get</b></a>
<ul>
<li><a name="owid_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owid_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
</ul>
<br />
</ul>
<a name="OWIDget"></a>
<h4>Get</h4>
<ul>
<li><a name="owid_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owid_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
</ul>
=end html
=cut

View File

@ -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 <name> OWLCD <ROM_ID>
#
@ -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/.*\&deg\;.*/ ) {
my @ma = split(/\&deg\;/,$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/.*\&deg\;.*/ ) {
my @ma = split(/\&deg\;/,$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
<a name="OWLCD"></a>
<h3>OWLCD</h3>
<ul>FHEM module to commmunicate with the <a
href="http://www.louisswart.co.za/1-Wire_Overview.html">1-Wire LCD controller</a>
from Louis Swart (1-Wire family id FF). See also the corresponding <a
href="http://fhemwiki.de/wiki/1-Wire_Textdisplay">Wiki page.</a><br /><br />
Note:<br /> This 1-Wire module so far works only with the OWX interface module. Please
define an <a href="#OWX">OWX</a> device first. <br />
<br /><b>Example</b><br />
<ul>
<code>define OWX_LCD OWLCD 9F0700000100</code>
<a name="OWLCD"></a>
<h3>OWLCD</h3>
<p>FHEM module to commmunicate with the <a
href="http://www.louisswart.co.za/1-Wire_Overview.html">1-Wire LCD controller</a>
from Louis Swart (1-Wire family id FF). See also the corresponding <a
href="http://fhemwiki.de/wiki/1-Wire_Textdisplay">Wiki page.</a><br /><br />
Note:<br /> This 1-Wire module so far works only with the OWX interface module. Please
define an <a href="#OWX">OWX</a> device first. <br /></p>
<br /><h4>Example</h4>
<p>
<code>define OWX_LCD OWLCD 9F0700000100</code>
<br />
</p>
<br />
</ul>
<br />
<a name="OWLCDdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; OWLCD &lt;id&gt;</code>
<br /><br /> Define a 1-Wire LCD device.<br /><br />
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and
CRC code </li>
</ul>
<br />
<a name="OWLCDset">
<b>Set</b></a>
<ul>
<li><a name="owlcd_icon">
<code>set &lt;name&gt; icon &lt;int&gt; on|off|blink</code></a><br /> Set
one of the icons 0..14 on, off or blinking</li>
<li><a name="owlcd_icon2">
<code>set &lt;name&gt; icon 15 0..6</code></a><br /> Set icon 15 to one of
its values</li>
<li><a name="owlcd_icon3">
<code>set &lt;name&gt; icon none</code></a><br /> Set all icons off</li>
<li><a name="owlcd_line">
<code>set &lt;name&gt; line &lt;int&gt; &lt;string&gt;</code></a><br />
Write LCD line 0..3 with some content </li>
<li><a name="owlcd_memory">
<code>set &lt;name&gt; memory &lt;page&gt;
&lt;string&gt;</code></a><br />Write memory page 0..6</li>
<li><a name="owlcd_gpio">
<code>set &lt;name&gt; gpio &lt;value&gt;</code></a><br />Write state for
all three gpio pins (value = 0..7, for each bit 0=ON, 1=OFF)</li>
<li><a name="owlcd_bl">
<code>set &lt;name&gt; backlight ON|OFF</code></a><br />Switch backlight on
or off</li>
<li><a name="owlcd_lcd">
<code>set &lt;name&gt; lcd ON|OFF</code></a><br />Switch LCD power on or
off</li>
<li><a name="owlcd_gpio">
<code>set &lt;name&gt; reset</code></a><br />Reset the display</li>
<li><a name="owlcd_gpio">
<code>set &lt;name&gt; test</code></a><br />Test the display</li>
</ul>
<br />
<a name="owlcdget">
<b>Get</b></a>
<ul>
<li><a name="owlcd_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owlcd_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owlcd_memory2">
<code>get &lt;name&gt; memory &lt;page&gt;</code></a><br />Read memory page
0..6 </li>
<li><a name="owlcd_gpio">
<code>get &lt;name&gt; gpio</code></a><br />Obtain state of all four input
channels (15 = all off, 0 = all on)</li>
<li><a name="owlcd_counter">
<code>get &lt;name&gt; gpio</code></a><br />Obtain state of all four input
counters (4 x 16 Bit)</li>
<li><a name="owlcd_version">
<code>get &lt;name&gt; version</code></a><br />Obtain firmware version of
the controller</li>
</ul>
<br />
<a name="owlcdattr">
<b>Attributes</b></a>
<ul>
<li>Standard attributes alias, comment, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>, <a href="#webCmd">webCmd</a></li>
</ul>
</ul>
<a name="OWLCDdefine"></a>
<h4>Define</h4>
<p>
<code>define &lt;name&gt; OWLCD &lt;id&gt;</code>
<br /><br /> Define a 1-Wire LCD device.<br /><br /></p>
<ul>
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and CRC
code </li>
</ul>
<br />
<a name="OWLCDset"></a>
<h4>Set</h4>
<ul>
<li><a name="owlcd_icon">
<code>set &lt;name&gt; icon &lt;int&gt; on|off|blink</code></a><br /> Set one of
the icons 0..14 on, off or blinking</li>
<li><a name="owlcd_icon2">
<code>set &lt;name&gt; icon 15 0..6</code></a><br /> Set icon 15 to one of its
values</li>
<li><a name="owlcd_icon3">
<code>set &lt;name&gt; icon none</code></a><br /> Set all icons off</li>
<li><a name="owlcd_line">
<code>set &lt;name&gt; line &lt;int&gt; &lt;string&gt;</code></a><br /> Write
LCD line 0..3 with some content </li>
<li><a name="owlcd_memory">
<code>set &lt;name&gt; memory &lt;page&gt; &lt;string&gt;</code></a><br />Write
memory page 0..6</li>
<li><a name="owlcd_gpio">
<code>set &lt;name&gt; gpio &lt;value&gt;</code></a><br />Write state for all
three gpio pins (value = 0..7, for each bit 0=ON, 1=OFF)</li>
<li><a name="owlcd_bl">
<code>set &lt;name&gt; backlight ON|OFF</code></a><br />Switch backlight on or
off</li>
<li><a name="owlcd_lcd">
<code>set &lt;name&gt; lcd ON|OFF</code></a><br />Switch LCD power on or
off</li>
<li><a name="owlcd_gpio">
<code>set &lt;name&gt; reset</code></a><br />Reset the display</li>
<li><a name="owlcd_gpio">
<code>set &lt;name&gt; test</code></a><br />Test the display</li>
</ul>
<br />
<a name="owlcdget"></a>
<h4>Get</h4>
<ul>
<li><a name="owlcd_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owlcd_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owlcd_memory2">
<code>get &lt;name&gt; memory &lt;page&gt;</code></a><br />Read memory page 0..6 </li>
<li><a name="owlcd_gpio">
<code>get &lt;name&gt; gpio</code></a><br />Obtain state of all four input
channels (15 = all off, 0 = all on)</li>
<li><a name="owlcd_counter">
<code>get &lt;name&gt; gpio</code></a><br />Obtain state of all four input
counters (4 x 16 Bit)</li>
<li><a name="owlcd_version">
<code>get &lt;name&gt; version</code></a><br />Obtain firmware version of the
controller</li>
</ul>
<br />
<a name="owlcdattr"></a>
<h4>Attributes</h4>
<ul>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#room">room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel"
>loglevel</a>, <a href="#webCmd">webCmd</a></li>
</ul>
=end html
=cut
=cut

View File

@ -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 <name> OWMULTI [<model>] <ROM_ID> [interval]
#
@ -38,8 +34,6 @@
# Additional attributes are defined in fhem.cfg
# Note: attributes "tempXXXX" are read during every update operation.
#
# attr <name> event on-change/on-update = when to write an event (default= on-update)
#
# attr <name> tempOffset <float> = temperature offset in degree Celsius added to the raw temperature reading
# attr <name> tempUnit <string> = unit of measurement, e.g. Celsius/Kelvin/Fahrenheit or C/K/F, default is Celsius
# attr <name> VName <string>|<string> = 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<length($res);$i++){
# my $j=int(ord(substr($res,$i,1))/16);
# my $k=ord(substr($res,$i,1))%16;
# $res2.=sprintf "0x%1x%1x ",$j,$k;
# }
# Log 1, $res2;
#-- process results
my @data=split(//,$res);
return "invalid data length, ".int(@data)." bytes"
if (@data != 20);
my @data=split(//,substr($res,9));
return "invalid data length, ".int(@data)." instead of 11 bytes"
if (@data != 11);
return "conversion not complete or data invalid"
if ((ord($data[11]) & 112)!=0);
#return "invalid CRC"
# if (OWX_CRC8(substr($res,10,8),$data[18])==0);
if ((ord($data[2]) & 112)!=0);
return "invalid CRC"
if (OWX_CRC8(substr($res,11,8),$data[10])==0);
#-- this must be different for the different device types
# family = 26 => 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<length($res);$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
@data=split(//,$res);
return "invalid data length, ".int(@data)." bytes"
if (@data != 20);
@data=split(//,substr($res,9));
return "invalid data length, ".int(@data)." instead of 11 bytes"
if (@data != 11);
return "conversion not complete or data invalid"
if ((ord($data[11]) & 112)!=0);
#return "invalid CRC"
# if (OWX_CRC8(substr($res,10,8),$data[18])==0);
if ((ord($data[2]) & 112)!=0);
return "invalid CRC"
if (OWX_CRC8(substr($res,11,8),$data[10])==0);
#-- this must be different for the different device types
# family = 26 => 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
<a name="OWMULTI"></a>
<h3>OWMULTI</h3>
<p>FHEM module to commmunicate with 1-Wire multi-sensors, currently the DS2438 smart battery
monitor<br /><br /> Note:<br /> This 1-Wire module so far works only with the OWX
interface module. Please define an <a href="#OWX">OWX</a> device first. <br /></p>
<br /><h4>Example</h4>
<p>
<code>define OWX_M OWMULTI 7C5034010000 45</code>
<br />
<code>attr OWX_M VName relHumidity|humidity</code>
<br />
<code>attr OWX_M VUnit percent|%</code>
<br />
<code>attr OWX_M VFunction (161.29 * V / VDD - 25.8065)/(1.0546 - 0.00216 * T)</code>
<br />
</p><br />
<a name="OWMULTIdefine"></a>
<h4>Define</h4>
<p>
<code>define &lt;name&gt; OWMULTI [&lt;model&gt;] &lt;id&gt; [&lt;interval&gt;]</code>
<br /><br /> Define a 1-Wire multi-sensor<br /><br /></p>
<ul>
<li>
<code>[&lt;model&gt;]</code><br /> Defines the sensor model (and thus 1-Wire family
id), currently the following values are permitted: <ul>
<li>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</li>
</ul>
</li>
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and CRC
code </li>
<li>
<code>&lt;interval&gt;</code>
<br />Measurement interval in seconds. The default is 300 seconds. </li>
</ul>
<br />
<a name="OWMULTIset"></a>
<h4>Set</h4>
<ul>
<li><a name="owmulti_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds. </li>
</ul>
<br />
<a name="OWMULTIget"></a>
<h4>Get</h4>
<ul>
<li><a name="owmulti_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owmulti_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owmulti_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval in
seconds. </li>
<li><a name="owmulti_reading">
<code>get &lt;name&gt; reading</code></a><br />Obtain the measurement value from
VFunction. </li>
<li><a name="owmulti_temperature">
<code>get &lt;name&gt; temperature</code></a><br />Obtain the temperature value. </li>
<li><a name="owmulti_vdd">
<code>get &lt;name&gt; VDD</code></a><br />Obtain the current supply voltage. </li>
<li><a name="owmulti_raw">
<code>get &lt;name&gt; V</code> or <code>get &lt;name&gt;
raw</code></a><br />Obtain the raw external voltage measurement. </li>
</ul>
<br />
<a name="OWMULTIattr"></a>
<h4>Attributes</h4>
<ul>
<li><a name="owmulti_vname"><code>attr &lt;name&gt; VName
&lt;string&gt;|&lt;string&gt;</code></a>
<br />name for the channel | a type description for the measured value. </li>
<li><a name="owmulti_vunit"><code>attr &lt;name&gt; VUnit
&lt;string&gt;|&lt;string&gt;</code></a>
<br />unit of measurement for this channel | its abbreviation. </li>
<li><a name="owmulti_vfunction"><code>attr &lt;name&gt; VFunction
&lt;string&gt;</code></a>
<br />arbitrary functional expression involving the values VDD, V, T. Example see
above. <ul>
<li>VDD is replaced by the measured supply voltage in Volt,</li>
<li> V by the measured external voltage,</li>
<li>T by the measured and corrected temperature in its unit</li>
</ul></li>
<li><a name="owmulti_tempOffset"><code>attr &lt;name&gt; tempOffset &lt;float&gt;</code>
</a>
<br />temperature offset in &deg;C added to the raw temperature reading. </li>
<li><a name="owmulti_tempUnit"><code>attr &lt;name&gt; tempUnit
Celsius|Kelvin|Fahrenheit|C|K|F</code>
</a>
<br />unit of measurement (temperature scale), default is Celsius = &deg;C </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
<a name="OWMULTI"></a>
<h3>OWMULTI</h3>
<ul>FHEM module to commmunicate with 1-Wire multi-sensors, currently the DS2438 smart battery monitor<br /><br /> Note:<br /> This
1-Wire module so far works only with the OWX interface module. Please define an <a
href="#OWX">OWX</a> device first. <br />
<br /><b>Example</b><br />
<ul>
<code>define OWX_M OWMULTI 7C5034010000 45</code>
<br />
<code>attr OWX_M VName relHumidity|humidity</code>
<br />
<code>attr OWX_M VUnit percent|%</code>
<br />
<code>attr OWX_M VFunction (161.29 * V / VDD - 25.8065)/(1.0546 - 0.00216 * T)</code>
<br />
</ul><br />
<a name="OWMULTIdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; OWMULTI [&lt;model&gt;] &lt;id&gt; [&lt;interval&gt;]</code>
<br /><br /> Define a 1-Wire multi-sensor<br /><br />
<li>
<code>[&lt;model&gt;]</code><br /> Defines the sensor model (and thus
1-Wire family id), currently the following values are permitted: <ul>
<li>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</li>
</ul>
</li>
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and
CRC code </li>
<li>
<code>&lt;interval&gt;</code>
<br />Measurement interval in seconds. The default is 300 seconds. </li>
<br />
</ul>
<br />
<a name="OWMULTIset">
<b>Set</b></a>
<ul>
<li><a name="owmulti_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds. </li>
</ul>
<br />
<a name="OWMULTIget">
<b>Get</b></a>
<ul>
<li><a name="owmulti_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owmulti_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owmulti_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval
in seconds. </li>
<li><a name="owmulti_reading">
<code>get &lt;name&gt; reading</code></a><br />Obtain the measurement value from VFunction. </li>
<li><a name="owmulti_temperature">
<code>get &lt;name&gt; temperature</code></a><br />Obtain the temperature value. </li>
<li><a name="owmulti_vdd">
<code>get &lt;name&gt; VDD</code></a><br />Obtain the current supply voltage.
</li>
<li><a name="owmulti_raw">
<code>get &lt;name&gt; V</code> or <code>get &lt;name&gt; raw</code></a><br />Obtain the raw external voltage measurement.
</li>
</ul>
<br />
<a name="OWMULTIattr">
<b>Attributes</b></a>
<ul>
<li><a name="owmulti_vname"><code>attr &lt;name&gt; VName
&lt;string&gt;|&lt;string&gt;</code></a>
<br />name for the channel | a type description for the measured value. </li>
<li><a name="owmulti_vunit"><code>attr &lt;name&gt; VUnit
&lt;string&gt;|&lt;string&gt;</code></a>
<br />unit of measurement for this channel | its abbreviation. </li>
<li><a name="owmulti_vfunction"><code>attr &lt;name&gt; VFunction
&lt;string&gt;</code></a>
<br />arbitrary functional expression involving the values VDD, V, T. Example see above.
<ul>
<li>VDD is replaced by the measured supply voltage in Volt,</li>
<li> V by the measured external voltage,</li>
<li>T by the measured and corrected temperature in its unit</li>
</ul></li>
<li><a name="owmulti_tempOffset"><code>attr &lt;name&gt; tempOffset
&lt;float&gt;</code>
</a>
<br />temperature offset in &deg;C added to the raw temperature reading. </li>
<li><a name="owmulti_tempUnit"><code>attr &lt;name&gt; tempUnit
Celsius|Kelvin|Fahrenheit|C|K|F</code>
</a>
<br />unit of measurement (temperature scale), default is Celsius = &deg;C </li>
<li><a name="owmulti_event"><code>attr &lt;name&gt; event on-change|on-update
</code></a>This attribte work similarly, but not identically to the standard event-on-update-change/event-on-update-reading attribute.
<ul><li><code>event on-update</code> (default) will write a notify/FileLog event any time a measurement is received.</li>
<li><code>event on-change</code> will write a notify/FileLog event only when a measurement is different from the previous one.</li>
</ul>
</li>
<li>Standard attributes alias, comment, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>, <a href="#webCmd">webCmd</a></li>
</ul>
</ul>
</ul>
=end html
=cut
=cut

View File

@ -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 <name> OWSWITCH [<model>] <ROM_ID> [interval]
#
@ -42,16 +31,17 @@
# get <name> gpio => values for channels
#
# set <name> interval => set period for measurement
# set <name> output <channel-name> ON|OFF => set value for channel (name A, B or defined channel name)
# set <name> output <channel-name> on|off|on-for-timer <int>|on-for-timer <int>
# => 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 <int> seconds
# and then will return to the opposite value.
# set <name> gpio value => set values for channels (3 = both OFF, 1 = B ON 2 = A ON 0 = both ON)
# set <name> init yes => re-initialize device
#
# Additional attributes are defined in fhem.cfg, in some cases per channel, where <channel>=A,B
# Note: attributes are read only during initialization procedure - later changes are not used.
#
# attr <name> event on-change/on-update = when to write an event (default= on-update)
#
# attr <name> stateS <string> = 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 <span style=\"color:red\">&#x2607;</span>")
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"} : "&#x2607;";
#-- 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
<a name="OWSWITCH"></a>
<h3>OWSWITCH</h3>
<ul>FHEM module to commmunicate with 1-Wire Programmable Switches <br /><br /> Note:<br />
This 1-Wire module so far works only with the OWX interface module. Please define an <a
href="#OWX">OWX</a> device first. <br />
<br /><b>Example</b><br />
<ul>
<code>define OWX_S OWSWITCH DS2413 B5D502000000 60</code>
<body>
<h3>OWSWITCH</h3>
<p>FHEM module to commmunicate with 1-Wire Programmable Switches <br /><br /> Note:<br />
This 1-Wire module so far works only with the OWX interface module. Please define an <a
href="#OWX">OWX</a> device first. <br /></p>
<br /><h4>Example</h4>
<p>
<code>define OWX_S OWSWITCH DS2413 B5D502000000 60</code>
<br />
<code>attr OWX_S AName Lampe|light</code>
<br />
<code>attr OWX_S AUnit AN|AUS</code>
<br />
</p>
<br />
<code>attr OWX_S AName Lampe|light</code>
<a name="OWSWITCHdefine"></a>
<h4>Define</h4>
<p>
<code>define &lt;name&gt; OWSWITCH [&lt;model&gt;] &lt;id&gt; [&lt;interval&gt;]</code>
<br /><br /> Define a 1-Wire switch.<br /><br /></p>
<ul>
<li>
<code>[&lt;model&gt;]</code><br /> Defines the switch model (and thus 1-Wire family
id), currently the following values are permitted: <ul>
<li>model DS2413 with family id 3A (default if the model parameter is omitted).
2 Channel switch with onboard memory</li>
<li>model DS2406 with family id 12. 2 Channel switch </li>
<li>model DS2408 with family id 29. 8 Channel switch</li>
</ul>
</li>
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and CRC
code </li>
<li>
<code>&lt;interval&gt;</code>
<br />Measurement interval in seconds. The default is 300 seconds. </li>
</ul>
<a name="OWSWITCHset"></a>
<h4>Set</h4>
<ul>
<li><a name="owswitch_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds. </li>
<li><a name="owswitch_output">
<code>set &lt;name&gt; output &lt;channel-name&gt; on | off | on-for-timer &lt;time&gt; | off-for-timer &lt;time&gt;</code>
</a><br />Set
value for channel (A,B,... or defined channel name). 1 = off, 0 = on in normal
usage. See also the note above.<br/>
on-for-timer/off-for-timer will set the desired value only for the given time,
either given as hh:mm:ss or as integers seconds
and then will return to the opposite value.</li>
<li><a name="owswitch_gpio">
<code>set &lt;name&gt; gpio &lt;value&gt;</code></a><br />Set values for
channels (For 2 channels: 3 = A and B off, 1 = B on 2 = A on 0 = both on)</li>
<li><a name="owswitch_init">
<code>set &lt;name&gt; init yes</code></a><br /> Re-initialize the device</li>
</ul>
<br />
<code>attr OWX_S AUnit AN|AUS</code>
<a name="OWSWITCHget"></a>
<h4>Get</h4>
<ul>
<li><a name="owswitch_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owswitch_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owswitch_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval in
seconds. </li>
<li><a name="owswitch_input">
<code>get &lt;name&gt; input &lt;channel-name&gt;</code></a><br /> 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.</li>
<li><a name="owswitch_gpio">
<code>get &lt;name&gt; gpio</code></a><br />Obtain state of all channels</li>
</ul>
<br />
</ul>
<br />
<a name="OWSWITCHdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; OWSWITCH [&lt;model&gt;] &lt;id&gt;
[&lt;interval&gt;]</code>
<br /><br /> Define a 1-Wire switch.<br /><br />
<li>
<code>[&lt;model&gt;]</code><br /> Defines the switch model (and thus 1-Wire
family id), currently the following values are permitted: <ul>
<li>model DS2413 with family id 3A (default if the model parameter is
omitted). 2 Channel switch with onboard memory</li>
<li>model DS2406 with family id 12. 2 Channel switch </li>
<li>model DS2406 with family id 29. 8 Channel switch</li>
</ul>
</li>
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and
CRC code </li>
<li>
<code>&lt;interval&gt;</code>
<br />Measurement interval in seconds. The default is 300 seconds. </li>
</ul>
<br />
<a name="OWSWITCHset">
<b>Set</b></a>
<ul>
<li><a name="owswitch_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds. </li>
<li><a name="owswitch_output">
<code>set &lt;name&gt; output &lt;channel-name&gt; ON |
OFF</code></a><br />Set value for channel (A,B,... or defined channel name). 1 = OFF, 0 = ON in normal usage.
See also the note above</li>
<li><a name="owswitch_gpio">
<code>set &lt;name&gt; gpio &lt;value&gt;</code></a><br />Set values for channels (For 2 channels: 3 = A and B OFF, 1 = B ON 2 = A ON 0 = both ON)</li>
<li><a name="owswitch_init">
<code>set &lt;name&gt; init yes</code></a><br /> Re-initialize the device</li>
</ul>
<br />
<a name="OWSWITCHget">
<b>Get</b></a>
<ul>
<li><a name="owswitch_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owswitch_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owswitch_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval
in seconds. </li>
<li><a name="owswitch_input">
<code>get &lt;name&gt; input &lt;channel-name&gt;</code></a><br />
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.</li>
<li><a name="owswitch_gpio">
<code>get &lt;name&gt; gpio</code></a><br />Obtain state of all
channels</li>
</ul>
<br />
<a name="OWSWITCHattr">
<b>Attributes</b></a> For each of the following attributes, the channel
identification A,B,... may be used. <ul>
<li><a name="owswitch_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
&lt;string&gt;|&lt;string&gt;</code></a>
<br />name for the channel | a type description for the measured value. </li>
<li><a name="owswitch_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit
&lt;string&gt;|&lt;string&gt;</code></a>
<br />display for on | off condition </li>
<li><a name="owswitch_event"><code>attr &lt;name&gt; event on-change|on-update
</code></a>This attribte work similarly, but not identically to the standard event-on-update-change/event-on-update-reading attribute.
<ul><li><code>event on-update</code> (default) will write a notify/FileLog event any time a measurement is received.</li>
<li><code>event on-change</code> will write a notify/FileLog event only when a measurement is different from the previous one.</li>
</ul>
</li>
<li>Standard attributes alias, comment, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>, <a href="#webCmd">webCmd</a></li>
</ul>
</ul>
<a name="OWSWITCHattr"></a>
<h4>Attributes</h4> For each of the following attributes, the channel identification A,B,...
may be used. <ul>
<li><a name="owswitch_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
&lt;string&gt;|&lt;string&gt;</code></a>
<br />name for the channel | a type description for the measured value. </li>
<li><a name="owswitch_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit
&lt;string&gt;|&lt;string&gt;</code></a>
<br />display for on | off condition </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
</ul>
=end html
=cut

View File

@ -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 <name> OWTHERM [<model>] <ROM_ID> [interval]
#
@ -43,12 +36,8 @@
# Additional attributes are defined in fhem.cfg
# Note: attributes "tempXXXX" are read during every update operation.
#
# attr <name> event on-change/on-update = when to write an event (default= on-update)
#
# attr <name> stateAL "<string>" = character string for denoting low alarm condition, default is (-),
# overwritten by attribute setting red down triangle
# attr <name> stateAH "<string>" = character string for denoting high alarm condition, default is (+),
# overwritten by attribute setting red up triangle
# attr <name> stateAL "<string>" = character string for denoting low alarm condition, default is down triangle
# attr <name> stateAH "<string>" = character string for denoting high alarm condition, default is up triangle
# attr <name> tempOffset <float> = temperature offset in degree Celsius added to the raw temperature reading
# attr <name> tempUnit <string> = unit of measurement, e.g. Celsius/Kelvin/Fahrenheit or C/K/F, default is Celsius
# attr <name> tempLow <float> = 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 <span style=\"color:red\">&#x25BE;</span>")
if( !defined($attr{$name}{"stateAL"} ));
CommandAttr (undef,"$name stateAH <span style=\"color:red\">&#x25B4;</span>")
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} : "&#x25BE;";
$stateah = defined($attr{$name}{stateAH}) ? $attr{$name}{stateAH} : "&#x25B4;";
$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 = "&deg;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
<a name="OWTHERM"></a>
<h3>OWTHERM</h3>
<ul>FHEM module to commmunicate with 1-Wire bus digital thermometer devices<br /><br />
Note:<br /> This is the only 1-Wire module which so far works with both the OWFS and the
OWX interface module. Please define an <a href="#OWFS">OWFS</a> device or an <a
href="#OWX">OWX</a> device first. <br />
<br /><b>Example</b><br />
<ul>
<code>define OWX_T OWTHERM DS18B20 E8D09B030000 300</code>
<br />
<code>attr OWX_T tempUnit Kelvin</code>
<br />
</ul><br />
<a name="OWTHERMdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; OWTHERM [&lt;model&gt;] &lt;id&gt;
[&lt;interval&gt;]</code>
<a name="OWTHERM"></a>
<h3>OWTHERM</h3>
<p>FHEM module to commmunicate with 1-Wire bus digital thermometer devices<br /><br />
Note:<br /> This is the only 1-Wire module which so far works with both the OWFS and the
OWX interface module. Please define an <a href="#OWFS">OWFS</a> device or an <a
href="#OWX">OWX</a> device first. <br />
</p>
<h4>Example</h4>
<p>
<code>define OWX_T OWTHERM DS18B20 E8D09B030000 300</code>
<br />
<code>attr OWX_T tempUnit Kelvin</code>
<br />
</p><br />
<a name="OWTHERMdefine"></a>
<h4>Define</h4>
<code>define &lt;name&gt; OWTHERM [&lt;model&gt;] &lt;id&gt; [&lt;interval&gt;]</code>
<br /><br /> Define a 1-Wire digital thermometer device.<br /><br />
<li>
<code>[&lt;model&gt;]</code><br /> Defines the thermometer model (and thus
1-Wire family id) currently the following values are permitted: <ul>
<li>model DS1820 with family id 10 (default if the model parameter is
omitted)</li>
<li>model DS1822 with family id 22</li>
<li>model DS18B20 with family id 28</li>
</ul>
</li>
<li>
<p>
<code>[&lt;model&gt;]</code><br /> Defines the thermometer model (and thus 1-Wire family
id) currently the following values are permitted: </p>
<ul>
<li>model DS1820 with family id 10 (default if the model parameter is omitted)</li>
<li>model DS1822 with family id 22</li>
<li>model DS18B20 with family id 28</li>
</ul>
<p>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the thermometer device without family id and
CRC code </li>
<li>
<br />12-character unique ROM id of the thermometer device without family id and CRC
code </p>
<p>
<code>&lt;interval&gt;</code>
<br /> Temperature measurement interval in seconds. The default is 300 seconds. </li>
<br /> Temperature measurement interval in seconds. The default is 300 seconds. </p>
<br /> Example: <br />
<code>define Temp1 OWTHERM 14B598010800 300 </code><br />
</ul>
<br />
<a name="OWTHERMset">
<b>Set</b></a>
<ul>
<li><a name="owtherm_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Temperature
measurement intervall in seconds. The default is 300 seconds.</li>
<li><a name="owtherm_tempHigh">
<code>set &lt;name&gt; tempHigh &lt;float&gt;</code></a>
<br /> The high alarm temperature (on the temperature scale chosen by the
attribute value) </li>
<li><a name="owtherm_tempLow">
<code>set &lt;name&gt; tempLow &lt;float&gt;</code></a>
<br /> The low alarm temperature (on the temperature scale chosen by the
attribute value) </li>
</ul>
<br />
<a name="OWTHERMget">
<b>Get</b></a>
<ul>
<li><a name="owtherm_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owtherm_present">
<code>get &lt;name&gt; present</code></a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owtherm_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns temperature
measurement interval in seconds.</li>
<li><a name="owtherm_temperature">
<code>get &lt;name&gt; temperature</code></a><br />Obtain the temperature. </li>
<li><a name="owtherm_alarm">
<code>get &lt;name&gt; alarm</code></a><br />Obtain the alarm temperature
values. </li>
</ul>
<br />
<a name="OWTHERMattr">
<b>Attributes</b></a>
<ul>
<li><a name="owtherm_stateAL"><code>attr &lt;name&gt; stateAL &lt;string&gt;</code>
</a>
<br />character string for denoting low alarm condition, default is red down
triangle, e.g. the code &lt;span style="color:red"&gt;&amp;#x25BE;&lt;/span&gt;
leading to the sign <span style="color:red">&#x25BE;</span>
</li>
<li><a name="owtherm_stateAH"><code>attr &lt;name&gt; stateAH &lt;string&gt;</code>
</a>
<br />character string for denoting high alarm condition, default is red upward
triangle, e.g. the code &lt;span style="color:red"&gt;&amp;#x25B4;&lt;/span&gt;
leading to the sign <span style="color:red">&#x25B4;</span>
</li>
<li><a name="owtherm_tempOffset"><code>attr &lt;name&gt; tempOffset
&lt;float&gt;</code>
</a>
<br />temperature offset in &deg;C added to the raw temperature reading. </li>
<li><a name="owtherm_tempUnit"><code>attr &lt;name&gt; tempUnit
Celsius|Kelvin|Fahrenheit|C|K|F</code>
</a>
<br />unit of measurement (temperature scale), default is Celsius = &deg;C </li>
<li><a name="owtherm_tempHigh2">
<code>attr &lt;name&gt; tempHigh &lt;float&gt;</code>
</a>
<br /> high alarm temperature (on the temperature scale chosen by the attribute
value). </li>
<li><a name="owtherm_tempLow2">
<code>attr &lt;name&gt; tempLow &lt;float&gt;</code>
</a>
<br /> low alarm temperature (on the temperature scale chosen by the attribute
value). </li>
<li><a name="owtherm_event"><code>attr &lt;name&gt; event on-change|on-update
</code></a>This attribte work similarly, but not identically to the standard event-on-update-change/event-on-update-reading attribute.
<ul><li><code>event on-update</code> (default) will write a notify/FileLog event any time a measurement is received.</li>
<li><code>event on-change</code> will write a notify/FileLog event only when a measurement is different from the previous one.</li>
</ul>
</li>
<li>Standard attributes alias, comment, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>, <a href="#webCmd">webCmd</a></li>
</ul>
</ul>
<br />
<a name="OWTHERMset"></a>
<h4>Set</h4>
<ul>
<li><a name="owtherm_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Temperature
measurement intervall in seconds. The default is 300 seconds.</li>
<li><a name="owtherm_tempHigh">
<code>set &lt;name&gt; tempHigh &lt;float&gt;</code></a>
<br /> The high alarm temperature (on the temperature scale chosen by the attribute
value) </li>
<li><a name="owtherm_tempLow">
<code>set &lt;name&gt; tempLow &lt;float&gt;</code></a>
<br /> The low alarm temperature (on the temperature scale chosen by the attribute
value) </li>
</ul>
<br />
<a name="OWTHERMget"></a>
<h4>Get</h4>
<ul>
<li><a name="owtherm_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owtherm_present">
<code>get &lt;name&gt; present</code></a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owtherm_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns temperature measurement
interval in seconds.</li>
<li><a name="owtherm_temperature">
<code>get &lt;name&gt; temperature</code></a><br />Obtain the temperature. </li>
<li><a name="owtherm_alarm">
<code>get &lt;name&gt; alarm</code></a><br />Obtain the alarm temperature
values. </li>
</ul>
<br />
<a name="OWTHERMattr"></a>
<h4>Attributes</h4>
<ul>
<li><a name="owtherm_stateAL"><code>attr &lt;name&gt; stateAL &lt;string&gt;</code>
</a>
<br />character string for denoting low alarm condition, default is down triangle,
e.g. the code &amp;#x25BE; leading to the sign &#x25BE; </li>
<li><a name="owtherm_stateAH"><code>attr &lt;name&gt; stateAH &lt;string&gt;</code>
</a>
<br />character string for denoting high alarm condition, default is upward
triangle, e.g. the code &amp;#x25B4; leading to the sign &#x25B4; </li>
<li><a name="owtherm_tempOffset"><code>attr &lt;name&gt; tempOffset &lt;float&gt;</code>
</a>
<br />temperature offset in &deg;C added to the raw temperature reading. </li>
<li><a name="owtherm_tempUnit"><code>attr &lt;name&gt; tempUnit
Celsius|Kelvin|Fahrenheit|C|K|F</code>
</a>
<br />unit of measurement (temperature scale), default is Celsius = &deg;C </li>
<li><a name="owtherm_tempHigh2">
<code>attr &lt;name&gt; tempHigh &lt;float&gt;</code>
</a>
<br /> high alarm temperature (on the temperature scale chosen by the attribute
value). </li>
<li><a name="owtherm_tempLow2">
<code>attr &lt;name&gt; tempLow &lt;float&gt;</code>
</a>
<br /> low alarm temperature (on the temperature scale chosen by the attribute
value). </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
</ul>
=end html
=cut