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:
parent
2cac0b8811
commit
5a898baf40
@ -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\">▾</span>")
|
||||
if( !defined($attr{$name}{"stateAL1"} ));
|
||||
CommandAttr (undef,"$name stateAH1 <span style=\"color:red\">▴</span>")
|
||||
if( !defined($attr{$name}{"stateAH1"} ));
|
||||
CommandAttr (undef,"$name stateAL0 <span style=\"color:green\">▾</span>")
|
||||
if( !defined($attr{$name}{"stateAL0"} ));
|
||||
CommandAttr (undef,"$name stateAH0 <span style=\"color:green\">▴</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} : "▾";
|
||||
my $stateah1 = defined($attr{$name}{stateAH1}) ? $attr{$name}{stateAH1} : "▴";
|
||||
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 <name> OWAD [<model>] <id> [<interval>]</code>
|
||||
<br /><br /> Define a 1-Wire A/D converter.<br /><br />
|
||||
<li>
|
||||
<code>[<model>]</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><id></code>
|
||||
<br />12-character unique ROM id of the converter device without family id and
|
||||
CRC code </li>
|
||||
<li>
|
||||
<code><interval></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 <name> interval <int></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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owad_present">
|
||||
<code>get <name> present</code>
|
||||
</a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owad_interval2">
|
||||
<code>get <name> interval</code></a><br />Returns measurement interval
|
||||
in seconds. </li>
|
||||
<li><a name="owad_reading">
|
||||
<code>get <name> reading</code></a><br />Obtain the measuement values. </li>
|
||||
<li><a name="owad_alarm">
|
||||
<code>get <name> alarm</code></a><br />Obtain the alarm values. </li>
|
||||
<li><a name="owad_status">
|
||||
<code>get <name> 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 <name> stateAL0
|
||||
<string></code></a>
|
||||
<br />character string for denoting low normal condition, default is green down
|
||||
triangle, e.g. the code <span
|
||||
style="color:green">&#x25BE;</span> leading to the sign <span
|
||||
style="color:green">▾</span>
|
||||
</li>
|
||||
<li><a name="owad_stateAH0"><code>attr <name> stateAH0
|
||||
<string></code></a>
|
||||
<br />character string for denoting high alarm condition, default is green
|
||||
upward triangle, e.g. the code <span
|
||||
style="color:green">&#x25B4;</span> leading to the sign <span
|
||||
style="color:green">▴</span>
|
||||
</li>
|
||||
<li><a name="owad_stateAL1"><code>attr <name> stateAL1
|
||||
<string></code></a>
|
||||
<br />character string for denoting low alarm condition, default is red down
|
||||
triangle, e.g. the code <span style="color:red">&#x25BE;</span>
|
||||
leading to the sign <span style="color:red">▾</span></li>
|
||||
<li><a name="owad_stateAH1"><code>attr <name> stateAH1
|
||||
<string></code></a>
|
||||
<br />character string for denoting high alarm condition, default is red upward
|
||||
triangle, e.g. the code <span style="color:red">&#x25B4;</span>
|
||||
leading to the sign <span style="color:red">▴</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 <name> <channel>Name
|
||||
<string>|<string></code></a>
|
||||
<br />name for the channel | a type description for the measured value. </li>
|
||||
<li><a name="owad_cunit"><code>attr <name> <channel>Unit
|
||||
<string>|<string></code></a>
|
||||
<br />unit of measurement for this channel | its abbreviation. </li>
|
||||
<li><a name="owad_coffset"><code>attr <name> <channel>Offset
|
||||
<float></code></a>
|
||||
<br />offset added to the reading in this channel. </li>
|
||||
<li><a name="owad_cfactor"><code>attr <name> <channel>Factor
|
||||
<float></code></a>
|
||||
<br />factor multiplied to (reading+offset) in this channel. </li>
|
||||
<li><a name="owad_calarm"><code>attr <name> <channel>Alarm
|
||||
<string></code></a>
|
||||
<br />alarm setting in this channel, either both, low, high or none (default). </li>
|
||||
<li><a name="owad_clow"><code>attr <name> <channel>Low
|
||||
<float></code></a>
|
||||
<br />measurement value (on the scale determined by offset and factor) for low
|
||||
alarm. </li>
|
||||
<li><a name="owad_chigh"><code>attr <name> <channel>High
|
||||
<float></code></a>
|
||||
<br />measurement value (on the scale determined by offset and factor) for high
|
||||
alarm. </li>
|
||||
<li><a name="owad_event"><code>attr <name> 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 <name> OWAD [<model>] <id> [<interval>]</code>
|
||||
<br /><br /> Define a 1-Wire A/D converter.<br /><br /></p>
|
||||
<ul>
|
||||
<li>
|
||||
<code>[<model>]</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><id></code>
|
||||
<br />12-character unique ROM id of the converter device without family id and CRC
|
||||
code </li>
|
||||
<li>
|
||||
<code><interval></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 <name> interval <int></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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owad_present">
|
||||
<code>get <name> present</code>
|
||||
</a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owad_interval2">
|
||||
<code>get <name> interval</code></a><br />Returns measurement interval in
|
||||
seconds. </li>
|
||||
<li><a name="owad_reading">
|
||||
<code>get <name> reading</code></a><br />Obtain the measuement values. </li>
|
||||
<li><a name="owad_alarm">
|
||||
<code>get <name> alarm</code></a><br />Obtain the alarm values. </li>
|
||||
<li><a name="owad_status">
|
||||
<code>get <name> 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 <name> stateAL0 <string></code></a>
|
||||
<br />character string for denoting low normal condition, default is empty </li>
|
||||
<li><a name="owad_stateAH0"><code>attr <name> stateAH0 <string></code></a>
|
||||
<br />character string for denoting high normal condition, default is empty </li>
|
||||
<li><a name="owad_stateAL1"><code>attr <name> stateAL1 <string></code></a>
|
||||
<br />character string for denoting low alarm condition, default is down triangle,
|
||||
e.g. the code &#x25BE; leading to the sign ▾</li>
|
||||
<li><a name="owad_stateAH1"><code>attr <name> stateAH1 <string></code></a>
|
||||
<br />character string for denoting high alarm condition, default is upward
|
||||
triangle, e.g. the code &#x25B4; leading to the sign ▴ </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 <name> <channel>Name
|
||||
<string>|<string></code></a>
|
||||
<br />name for the channel | a type description for the measured value. </li>
|
||||
<li><a name="owad_cunit"><code>attr <name> <channel>Unit
|
||||
<string>|<string></code></a>
|
||||
<br />unit of measurement for this channel | its abbreviation. </li>
|
||||
<li><a name="owad_coffset"><b>deprecated</b>: <code>attr <name> <channel>Offset
|
||||
<float></code></a>
|
||||
<br />offset added to the reading in this channel. </li>
|
||||
<li><a name="owad_cfactor"><b>deprecated</b>: <code>attr <name> <channel>Factor
|
||||
<float></code></a>
|
||||
<br />factor multiplied to (reading+offset) in this channel. </li>
|
||||
<li><a name="owad_cfunction"> <code>attr <name> <channel>Function
|
||||
<string></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 <name> <channel>Alarm
|
||||
<string></code></a>
|
||||
<br />alarm setting in this channel, either both, low, high or none (default). </li>
|
||||
<li><a name="owad_clow"><code>attr <name> <channel>Low
|
||||
<float></code></a>
|
||||
<br />measurement value (on the scale determined by offset and factor) for low
|
||||
alarm. </li>
|
||||
<li><a name="owad_chigh"><code>attr <name> <channel>High
|
||||
<float></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
|
||||
|
@ -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 <name> OWID <id> </code>
|
||||
<br /><br /> Define a 1-Wire device.<br /><br />
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<code><id></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 <name> OWID <id> </code>
|
||||
<br /><br /> Define a 1-Wire device.<br /><br />
|
||||
<li>
|
||||
<code><id></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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owid_present">
|
||||
<code>get <name> 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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owid_present">
|
||||
<code>get <name> present</code>
|
||||
</a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
</ul>
|
||||
=end html
|
||||
=cut
|
||||
|
@ -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/.*\°\;.*/ ) {
|
||||
my @ma = split(/\°\;/,$msg);
|
||||
$msg = $ma[0]."\x80".$ma[1];
|
||||
}
|
||||
$msg = OWXLCD_Trans($msg);
|
||||
|
||||
#-- ID of the device, hash of the busmaster
|
||||
my $owx_dev = $hash->{ROM_ID};
|
||||
my $master = $hash->{IODev};
|
||||
@ -986,6 +969,34 @@ sub OWXLCD_SetLine($$$) {
|
||||
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
#
|
||||
# OWXLCD_Trans - String translation helper
|
||||
#
|
||||
# Parameter msg = data string to be written
|
||||
#
|
||||
########################################################################################
|
||||
|
||||
sub OWXLCD_Trans($) {
|
||||
|
||||
my ($msg) = @_;
|
||||
|
||||
#-- replace umlaut chars for special codepage
|
||||
$msg =~ s/ä/\x7B/g;
|
||||
$msg =~ s/ö/\x7C/g;
|
||||
$msg =~ s/ü/\x7E/g;
|
||||
$msg =~ s/Ä/\x5B/g;
|
||||
$msg =~ s/Ö/\x5C/g;
|
||||
$msg =~ s/Ü/\x5E/g;
|
||||
$msg =~ s/ß/\xBE/g;
|
||||
#--take out degree sign
|
||||
if( $msg =~ m/.*\°\;.*/ ) {
|
||||
my @ma = split(/\°\;/,$msg);
|
||||
$msg = $ma[0]."\x80".$ma[1];
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
#
|
||||
# OWXLCD_SetMemory - set internal nonvolatile memory
|
||||
@ -1038,94 +1049,93 @@ sub OWXLCD_SetMemory($$$) {
|
||||
|
||||
=pod
|
||||
=begin html
|
||||
|
||||
<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 <name> OWLCD <id></code>
|
||||
<br /><br /> Define a 1-Wire LCD device.<br /><br />
|
||||
<li>
|
||||
<code><id></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 <name> icon <int> 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 <name> icon 15 0..6</code></a><br /> Set icon 15 to one of
|
||||
its values</li>
|
||||
<li><a name="owlcd_icon3">
|
||||
<code>set <name> icon none</code></a><br /> Set all icons off</li>
|
||||
<li><a name="owlcd_line">
|
||||
<code>set <name> line <int> <string></code></a><br />
|
||||
Write LCD line 0..3 with some content </li>
|
||||
<li><a name="owlcd_memory">
|
||||
<code>set <name> memory <page>
|
||||
<string></code></a><br />Write memory page 0..6</li>
|
||||
<li><a name="owlcd_gpio">
|
||||
<code>set <name> gpio <value></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 <name> backlight ON|OFF</code></a><br />Switch backlight on
|
||||
or off</li>
|
||||
<li><a name="owlcd_lcd">
|
||||
<code>set <name> lcd ON|OFF</code></a><br />Switch LCD power on or
|
||||
off</li>
|
||||
<li><a name="owlcd_gpio">
|
||||
<code>set <name> reset</code></a><br />Reset the display</li>
|
||||
<li><a name="owlcd_gpio">
|
||||
<code>set <name> 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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owlcd_present">
|
||||
<code>get <name> present</code>
|
||||
</a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owlcd_memory2">
|
||||
<code>get <name> memory <page></code></a><br />Read memory page
|
||||
0..6 </li>
|
||||
<li><a name="owlcd_gpio">
|
||||
<code>get <name> 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 <name> gpio</code></a><br />Obtain state of all four input
|
||||
counters (4 x 16 Bit)</li>
|
||||
<li><a name="owlcd_version">
|
||||
<code>get <name> 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 <name> OWLCD <id></code>
|
||||
<br /><br /> Define a 1-Wire LCD device.<br /><br /></p>
|
||||
<ul>
|
||||
<li>
|
||||
<code><id></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 <name> icon <int> 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 <name> icon 15 0..6</code></a><br /> Set icon 15 to one of its
|
||||
values</li>
|
||||
<li><a name="owlcd_icon3">
|
||||
<code>set <name> icon none</code></a><br /> Set all icons off</li>
|
||||
<li><a name="owlcd_line">
|
||||
<code>set <name> line <int> <string></code></a><br /> Write
|
||||
LCD line 0..3 with some content </li>
|
||||
<li><a name="owlcd_memory">
|
||||
<code>set <name> memory <page> <string></code></a><br />Write
|
||||
memory page 0..6</li>
|
||||
<li><a name="owlcd_gpio">
|
||||
<code>set <name> gpio <value></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 <name> backlight ON|OFF</code></a><br />Switch backlight on or
|
||||
off</li>
|
||||
<li><a name="owlcd_lcd">
|
||||
<code>set <name> lcd ON|OFF</code></a><br />Switch LCD power on or
|
||||
off</li>
|
||||
<li><a name="owlcd_gpio">
|
||||
<code>set <name> reset</code></a><br />Reset the display</li>
|
||||
<li><a name="owlcd_gpio">
|
||||
<code>set <name> 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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owlcd_present">
|
||||
<code>get <name> present</code>
|
||||
</a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owlcd_memory2">
|
||||
<code>get <name> memory <page></code></a><br />Read memory page 0..6 </li>
|
||||
<li><a name="owlcd_gpio">
|
||||
<code>get <name> 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 <name> gpio</code></a><br />Obtain state of all four input
|
||||
counters (4 x 16 Bit)</li>
|
||||
<li><a name="owlcd_version">
|
||||
<code>get <name> 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
|
@ -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 <name> OWMULTI [<model>] <id> [<interval>]</code>
|
||||
<br /><br /> Define a 1-Wire multi-sensor<br /><br /></p>
|
||||
<ul>
|
||||
<li>
|
||||
<code>[<model>]</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><id></code>
|
||||
<br />12-character unique ROM id of the converter device without family id and CRC
|
||||
code </li>
|
||||
<li>
|
||||
<code><interval></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 <name> interval <int></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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owmulti_present">
|
||||
<code>get <name> present</code>
|
||||
</a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owmulti_interval2">
|
||||
<code>get <name> interval</code></a><br />Returns measurement interval in
|
||||
seconds. </li>
|
||||
<li><a name="owmulti_reading">
|
||||
<code>get <name> reading</code></a><br />Obtain the measurement value from
|
||||
VFunction. </li>
|
||||
<li><a name="owmulti_temperature">
|
||||
<code>get <name> temperature</code></a><br />Obtain the temperature value. </li>
|
||||
<li><a name="owmulti_vdd">
|
||||
<code>get <name> VDD</code></a><br />Obtain the current supply voltage. </li>
|
||||
<li><a name="owmulti_raw">
|
||||
<code>get <name> V</code> or <code>get <name>
|
||||
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 <name> VName
|
||||
<string>|<string></code></a>
|
||||
<br />name for the channel | a type description for the measured value. </li>
|
||||
<li><a name="owmulti_vunit"><code>attr <name> VUnit
|
||||
<string>|<string></code></a>
|
||||
<br />unit of measurement for this channel | its abbreviation. </li>
|
||||
<li><a name="owmulti_vfunction"><code>attr <name> VFunction
|
||||
<string></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 <name> tempOffset <float></code>
|
||||
</a>
|
||||
<br />temperature offset in °C added to the raw temperature reading. </li>
|
||||
<li><a name="owmulti_tempUnit"><code>attr <name> tempUnit
|
||||
Celsius|Kelvin|Fahrenheit|C|K|F</code>
|
||||
</a>
|
||||
<br />unit of measurement (temperature scale), default is Celsius = °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 <name> OWMULTI [<model>] <id> [<interval>]</code>
|
||||
<br /><br /> Define a 1-Wire multi-sensor<br /><br />
|
||||
<li>
|
||||
<code>[<model>]</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><id></code>
|
||||
<br />12-character unique ROM id of the converter device without family id and
|
||||
CRC code </li>
|
||||
<li>
|
||||
<code><interval></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 <name> interval <int></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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owmulti_present">
|
||||
<code>get <name> present</code>
|
||||
</a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owmulti_interval2">
|
||||
<code>get <name> interval</code></a><br />Returns measurement interval
|
||||
in seconds. </li>
|
||||
<li><a name="owmulti_reading">
|
||||
<code>get <name> reading</code></a><br />Obtain the measurement value from VFunction. </li>
|
||||
<li><a name="owmulti_temperature">
|
||||
<code>get <name> temperature</code></a><br />Obtain the temperature value. </li>
|
||||
<li><a name="owmulti_vdd">
|
||||
<code>get <name> VDD</code></a><br />Obtain the current supply voltage.
|
||||
</li>
|
||||
<li><a name="owmulti_raw">
|
||||
<code>get <name> V</code> or <code>get <name> 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 <name> VName
|
||||
<string>|<string></code></a>
|
||||
<br />name for the channel | a type description for the measured value. </li>
|
||||
<li><a name="owmulti_vunit"><code>attr <name> VUnit
|
||||
<string>|<string></code></a>
|
||||
<br />unit of measurement for this channel | its abbreviation. </li>
|
||||
<li><a name="owmulti_vfunction"><code>attr <name> VFunction
|
||||
<string></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 <name> tempOffset
|
||||
<float></code>
|
||||
</a>
|
||||
<br />temperature offset in °C added to the raw temperature reading. </li>
|
||||
<li><a name="owmulti_tempUnit"><code>attr <name> tempUnit
|
||||
Celsius|Kelvin|Fahrenheit|C|K|F</code>
|
||||
</a>
|
||||
<br />unit of measurement (temperature scale), default is Celsius = °C </li>
|
||||
<li><a name="owmulti_event"><code>attr <name> 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
|
@ -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\">☇</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"} : "☇";
|
||||
|
||||
#-- 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 <name> OWSWITCH [<model>] <id> [<interval>]</code>
|
||||
<br /><br /> Define a 1-Wire switch.<br /><br /></p>
|
||||
<ul>
|
||||
<li>
|
||||
<code>[<model>]</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><id></code>
|
||||
<br />12-character unique ROM id of the converter device without family id and CRC
|
||||
code </li>
|
||||
<li>
|
||||
<code><interval></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 <name> interval <int></code></a><br /> Measurement
|
||||
interval in seconds. The default is 300 seconds. </li>
|
||||
<li><a name="owswitch_output">
|
||||
<code>set <name> output <channel-name> on | off | on-for-timer <time> | off-for-timer <time></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 <name> gpio <value></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 <name> 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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owswitch_present">
|
||||
<code>get <name> present</code>
|
||||
</a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owswitch_interval2">
|
||||
<code>get <name> interval</code></a><br />Returns measurement interval in
|
||||
seconds. </li>
|
||||
<li><a name="owswitch_input">
|
||||
<code>get <name> input <channel-name></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 <name> gpio</code></a><br />Obtain state of all channels</li>
|
||||
</ul>
|
||||
<br />
|
||||
</ul>
|
||||
<br />
|
||||
<a name="OWSWITCHdefine"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> OWSWITCH [<model>] <id>
|
||||
[<interval>]</code>
|
||||
<br /><br /> Define a 1-Wire switch.<br /><br />
|
||||
<li>
|
||||
<code>[<model>]</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><id></code>
|
||||
<br />12-character unique ROM id of the converter device without family id and
|
||||
CRC code </li>
|
||||
<li>
|
||||
<code><interval></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 <name> interval <int></code></a><br /> Measurement
|
||||
interval in seconds. The default is 300 seconds. </li>
|
||||
<li><a name="owswitch_output">
|
||||
<code>set <name> output <channel-name> 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 <name> gpio <value></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 <name> 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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owswitch_present">
|
||||
<code>get <name> present</code>
|
||||
</a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owswitch_interval2">
|
||||
<code>get <name> interval</code></a><br />Returns measurement interval
|
||||
in seconds. </li>
|
||||
<li><a name="owswitch_input">
|
||||
<code>get <name> input <channel-name></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 <name> 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 <name> <channel>Name
|
||||
<string>|<string></code></a>
|
||||
<br />name for the channel | a type description for the measured value. </li>
|
||||
<li><a name="owswitch_cunit"><code>attr <name> <channel>Unit
|
||||
<string>|<string></code></a>
|
||||
<br />display for on | off condition </li>
|
||||
<li><a name="owswitch_event"><code>attr <name> 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 <name> <channel>Name
|
||||
<string>|<string></code></a>
|
||||
<br />name for the channel | a type description for the measured value. </li>
|
||||
<li><a name="owswitch_cunit"><code>attr <name> <channel>Unit
|
||||
<string>|<string></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
|
||||
|
@ -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\">▾</span>")
|
||||
if( !defined($attr{$name}{"stateAL"} ));
|
||||
CommandAttr (undef,"$name stateAH <span style=\"color:red\">▴</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} : "▾";
|
||||
$stateah = defined($attr{$name}{stateAH}) ? $attr{$name}{stateAH} : "▴";
|
||||
$unit = $hash->{READINGS}{"temperature"}{UNIT} = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : "Celsius";
|
||||
$offset = defined($attr{$name}{"tempOffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ;
|
||||
$factor = 1.0;
|
||||
|
||||
if( $unit eq "Celsius" ){
|
||||
$abbr = "°C";
|
||||
@ -300,57 +285,51 @@ sub OWTHERM_FormatValues($) {
|
||||
$factor = 1.8;
|
||||
} else {
|
||||
$abbr="?";
|
||||
Log 1, "OWTHERM_FormatValues: unknown unit $unit";
|
||||
Log 3, "OWTHERM_FormatValues: unknown unit $unit";
|
||||
}
|
||||
#-- these values are rather coplex to obtain, therefore save them in the hash
|
||||
#-- these values are rather complex to obtain, therefore save them in the hash
|
||||
$hash->{READINGS}{"temperature"}{UNIT} = $unit;
|
||||
$hash->{READINGS}{"temperature"}{UNITABBR} = $abbr;
|
||||
$hash->{tempf}{offset} = $offset;
|
||||
$hash->{tempf}{factor} = $factor;
|
||||
|
||||
#-- no change in any value if invalid reading
|
||||
return if( $owg_temp eq "");
|
||||
|
||||
#-- correct values for proper offset, factor
|
||||
$vval = ($owg_temp + $offset)*$factor;
|
||||
|
||||
#-- put into READINGS
|
||||
$hash->{READINGS}{"temperature"}{VAL} = $vval;
|
||||
$hash->{READINGS}{"temperature"}{TIME} = $tn;
|
||||
|
||||
#-- correct alarm values for proper offset, factor
|
||||
$vlow = ($owg_tl + $offset)*$factor;
|
||||
$vhigh = ($owg_th + $offset)*$factor;
|
||||
|
||||
#-- put into READINGS
|
||||
$hash->{READINGS}{"tempLow"}{VAL} = $vlow;
|
||||
$hash->{READINGS}{"tempLow"}{TIME} = $tn;
|
||||
$hash->{READINGS}{"tempHigh"}{VAL} = $vhigh;
|
||||
$hash->{READINGS}{"tempHigh"}{TIME} = $tn;
|
||||
|
||||
#-- formats for output
|
||||
$statef = "%5.2f ".$abbr;
|
||||
$value1 = "temperature: ".sprintf($statef,$vval);
|
||||
$value2 = sprintf($statef,$vval);
|
||||
$hash->{ALARM} = 1;
|
||||
$svalue = "temperature: ".sprintf($statef,$vval);
|
||||
|
||||
#-- Test for alarm condition
|
||||
$hash->{ALARM} = 1;
|
||||
if( ($vval <= $vlow) && ( $vval >= $vhigh ) ){
|
||||
$value2 .= " ".$stateal.$stateah;
|
||||
$value3 .= " ".$stateal.$stateah;
|
||||
$svalue .= " ".$stateal.$stateah;
|
||||
}elsif( $vval <= $vlow ){
|
||||
$value2 .= " ".$stateal;
|
||||
$value3 .= " ".$stateal;
|
||||
$svalue .= " ".$stateal;
|
||||
}elsif( $vval >= $vhigh ){
|
||||
$value2 .= " ".$stateah;
|
||||
$value3 .= " ".$stateah;
|
||||
$svalue .= " ".$stateah;
|
||||
} else {
|
||||
$hash->{ALARM} = 0;
|
||||
}
|
||||
|
||||
#-- put into READINGS
|
||||
readingsBeginUpdate($hash);
|
||||
readingsBulkUpdate($hash,"temperature",$vval);
|
||||
readingsBulkUpdate($hash,"tempLow",$vlow);
|
||||
readingsBulkUpdate($hash,"tempHigh",$vhigh);
|
||||
|
||||
#-- STATE
|
||||
$hash->{STATE} = $value2;
|
||||
#-- alarm
|
||||
#$hash->{READINGS}{alarms}{VAL} = $value3;
|
||||
#$hash->{READINGS}{alarms}{TIME} = $tn;
|
||||
return $value1;
|
||||
readingsBulkUpdate($hash,"state",$svalue);
|
||||
readingsEndUpdate($hash,1);
|
||||
|
||||
return $svalue;
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
@ -485,17 +464,8 @@ sub OWTHERM_GetValues($@) {
|
||||
}
|
||||
$hash->{PRESENT} = 1;
|
||||
|
||||
#-- old state, new state
|
||||
my $oldval = $hash->{STATE};
|
||||
$value=OWTHERM_FormatValues($hash);
|
||||
my $newval = $hash->{STATE};
|
||||
#--logging depends on setting of the event-attribute
|
||||
Log 5, $value;
|
||||
my $ev = defined($attr{$name}{"event"}) ? $attr{$name}{"event"} : "on-update";
|
||||
if( ($ev eq "on-update") || (($ev eq "on-change") && ($newval ne $oldval)) ){
|
||||
$hash->{CHANGED}[0] = $value;
|
||||
DoTrigger($name, undef);
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
@ -540,7 +510,7 @@ sub OWTHERM_Set($@) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
#-- set other values depending on interface type
|
||||
#-- set tempLow or tempHigh
|
||||
my $interface = $hash->{IODev}->{TYPE};
|
||||
my $offset = $hash->{tempf}{offset};
|
||||
my $factor = $hash->{tempf}{factor};
|
||||
@ -551,7 +521,7 @@ sub OWTHERM_Set($@) {
|
||||
return sprintf("OWTHERM: Set with wrong value $value for $key, range is [%3.1f,%3.1f]",$mmin,$mmax)
|
||||
if($value < $mmin || $value > $mmax);
|
||||
|
||||
#-- seems to be ok, put into the device
|
||||
#-- seems to be ok, put into the device after correcting for offset and factor
|
||||
$a[2] = int($value/$factor-$offset);
|
||||
|
||||
#-- OWX interface
|
||||
@ -664,7 +634,7 @@ sub OWXTHERM_GetValues($) {
|
||||
|
||||
my ($hash) = @_;
|
||||
|
||||
my ($i,$j,$k);
|
||||
my ($i,$j,$k,@data);
|
||||
|
||||
#-- For default, perform the conversion NOT now
|
||||
my $con=1;
|
||||
@ -702,25 +672,25 @@ sub OWXTHERM_GetValues($) {
|
||||
}
|
||||
|
||||
#-- process results
|
||||
my @data=split(//,$res);
|
||||
return "invalid data length, ".int(@data)." bytes"
|
||||
if (@data != 19);
|
||||
@data=split(//,substr($res,9));
|
||||
return "invalid data length, ".int(@data)." instead of 10 bytes"
|
||||
if (@data != 10);
|
||||
return "invalid data"
|
||||
if (ord($data[17])<=0);
|
||||
if (ord($data[8])<=0);
|
||||
return "invalid CRC"
|
||||
if (OWX_CRC8(substr($res,10,8),$data[18])==0);
|
||||
if (OWX_CRC8(substr($res,10,8),$data[9])==0);
|
||||
|
||||
#-- this must be different for the different device types
|
||||
# family = 10 => DS1820, DS18S20
|
||||
if( $hash->{OW_FAMILY} eq "10" ) {
|
||||
|
||||
my $count_remain = ord($data[16]);
|
||||
my $count_perc = ord($data[17]);
|
||||
my $count_remain = ord($data[7]);
|
||||
my $count_perc = ord($data[8]);
|
||||
my $delta = -0.25 + ($count_perc - $count_remain)/$count_perc;
|
||||
|
||||
my $lsb = ord($data[10]);
|
||||
my $lsb = ord($data[1]);
|
||||
my $msb = 0;
|
||||
my $sign = ord($data[11]) & 255;
|
||||
my $sign = ord($data[2]) & 255;
|
||||
|
||||
#-- test with -25 degrees
|
||||
#$lsb = 12*16+14;
|
||||
@ -733,16 +703,16 @@ sub OWXTHERM_GetValues($) {
|
||||
$owg_temp = -128+$owg_temp;
|
||||
}
|
||||
|
||||
$owg_th = ord($data[12]) > 127 ? 128-ord($data[12]) : ord($data[12]);
|
||||
$owg_tl = ord($data[13]) > 127 ? 128-ord($data[13]) : ord($data[13]);
|
||||
$owg_th = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]);
|
||||
$owg_tl = ord($data[4]) > 127 ? 128-ord($data[4]) : ord($data[4]);
|
||||
|
||||
return undef;
|
||||
|
||||
} elsif ( ($hash->{OW_FAMILY} eq "22") || ($hash->{OW_FAMILY} eq "28") ) {
|
||||
|
||||
my $lsb = ord($data[10]);
|
||||
my $msb = ord($data[11]) & 7;
|
||||
my $sign = ord($data[11]) & 248;
|
||||
my $lsb = ord($data[1]);
|
||||
my $msb = ord($data[2]) & 7;
|
||||
my $sign = ord($data[2]) & 248;
|
||||
|
||||
#-- test with -55 degrees
|
||||
#$lsb = 9*16;
|
||||
@ -754,8 +724,8 @@ sub OWXTHERM_GetValues($) {
|
||||
if( $sign !=0 ){
|
||||
$owg_temp = -128+$owg_temp;
|
||||
}
|
||||
$owg_th = ord($data[12]) > 127 ? 128-ord($data[12]) : ord($data[12]);
|
||||
$owg_tl = ord($data[13]) > 127 ? 128-ord($data[13]) : ord($data[13]);
|
||||
$owg_th = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]);
|
||||
$owg_tl = ord($data[4]) > 127 ? 128-ord($data[4]) : ord($data[4]);
|
||||
|
||||
return undef;
|
||||
|
||||
@ -815,129 +785,114 @@ sub OWXTHERM_SetValues($@) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
=begin html
|
||||
|
||||
<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 <name> OWTHERM [<model>] <id>
|
||||
[<interval>]</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 <name> OWTHERM [<model>] <id> [<interval>]</code>
|
||||
<br /><br /> Define a 1-Wire digital thermometer device.<br /><br />
|
||||
<li>
|
||||
<code>[<model>]</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>[<model>]</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><id></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><interval></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 <name> interval <int></code></a><br /> Temperature
|
||||
measurement intervall in seconds. The default is 300 seconds.</li>
|
||||
<li><a name="owtherm_tempHigh">
|
||||
<code>set <name> tempHigh <float></code></a>
|
||||
<br /> The high alarm temperature (on the temperature scale chosen by the
|
||||
attribute value) </li>
|
||||
<li><a name="owtherm_tempLow">
|
||||
<code>set <name> tempLow <float></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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owtherm_present">
|
||||
<code>get <name> present</code></a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owtherm_interval2">
|
||||
<code>get <name> interval</code></a><br />Returns temperature
|
||||
measurement interval in seconds.</li>
|
||||
<li><a name="owtherm_temperature">
|
||||
<code>get <name> temperature</code></a><br />Obtain the temperature. </li>
|
||||
<li><a name="owtherm_alarm">
|
||||
<code>get <name> 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 <name> stateAL <string></code>
|
||||
</a>
|
||||
<br />character string for denoting low alarm condition, default is red down
|
||||
triangle, e.g. the code <span style="color:red">&#x25BE;</span>
|
||||
leading to the sign <span style="color:red">▾</span>
|
||||
</li>
|
||||
<li><a name="owtherm_stateAH"><code>attr <name> stateAH <string></code>
|
||||
</a>
|
||||
<br />character string for denoting high alarm condition, default is red upward
|
||||
triangle, e.g. the code <span style="color:red">&#x25B4;</span>
|
||||
leading to the sign <span style="color:red">▴</span>
|
||||
</li>
|
||||
<li><a name="owtherm_tempOffset"><code>attr <name> tempOffset
|
||||
<float></code>
|
||||
</a>
|
||||
<br />temperature offset in °C added to the raw temperature reading. </li>
|
||||
<li><a name="owtherm_tempUnit"><code>attr <name> tempUnit
|
||||
Celsius|Kelvin|Fahrenheit|C|K|F</code>
|
||||
</a>
|
||||
<br />unit of measurement (temperature scale), default is Celsius = °C </li>
|
||||
<li><a name="owtherm_tempHigh2">
|
||||
<code>attr <name> tempHigh <float></code>
|
||||
</a>
|
||||
<br /> high alarm temperature (on the temperature scale chosen by the attribute
|
||||
value). </li>
|
||||
<li><a name="owtherm_tempLow2">
|
||||
<code>attr <name> tempLow <float></code>
|
||||
</a>
|
||||
<br /> low alarm temperature (on the temperature scale chosen by the attribute
|
||||
value). </li>
|
||||
<li><a name="owtherm_event"><code>attr <name> 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 <name> interval <int></code></a><br /> Temperature
|
||||
measurement intervall in seconds. The default is 300 seconds.</li>
|
||||
<li><a name="owtherm_tempHigh">
|
||||
<code>set <name> tempHigh <float></code></a>
|
||||
<br /> The high alarm temperature (on the temperature scale chosen by the attribute
|
||||
value) </li>
|
||||
<li><a name="owtherm_tempLow">
|
||||
<code>set <name> tempLow <float></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 <name> id</code></a>
|
||||
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
|
||||
<li><a name="owtherm_present">
|
||||
<code>get <name> present</code></a>
|
||||
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
|
||||
<li><a name="owtherm_interval2">
|
||||
<code>get <name> interval</code></a><br />Returns temperature measurement
|
||||
interval in seconds.</li>
|
||||
<li><a name="owtherm_temperature">
|
||||
<code>get <name> temperature</code></a><br />Obtain the temperature. </li>
|
||||
<li><a name="owtherm_alarm">
|
||||
<code>get <name> 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 <name> stateAL <string></code>
|
||||
</a>
|
||||
<br />character string for denoting low alarm condition, default is down triangle,
|
||||
e.g. the code &#x25BE; leading to the sign ▾ </li>
|
||||
<li><a name="owtherm_stateAH"><code>attr <name> stateAH <string></code>
|
||||
</a>
|
||||
<br />character string for denoting high alarm condition, default is upward
|
||||
triangle, e.g. the code &#x25B4; leading to the sign ▴ </li>
|
||||
<li><a name="owtherm_tempOffset"><code>attr <name> tempOffset <float></code>
|
||||
</a>
|
||||
<br />temperature offset in °C added to the raw temperature reading. </li>
|
||||
<li><a name="owtherm_tempUnit"><code>attr <name> tempUnit
|
||||
Celsius|Kelvin|Fahrenheit|C|K|F</code>
|
||||
</a>
|
||||
<br />unit of measurement (temperature scale), default is Celsius = °C </li>
|
||||
<li><a name="owtherm_tempHigh2">
|
||||
<code>attr <name> tempHigh <float></code>
|
||||
</a>
|
||||
<br /> high alarm temperature (on the temperature scale chosen by the attribute
|
||||
value). </li>
|
||||
<li><a name="owtherm_tempLow2">
|
||||
<code>attr <name> tempLow <float></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
|
||||
|
Loading…
x
Reference in New Issue
Block a user