2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-07 12:58:13 +00:00

OWAD.pm: Neue Version 6.0, eingerichtet für asynchrones OWX

OWCOUNT.pm: Neue Version 6.0, eingerichtet für asynchrones OWX
OWID.pm: Neue Version 6.0, eingerichtet für asynchrones OWX
OWLCD.pm: Neue Version 6.0, eingerichtet für asynchrones OWX
OWMULTI.pm: Neue Version 6.0, eingerichtet für asynchrones OWX
OWSWITCH.pm: Neue Version 6.0, eingerichtet für asynchrones OWX
OWTHERM.pm: Neue Version 6.0, eingerichtet für asynchrones OWX


git-svn-id: https://svn.fhem.de/fhem/trunk@11130 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
pahenning 2016-03-27 09:14:38 +00:00
parent 15cb46808f
commit fc6db34218
7 changed files with 2270 additions and 1630 deletions

View File

@ -36,20 +36,16 @@
# #
# attr <name> stateAL0 "<string>" = character string for denoting low normal condition, default is empty # 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> 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> stateAL1 "<string>" = character string for denoting low alarm condition, default is
# attr <name> stateAH1 "<string>" = character string for denoting high alarm condition, default is up triangle # attr <name> stateAH1 "<string>" = character string for denoting high alarm condition, default is
# attr <name> <channel>Name <string>[|<string>] = name for the channel [|name used in state reading] # attr <name> <channel>Name <string>[|<string>] = name for the channel [|name used in state reading]
# attr <name> <channel>Unit <string>[|<string>] = unit of measurement for this channel [|unit used in state reading] # attr <name> <channel>Unit <string> = unit of measurement for this channel used in state reading (default V, none for empty)
#
# 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 # 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. # 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>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>Low <float> = measurement value (on the scale determined by function) for low alarm
# attr <name> <channel>High <float> = measurement value (on the scale determined by offset and factor) for high alarm # attr <name> <channel>High <float> = measurement value (on the scale determined by function) for high alarm
# #
######################################################################################## ########################################################################################
# #
@ -88,9 +84,9 @@ BEGIN {
use ProtoThreads; use ProtoThreads;
no warnings 'deprecated'; no warnings 'deprecated';
sub Log($$); sub Log3($$$);
my $owx_version="5.20"; my $owx_version="6.0";
#-- fixed raw channel name, flexible channel name #-- fixed raw channel name, flexible channel name
my @owg_fixed = ("A","B","C","D"); my @owg_fixed = ("A","B","C","D");
my @owg_channel = ("A","B","C","D"); my @owg_channel = ("A","B","C","D");
@ -161,15 +157,13 @@ sub OWAD_Initialize ($) {
$hash->{InitFn} = "OWAD_Init"; $hash->{InitFn} = "OWAD_Init";
$hash->{AttrFn} = "OWAD_Attr"; $hash->{AttrFn} = "OWAD_Attr";
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2450 verbose:0,1,2,3,4,5 ". my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2450 ".
"stateAL0 stateAL1 stateAH0 stateAH1 ". "stateAL0 stateAL1 stateAH0 stateAH1 ".
"interval ". "interval ".
$readingFnAttributes; $readingFnAttributes;
for( my $i=0;$i<int(@owg_fixed);$i++ ){ for( my $i=0;$i<int(@owg_fixed);$i++ ){
$attlist .= " ".$owg_fixed[$i]."Name"; $attlist .= " ".$owg_fixed[$i]."Name";
$attlist .= " ".$owg_fixed[$i]."Offset";
$attlist .= " ".$owg_fixed[$i]."Factor";
$attlist .= " ".$owg_fixed[$i]."Function"; $attlist .= " ".$owg_fixed[$i]."Function";
$attlist .= " ".$owg_fixed[$i]."Unit"; $attlist .= " ".$owg_fixed[$i]."Unit";
$attlist .= " ".$owg_fixed[$i]."Alarm:none,low,high,both"; $attlist .= " ".$owg_fixed[$i]."Alarm:none,low,high,both";
@ -391,11 +385,11 @@ sub OWAD_ChannelNames($) {
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $state = $hash->{READINGS}{"state"}{VAL}; my $state = $hash->{READINGS}{"state"}{VAL};
my ($cname,@cnama,$unit,@unarr); my ($cname,@cnama,$unit);
for (my $i=0;$i<int(@owg_fixed);$i++){ for (my $i=0;$i<int(@owg_fixed);$i++){
#-- name #-- name
$cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : $owg_fixed[$i]; $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : "$owg_fixed[$i]";
@cnama = split(/\|/,$cname); @cnama = split(/\|/,$cname);
if( int(@cnama)!=2){ if( int(@cnama)!=2){
push(@cnama,$cnama[0]); push(@cnama,$cnama[0]);
@ -403,16 +397,16 @@ sub OWAD_ChannelNames($) {
$owg_channel[$i]=$cnama[0]; $owg_channel[$i]=$cnama[0];
#-- unit #-- unit
$unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "Volt|V"; $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "V";
@unarr= split(/\|/,$unit); if($unit eq "none"){
if( int(@unarr)!=2 ){ $unit = "";
push(@unarr,$unarr[0]); }else{
$unit = " ".$unit;
} }
#-- put into readings #-- put into readings
$hash->{READINGS}{$owg_channel[$i]}{ABBR} = $cnama[1]; $hash->{READINGS}{$owg_channel[$i]}{ABBR} = $cnama[1];
$hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unarr[0]; $hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unit;
$hash->{READINGS}{$owg_channel[$i]}{UNITABBR} = $unarr[1];
} }
} }
@ -429,7 +423,7 @@ sub OWAD_FormatValues($) {
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $interface = $hash->{IODev}->{TYPE}; my $interface = $hash->{IODev}->{TYPE};
my ($offset,$factor,$vval,$vlow,$vhigh,$vfunc,$ret); my ($vval,$vlow,$vhigh,$vfunc,$ret);
my $vfuncall = ""; my $vfuncall = "";
my $svalue = ""; my $svalue = "";
@ -445,8 +439,8 @@ sub OWAD_FormatValues($) {
$hash->{ALARM} = 0; $hash->{ALARM} = 0;
#-- alarm signatures #-- alarm signatures
my $stateal1 = defined($attr{$name}{stateAL1}) ? $attr{$name}{stateAL1} : "&#x25BE;"; my $stateal1 = defined($attr{$name}{stateAL1}) ? $attr{$name}{stateAL1} : "";
my $stateah1 = defined($attr{$name}{stateAH1}) ? $attr{$name}{stateAH1} : "&#x25B4;"; my $stateah1 = defined($attr{$name}{stateAH1}) ? $attr{$name}{stateAH1} : "";
my $stateal0 = defined($attr{$name}{stateAL0}) ? $attr{$name}{stateAL0} : ""; my $stateal0 = defined($attr{$name}{stateAL0}) ? $attr{$name}{stateAL0} : "";
my $stateah0 = defined($attr{$name}{stateAH0}) ? $attr{$name}{stateAH0} : ""; my $stateah0 = defined($attr{$name}{stateAH0}) ? $attr{$name}{stateAH0} : "";
@ -463,13 +457,7 @@ sub OWAD_FormatValues($) {
#-- formats for output #-- formats for output
for (my $i=0;$i<int(@owg_fixed);$i++){ for (my $i=0;$i<int(@owg_fixed);$i++){
#-- when offset and scale factor are defined, we cannot have a function and vice versa if (defined($attr{$name}{$owg_fixed[$i]."Function"})){
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"}; $vfunc = $attr{$name}{$owg_fixed[$i]."Function"};
} else { } else {
$vfunc = "V$owg_fixed[$i]"; $vfunc = "V$owg_fixed[$i]";
@ -504,7 +492,7 @@ sub OWAD_FormatValues($) {
$main::attr{$name}{$owg_fixed[$i]."High"}=$vhigh; $main::attr{$name}{$owg_fixed[$i]."High"}=$vhigh;
#-- string buildup for return value, STATE and alarm #-- string buildup for return value, STATE and alarm
$svalue .= sprintf( "%s: %5.3f %s", $hash->{READINGS}{$owg_channel[$i]}{ABBR}, $vval,$hash->{READINGS}{$owg_channel[$i]}{UNITABBR}); $svalue .= sprintf( "%s: %5.3f%s", $hash->{READINGS}{$owg_channel[$i]}{ABBR}, $vval,$hash->{READINGS}{$owg_channel[$i]}{UNIT});
#-- Test for alarm condition #-- Test for alarm condition
$alarm = "none"; $alarm = "none";
@ -542,6 +530,7 @@ sub OWAD_FormatValues($) {
} }
#-- put into READINGS #-- put into READINGS
$vval = sprintf( "%5.3f", $vval);
readingsBulkUpdate($hash,"$owg_channel[$i]",$vval); readingsBulkUpdate($hash,"$owg_channel[$i]",$vval);
#-- insert space #-- insert space
if( $i<int(@owg_fixed)-1 ){ if( $i<int(@owg_fixed)-1 ){
@ -578,8 +567,6 @@ sub OWAD_Get($@) {
my $interface= $hash->{IODev}->{TYPE}; my $interface= $hash->{IODev}->{TYPE};
my ($value,$value2,$value3) = (undef,undef,undef); my ($value,$value2,$value3) = (undef,undef,undef);
my $ret = ""; my $ret = "";
my $offset;
my $factor;
#-- check syntax #-- check syntax
return "OWAD: Get argument is missing @a" return "OWAD: Get argument is missing @a"
@ -642,7 +629,10 @@ sub OWAD_Get($@) {
return "OWAD: Get with wrong IODev type $interface"; return "OWAD: Get with wrong IODev type $interface";
} }
#-- process results #-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWAD: $name getting reading, please wait for completion";
}else{
if( defined($ret) ){ if( defined($ret) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1; $hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){ if( $hash->{ERRCOUNT} > 5 ){
@ -652,7 +642,7 @@ sub OWAD_Get($@) {
} }
return "OWAD: $name.reading => ".$hash->{READINGS}{"state"}{VAL}; return "OWAD: $name.reading => ".$hash->{READINGS}{"state"}{VAL};
} }
}
#-- get alarm values according to interface type #-- get alarm values according to interface type
if($a[1] eq "alarm") { if($a[1] eq "alarm") {
#-- OWX interface #-- OWX interface
@ -671,7 +661,10 @@ sub OWAD_Get($@) {
return "OWAD: Get with wrong IODev type $interface"; return "OWAD: Get with wrong IODev type $interface";
} }
#-- process results #-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWAD: $name getting alarm values, please wait for completion";
}else{
if( defined($ret) ){ if( defined($ret) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1; $hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){ if( $hash->{ERRCOUNT} > 5 ){
@ -689,6 +682,7 @@ sub OWAD_Get($@) {
} }
return "OWAD: $name.alarm => $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") { if($a[1] eq "status") {
@ -708,7 +702,10 @@ sub OWAD_Get($@) {
return "OWAD: Get with wrong IODev type $interface"; return "OWAD: Get with wrong IODev type $interface";
} }
#-- process results #-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWAD: $name getting status, please wait for completion";
}else{
if( defined($ret) ){ if( defined($ret) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1; $hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){ if( $hash->{ERRCOUNT} > 5 ){
@ -750,6 +747,7 @@ sub OWAD_Get($@) {
} }
return "OWAD: $name.status => ".$value; return "OWAD: $name.status => ".$value;
} }
}
} }
####################################################################################### #######################################################################################
@ -939,8 +937,6 @@ sub OWAD_Set($@) {
my $ret = undef; my $ret = undef;
my $channon = undef; my $channon = undef;
my $channo = undef; my $channo = undef;
my $factor;
my $offset;
my $condx; my $condx;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -1024,7 +1020,7 @@ sub OWAD_Set($@) {
#-- set alarm values (alarm voltages) #-- set alarm values (alarm voltages)
}elsif( $key =~ m/(.*)(Low|High)/ ) { }elsif( $key =~ m/(.*)(Low|High)/ ) {
#-- find upper and lower boundaries for given offset/factor #-- find upper and lower boundaries
my $mmin = 0.0; my $mmin = 0.0;
my $mmax = $owg_range[$channo]/1000; my $mmax = $owg_range[$channo]/1000;
@ -1313,37 +1309,61 @@ sub OWFSAD_SetPage($$) {
# #
######################################################################################## ########################################################################################
# #
# OWXAD_BinValues - Binary readings into clear values # OWXAD_BinValues - Process reading from one device - translate binary into raw
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# context = mode for evaluating the binary data
# proc = processing instruction, also passed to OWX_Read.
# bitwise interpretation !!
# if 0, nothing special
# if 1 = bit 0, a reset will be performed not only before, but also after
# the last operation in OWX_Read
# if 2 = bit 1, the initial reset of the bus will be suppressed
# if 8 = bit 3, the fillup of the data with 0xff will be suppressed
# if 16= bit 4, the insertion will be at the top of the queue
# owx_dev = ROM ID of slave device
# crcpart = part of the data that needs to be part of the CRC check
# numread = number of bytes to receive
# res = result string
#
# #
######################################################################################## ########################################################################################
sub OWXAD_BinValues($$$$$$$$) { sub OWXAD_BinValues($$$$$$$) {
my ($hash, $context, $success, $reset, $owx_dev, $command, $numread, $res) = @_; my ($hash, $context, $proc, $owx_dev, $crcpart, $numread, $res) = @_;
#-- hash of the busmaster
my $master = $hash->{IODev};
my $name = $hash->{NAME};
my @data=[];
my $value;
my $msg;
OWX_WDBG($name,"OWXAD_BinValues called for device $name in context $context with ",$res)
if( $main::owx_debug>2 );
#-- always check for success, unused are reset
return unless ($success and $context);
#Log 1,"OWXAD_BinValues context = $context";
my $final = ($context =~ /\.final$/ ); my $final = ($context =~ /\.final$/ );
my ($ow_thn,$ow_tln);
my ($i,$j,$k,@data,$ow_thn,$ow_tln);
#-- process results #-- process results
@data=split(//,$res); @data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 10 bytes" if (@data != 10){
if (@data != 10); $msg="$name returns invalid data length, ".int(@data)." instead of 10 bytes ";
return "invalid CRC" }elsif (OWX_CRC16($crcpart.substr($res,0,8),$data[8],$data[9])==0){
if (OWX_CRC16($command.substr($res,0,8),$data[8],$data[9])==0); $msg="$name returns invalid CRC "
}else{
$msg="No error ";
}
OWX_WDBG($name,"OWXAD_BinValues: ".$msg,$crcpart)
if( $main::owx_debug>2 );
#=============== get the voltage reading =============================== #=============== get the voltage reading ===============================
if( $context =~ /^ds2450.getreading/ ){ if( $context =~ /^ds2450.getreading/ ){
for( $i=0;$i<int(@owg_fixed);$i++){ for( my $i=0;$i<int(@owg_fixed);$i++){
$hash->{owg_val}->[$i]= (ord($data[2*$i])+256*ord($data[1+2*$i]) )/(1<<$owg_resoln[$i]) * $owg_range[$i]/1000; $hash->{owg_val}->[$i]= (ord($data[2*$i])+256*ord($data[1+2*$i]) )/(1<<$owg_resoln[$i]) * $owg_range[$i]/1000;
} }
#=============== get the alarm reading =============================== #=============== get the alarm reading ===============================
} elsif ( $context =~ /^ds2450.getalarm/ ){ } elsif ( $context =~ /^ds2450.getalarm/ ){
for( $i=0;$i<int(@owg_fixed);$i++){ for( my $i=0;$i<int(@owg_fixed);$i++){
$hash->{owg_vlow}->[$i] = int(ord($data[2*$i])/256 * $owg_range[$i]+0.5)/1000; $hash->{owg_vlow}->[$i] = int(ord($data[2*$i])/256 * $owg_range[$i]+0.5)/1000;
$hash->{owg_vhigh}->[$i] = int(ord($data[1+2*$i])/256 * $owg_range[$i]+0.5)/1000; $hash->{owg_vhigh}->[$i] = int(ord($data[1+2*$i])/256 * $owg_range[$i]+0.5)/1000;
} }
@ -1406,7 +1426,6 @@ sub OWXAD_BinValues($$$$$$$$) {
$hash->{PRESENT} = 1; $hash->{PRESENT} = 1;
if( $final ){ if( $final ){
my $value = OWAD_FormatValues($hash); my $value = OWAD_FormatValues($hash);
Log 5, $value;
} }
return undef return undef
} }
@ -1465,6 +1484,8 @@ sub OWXAD_GetPage($$$@) {
return "wrong memory page requested from $owx_dev"; return "wrong memory page requested from $owx_dev";
} }
my $context = "ds2450.get".$page.($final ? ".final" : ""); my $context = "ds2450.get".$page.($final ? ".final" : "");
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
#-- reset the bus #-- reset the bus
OWX_Reset($master); OWX_Reset($master);
#-- reading 9 + 3 + 8 data bytes and 2 CRC bytes = 22 bytes #-- reading 9 + 3 + 8 data bytes and 2 CRC bytes = 22 bytes
@ -1474,7 +1495,14 @@ sub OWXAD_GetPage($$$@) {
return "$owx_dev has returned invalid data" return "$owx_dev has returned invalid data"
if( length($res)!=22); if( length($res)!=22);
#-- for processing we also need the 3 command bytes #-- for processing we also need the 3 command bytes
return OWXAD_BinValues($hash,$context,1,undef,$owx_dev,$select,10,substr($res,12,10)); return OWXAD_BinValues($hash,$context,1,undef,$owx_dev,$select,substr($res,12,10));
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
# 1 additional reset after last action
OWX_Qomplex($master, $hash, $context, 1, $owx_dev, $select, $select, 10, 12, \&OWXAD_BinValues, 0);
return undef;
}
} }
######################################################################################## ########################################################################################
@ -1542,11 +1570,18 @@ sub OWXAD_SetPage($$) {
} else { } else {
return "wrong memory page write attempt"; return "wrong memory page write attempt";
} }
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,0); $res=OWX_Complex($master,$owx_dev,$select,0);
if( $res eq 0 ){ if( $res eq 0 ){
return "device $owx_dev not accessible for writing"; return "device $owx_dev not accessible for writing";
} }
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, undef, 0, $owx_dev, $select, 0, 0, 0, undef, 0);
}
return undef; return undef;
} }
@ -1613,7 +1648,7 @@ sub OWXAD_PT_GetPage($$$) {
PT_WAIT_THREAD($thread->{pt_execute}); PT_WAIT_THREAD($thread->{pt_execute});
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR); die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
my $response = $thread->{pt_execute}->PT_RETVAL(); my $response = $thread->{pt_execute}->PT_RETVAL();
my $res = OWXAD_BinValues($hash,"ds2450.get".$page.($final ? ".final" : ""),1,1,$owx_dev,$thread->{'select'},10,$response); my $res = OWXAD_BinValues($hash,"ds2450.get".$page.($final ? ".final" : ""),1,$owx_dev,$thread->{'select'},10,$response);
if ($res) { if ($res) {
die $res; die $res;
} }
@ -1716,16 +1751,14 @@ sub OWXAD_PT_SetPage($$) {
<br /> <br />
<code>attr OWX_AD DAlarm high</code> <code>attr OWX_AD DAlarm high</code>
<br /> <br />
<code>attr OWX_AD DFactor 31.907097</code> <code>attr OWX_AD DName humidity</code>
<br />
<code>attr OWX_AD DUnit %</code>
<br />
<code>attr OWX_AD DFunction VD*31.907097-0.8088</code>
<br /> <br />
<code>attr OWX_AD DHigh 50.0</code> <code>attr OWX_AD DHigh 50.0</code>
<br /> <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 /> </p><br />
<a name="OWADdefine"></a> <a name="OWADdefine"></a>
<h4>Define</h4> <h4>Define</h4>
@ -1792,46 +1825,31 @@ sub OWXAD_PT_SetPage($$) {
<li><a name="owad_stateAH0"><code>attr &lt;name&gt; stateAH0 &lt;string&gt;</code></a> <li><a name="owad_stateAH0"><code>attr &lt;name&gt; stateAH0 &lt;string&gt;</code></a>
<br />character string for denoting high normal condition, default is empty </li> <br />character string for denoting high normal condition, default is empty </li>
<li><a name="owad_stateAL1"><code>attr &lt;name&gt; stateAL1 &lt;string&gt;</code></a> <li><a name="owad_stateAL1"><code>attr &lt;name&gt; stateAL1 &lt;string&gt;</code></a>
<br />character string for denoting low alarm condition, default is down triangle, <br />character string for denoting low alarm condition, default is ↓</li>
e.g. the code &amp;#x25BE; leading to the sign &#x25BE;</li>
<li><a name="owad_stateAH1"><code>attr &lt;name&gt; stateAH1 &lt;string&gt;</code></a> <li><a name="owad_stateAH1"><code>attr &lt;name&gt; stateAH1 &lt;string&gt;</code></a>
<br />character string for denoting high alarm condition, default is upward <br />character string for denoting high alarm condition, default is ↑</li>
triangle, e.g. the code &amp;#x25B4; leading to the sign &#x25B4; </li>
</ul> For each of the following attributes, the channel identification A,B,C,D may be used. <ul> </ul> For each of the following attributes, the channel identification A,B,C,D may be used. <ul>
<li><a name="owad_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name <li><a name="owad_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
&lt;string&gt;[|&lt;string&gt;]</code></a> &lt;string&gt;[|&lt;string&gt;]</code></a>
<br />name for the channel [|name used in state reading]. </li> <br />name for the channel [|short name used in state reading]. </li>
<li><a name="owad_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit <li><a name="owad_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit
&lt;string&gt;[|&lt;string&gt;]</code></a> &lt;string&gt;</code></a>
<br />unit of measurement for this channel [|unit used in state reading]. </li> <br />unit of measurement for this channel used in state reading (default "V", set to "none" for empty). </li>
<li><a name="owad_coffset"><b>deprecated</b>: <code>attr &lt;name&gt; &lt;channel&gt;Offset
&lt;float&gt;</code></a>
<br />offset added to the reading in this channel. </li>
<li><a name="owad_cfactor"><b>deprecated</b>: <code>attr &lt;name&gt; &lt;channel&gt;Factor
&lt;float&gt;</code></a>
<br />factor multiplied to (reading+offset) in this channel. </li>
<li><a name="owad_cfunction"> <code>attr &lt;name&gt; &lt;channel&gt;Function <li><a name="owad_cfunction"> <code>attr &lt;name&gt; &lt;channel&gt;Function
&lt;string&gt;</code></a> &lt;string&gt;</code></a>
<br />arbitrary functional expression involving the values VA,VB,VC,VD. VA is replaced by <br />arbitrary functional expression involving the variables VA,VB,VC,VD. VA is replaced by
the measured voltage in channel A, etc. This attribute allows linearization of measurement the (raw) 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> curves as well as the mixing of various channels. </li>
<li><a name="owad_calarm"><code>attr &lt;name&gt; &lt;channel&gt;Alarm <li><a name="owad_calarm"><code>attr &lt;name&gt; &lt;channel&gt;Alarm
&lt;string&gt;</code></a> &lt;string&gt;</code></a>
<br />alarm setting in this channel, either both, low, high or none (default). </li> <br />alarm setting in this channel, either both, low, high or none (default). </li>
<li><a name="owad_clow"><code>attr &lt;name&gt; &lt;channel&gt;Low <li><a name="owad_clow"><code>attr &lt;name&gt; &lt;channel&gt;Low
&lt;float&gt;</code></a> &lt;float&gt;</code></a>
<br />measurement value (on the scale determined by offset and factor) for low <br />measurement value for low alarm. </li>
alarm. </li>
<li><a name="owad_chigh"><code>attr &lt;name&gt; &lt;channel&gt;High <li><a name="owad_chigh"><code>attr &lt;name&gt; &lt;channel&gt;High
&lt;float&gt;</code></a> &lt;float&gt;</code></a>
<br />measurement value (on the scale determined by offset and factor) for high <br />measurement value for highalarm. </li>
alarm. </li> <li><a href="#readingFnAttributes">readingFnAttributes</a></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="#stateFormat">stateFormat</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#verbose">verbose</a>,
<a href="#webCmd">webCmd</a></li>
</ul> </ul>
=end html =end html

View File

@ -44,9 +44,9 @@
# attr <name> LogM <string> = device name (not file name) of monthly log file # attr <name> LogM <string> = device name (not file name) of monthly log file
# attr <name> LogY <string> = device name (not file name) of yearly log file # attr <name> LogY <string> = device name (not file name) of yearly log file
# attr <name> nomemory = 1|0 (when set to 1, disables use of internal memory) # attr <name> nomemory = 1|0 (when set to 1, disables use of internal memory)
# attr <name> <channel>Name <string>[|<string>] = name for the channel [|name used in state reading] # attr <name> <channel>Name <string>[|<string>] = name for the channel [|short name used in state reading]
# attr <name> <channel>Unit <string>[|<string>] = unit of measurement for this channel [|unit used in state reading] # attr <name> <channel>Unit <string> = unit of measurement used in state reading (default cts, none for empty)
# attr <name> <channel>Rate <string>[|<string>] = name for the channel rate [|name used in state reading] # attr <name> <channel>Rate <string>[|<string>] = name for the channel rate [|short name used in state reading]
# attr <name> <channel>Offset <float> = offset added to the reading in this channel # 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>Factor <float> = factor multiplied to (reading+offset) in this channel
# attr <name> <channel>Mode <string> = counting mode = normal(default) or daily # attr <name> <channel>Mode <string> = counting mode = normal(default) or daily
@ -99,11 +99,13 @@ no warnings 'deprecated';
sub Log3($$$); sub Log3($$$);
my $owx_version="5.33"; my $owx_version="6.0";
#-- fixed raw channel name, flexible channel name #-- fixed raw channel name, flexible channel name
my @owg_fixed = ("A","B"); my @owg_fixed = ("A","B");
my @owg_channel = ("A","B"); my @owg_channel = ("A","B");
my @owg_rate = ("A_rate","B_rate"); my @owg_rate = ("A_rate","B_rate");
#-- initially assume that both memory types (low, high) are present
my @owg_memory = (1,1,0);
my %gets = ( my %gets = (
"id" => "", "id" => "",
@ -229,13 +231,16 @@ sub OWCOUNT_Define ($$) {
if( $model eq "DS2423" ){ if( $model eq "DS2423" ){
$fam = "1D"; $fam = "1D";
CommandAttr (undef,"$name model DS2423"); CommandAttr (undef,"$name model DS2423");
@owg_memory = (1,1,0);
}elsif( $model eq "DS2423enew" ){ }elsif( $model eq "DS2423enew" ){
$fam = "1D"; $fam = "1D";
@owg_memory = (1,1,0);
CommandAttr (undef,"$name model DS2423enew"); CommandAttr (undef,"$name model DS2423enew");
}elsif( $model eq "DS2423eold" ){ }elsif( $model eq "DS2423eold" ){
$fam = "1D"; $fam = "1D";
CommandAttr (undef,"$name model DS2423eold"); CommandAttr (undef,"$name model DS2423eold");
CommandAttr (undef,"$name nomemory 1"); CommandAttr (undef,"$name nomemory 1");
@owg_memory = (0,0,0);
}else{ }else{
return "OWCOUNT: Wrong 1-Wire device model $model"; return "OWCOUNT: Wrong 1-Wire device model $model";
} }
@ -301,12 +306,61 @@ sub OWCOUNT_Notify ($$) {
sub OWCOUNT_Init ($) { sub OWCOUNT_Init ($) {
my ($hash)=@_; my ($hash)=@_;
#-- Start timer for updates #-- Start timer for updates
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+10, "OWCOUNT_GetValues", $hash, 0); InternalTimer(gettimeofday()+10, "OWCOUNT_GetValues", $hash, 0);
return undef; return undef;
} }
########################################################################################
#
# OWCOUNT_InitializeDevice - delayed setting of initial readings and channel names
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWCOUNT_InitializeDevice($) {
my ($hash) = @_;
my $name = $hash->{NAME};
#-- get memory page/counter according to interface type
my $master= $hash->{IODev};
my $interface= $hash->{IODev}->{TYPE};
my $olddata = "";
my ($olddata1,$olddata2);
my $newdata = "OWCOUNT ".$owx_version;
my $ret;
#-- initial values
for( my $i=0;$i<int(@owg_fixed);$i++) {
#-- initial readings
$hash->{owg_val}->[$i] = "";
$hash->{owg_midnight}->[$i] = "";
$hash->{owg_str}->[$i] = "";
}
#-- Check memory string
my $memory;
if( ($owg_memory[0]==1) && ($owg_memory[1]==1) ){
$memory="page 0..13 and midnight";
}elsif( ($owg_memory[0]==0) && ($owg_memory[1]==1) ){
$memory="midnight only";
}elsif( ($owg_memory[0]==1) && ($owg_memory[1]==0) ){
$memory="page 0..13 only";
}else{
$memory="no pages, no midnight";
}
readingsSingleUpdate($hash,"memory","$memory",0);
#-- Set state to initialized
readingsSingleUpdate($hash,"state","initialized",1);
return undef;
}
####################################################################################### #######################################################################################
# #
# OWCOUNT_Attr - Set one attribute value for device # OWCOUNT_Attr - Set one attribute value for device
@ -369,56 +423,56 @@ sub OWCOUNT_ChannelNames($) {
for (my $i=0;$i<int(@owg_fixed);$i++){ for (my $i=0;$i<int(@owg_fixed);$i++){
#-- name #-- name
$cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : $owg_fixed[$i]; $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : "$owg_fixed[$i]";
@cnama = split(/\|/,$cname); @cnama = split(/\|/,$cname);
if( int(@cnama)!=2){ if( int(@cnama)!=2){
push(@cnama,$cnama[0]); push(@cnama,$cnama[0]);
} }
#-- unit #-- unit
$unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "counts|cts"; $unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "cts";
@unarr= split(/\|/,$unit); if( $unit eq "none" ){
if( int(@unarr)!=2 ){ $unit = "";
push(@unarr,$unarr[0]); }else{
$unit = " ".$unit;
} }
#-- put into readings #-- put into readings
$owg_channel[$i]=$cnama[0]; $owg_channel[$i]=$cnama[0];
$hash->{READINGS}{$owg_channel[$i]}{ABBR} = $cnama[1]; $hash->{READINGS}{$owg_channel[$i]}{ABBR} = $cnama[1];
$hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unarr[0]; $hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unit;
$hash->{READINGS}{$owg_channel[$i]}{UNITABBR} = $unarr[1];
$period = defined($attr{$name}{$owg_fixed[$i]."Period"}) ? $attr{$name}{$owg_fixed[$i]."Period"} : "hour"; $period = defined($attr{$name}{$owg_fixed[$i]."Period"}) ? $attr{$name}{$owg_fixed[$i]."Period"} : "hour";
#-- put into readings #-- put into readings
$hash->{READINGS}{$owg_channel[$i]}{PERIOD} = $period; $hash->{READINGS}{$owg_channel[$i]}{PERIOD} = $period;
#-- rate #-- rate
$cname = defined($attr{$name}{$owg_fixed[$i]."Rate"}) ? $attr{$name}{$owg_fixed[$i]."Rate"} : $cnama[0]."_rate|".$cnama[1]."_rate"; $cname = defined($attr{$name}{$owg_fixed[$i]."Rate"}) ? $attr{$name}{$owg_fixed[$i]."Rate"} :
(defined($attr{$name}{$owg_fixed[$i]."Name"}) ? "$cnama[0]_rate|$cnama[1]_r" : "$owg_fixed[$i]_rate|$owg_fixed[$i]_r");
@cnama = split(/\|/,$cname); @cnama = split(/\|/,$cname);
if( int(@cnama)!=2){ if( int(@cnama)!=2){
push(@cnama,$cnama[0]); push(@cnama,$cnama[0]);
} }
#-- rate unit #-- rate unit
my $runit = ""; if( $unit ne " " ){
if( $period eq "hour" ){ if( $period eq "hour" ){
$runit = "/h"; $unit .= "/h";
}elsif( $period eq "minute" ){ }elsif( $period eq "minute" ){
$runit = "/min"; $unit .= "/min";
} else { } else {
$runit = "/s"; $unit .= "/s";
}
} }
#-- put into readings
$owg_rate[$i]=$cnama[0];
$hash->{READINGS}{$owg_rate[$i]}{ABBR} = $cnama[1];
$hash->{READINGS}{$owg_rate[$i]}{UNIT} = $unarr[0].$runit;
$hash->{READINGS}{$owg_rate[$i]}{UNITABBR} = $unarr[1].$runit;
#-- some special cases #-- some special cases
# Energy/Power # Energy/Power
$hash->{READINGS}{$owg_rate[$i]}{UNIT} = "kW" $unit = " kW"
if ($unarr[0].$runit eq "kWh/h" ); if ($unit eq " kWh/h" );
$hash->{READINGS}{$owg_rate[$i]}{UNITABBR} = "kW"
if ($unarr[1].$runit eq "kWh/h" ); #-- put into readings
$owg_rate[$i]=$cnama[0];
$hash->{READINGS}{$owg_rate[$i]}{ABBR} = $cnama[1];
$hash->{READINGS}{$owg_rate[$i]}{UNIT} = $unit;
} }
} }
@ -467,9 +521,34 @@ sub OWCOUNT_FormatValues($) {
} }
} }
#-- put into READINGS #-- put into READING
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
#-- Check memory string
if( $owg_memory[2]==1 ){
my $memory;
my $model = $hash->{OW_MODEL};
my $nomemory;
if( ($owg_memory[0]==1) && ($owg_memory[1]==1) ){
$memory = "page 0..13 and midnight";
$model = "DS2423";
$nomemory = 0;
}elsif( ($owg_memory[0]==0) && ($owg_memory[1]==1) ){
$memory="midnight only";
$model = "DS2423enew";
$nomemory = 0;
}else{
$memory="no pages, no midnight";
$model = "DS2423eold";
$nomemory = 1;
}
CommandAttr (undef,"$name model ".$model);
CommandAttr (undef,"$name nomemory ".$nomemory);
readingsBulkUpdate($hash,"memory","$memory");
$owg_memory[2]=0;
}
#-- formats for output #-- formats for output
for (my $i=0;$i<int(@owg_fixed);$i++){ for (my $i=0;$i<int(@owg_fixed);$i++){
@ -489,13 +568,13 @@ sub OWCOUNT_FormatValues($) {
$hash->{READINGS}{$owg_channel[$i]}{OFFSET} = $offset; $hash->{READINGS}{$owg_channel[$i]}{OFFSET} = $offset;
$hash->{READINGS}{$owg_channel[$i]}{FACTOR} = $factor; $hash->{READINGS}{$owg_channel[$i]}{FACTOR} = $factor;
$unit = $hash->{READINGS}{$owg_channel[$i]}{UNITABBR}; $unit = $hash->{READINGS}{$owg_channel[$i]}{UNIT};
$period = $hash->{READINGS}{$owg_channel[$i]}{PERIOD}; $period = $hash->{READINGS}{$owg_channel[$i]}{PERIOD};
$runit = $hash->{READINGS}{$owg_rate[$i]}{UNITABBR}; $runit = $hash->{READINGS}{$owg_rate[$i]}{UNIT};
#-- skip some things if undefined #-- skip some things if undefined
if( $hash->{owg_val}->[$i] eq ""){ if( $hash->{owg_val}->[$i] eq ""){
$svalue .= $owg_channel[$i].": ???"; $svalue .= $owg_channel[$i]." ???";
}else{ }else{
#-- only if attribute value mode=daily, take the midnight value from memory #-- only if attribute value mode=daily, take the midnight value from memory
if( $daily == 1){ if( $daily == 1){
@ -555,6 +634,7 @@ sub OWCOUNT_FormatValues($) {
my $msg = sprintf("%4d-%02d-%02d midnight %7.2f", my $msg = sprintf("%4d-%02d-%02d midnight %7.2f",
$year+1900,$month+1,$day,$dval2); $year+1900,$month+1,$day,$dval2);
OWCOUNT_SetPage($hash,14+$i,$msg); OWCOUNT_SetPage($hash,14+$i,$msg);
Log3 $name,5,"OWCOUNT: measured value $vval (midnight ".$hash->{owg_midnight}->[$i].") => new extrapolated midnight $dval2";
#-- string buildup for monthly and yearly logging #-- string buildup for monthly and yearly logging
$dvalue .= sprintf( " %s: %5.2f %s %sM: %%5.2f %s", $owg_channel[$i],$dval,$unit,$owg_channel[$i],$unit); $dvalue .= sprintf( " %s: %5.2f %s %sM: %%5.2f %s", $owg_channel[$i],$dval,$unit,$owg_channel[$i],$unit);
@ -563,7 +643,7 @@ sub OWCOUNT_FormatValues($) {
#-- string buildup for return value and STATE #-- string buildup for return value and STATE
#-- 1 or 3 decimals #-- 1 or 3 decimals
my $fs = ( $factor == 1.0 )? "%s: %5.2f %s %s: %5.2f %s":"%s: %5.3f %s %s: %5.3f %s"; my $fs = ( $factor == 1.0 )? "%s: %5.2f %s %s: %5.2f %s" : "%s: %5.3f %s %s: %5.3f %s";
$svalue .= sprintf( $fs, $hash->{READINGS}{$owg_channel[$i]}{ABBR}, $vval,$unit,$hash->{READINGS}{$owg_rate[$i]}{ABBR},$vrate,$runit); $svalue .= sprintf( $fs, $hash->{READINGS}{$owg_channel[$i]}{ABBR}, $vval,$unit,$hash->{READINGS}{$owg_rate[$i]}{ABBR},$vrate,$runit);
#-- 3 decimals #-- 3 decimals
} }
@ -585,7 +665,7 @@ sub OWCOUNT_FormatValues($) {
#-- put in monthly and yearly sums #-- put in monthly and yearly sums
if( int(@monthv) == 2 ){ if( int(@monthv) == 2 ){
$total0 = $monthv[0]->[1]; $total0 = $monthv[0]->[1];
$total1 = $monthv[1]->[1]; $total1 = ($day==1)?$total0:$monthv[1]->[1];
$dvalue = sprintf("D%02d ",$day).$dvalue; $dvalue = sprintf("D%02d ",$day).$dvalue;
$dvalue = sprintf($dvalue,$total0,$total1); $dvalue = sprintf($dvalue,$total0,$total1);
readingsBulkUpdate($hash,"day",$dvalue); readingsBulkUpdate($hash,"day",$dvalue);
@ -597,7 +677,7 @@ sub OWCOUNT_FormatValues($) {
if( int(@yearv) == 2 ){ if( int(@yearv) == 2 ){
$total2 = $yearv[0]->[1]; $total2 = $yearv[0]->[1];
$total3 = $yearv[1]->[1]; $total3 = ($month==0)?$total2: $yearv[1]->[1];
if ( $monthbreak == 1){ if ( $monthbreak == 1){
$mvalue = sprintf("M%02d ",$month+1).$mvalue; $mvalue = sprintf("M%02d ",$month+1).$mvalue;
$mvalue = sprintf($mvalue,$total0,$total2,$total1,$total3); $mvalue = sprintf($mvalue,$total0,$total2,$total1,$total3);
@ -631,6 +711,7 @@ sub OWCOUNT_Get($@) {
my $reading = $a[1]; my $reading = $a[1];
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL}; my $model = $hash->{OW_MODEL};
my $master = $hash->{IODev};
my $value = undef; my $value = undef;
my $ret = ""; my $ret = "";
my $page; my $page;
@ -655,18 +736,20 @@ sub OWCOUNT_Get($@) {
if($a[1] eq "present") { if($a[1] eq "present") {
#-- hash of the busmaster #-- hash of the busmaster
my $master = $hash->{IODev}; my $master = $hash->{IODev};
#-- asynchronous mode
if( $hash->{ASYNC} ){ #-- normal OWX
if( !$hash->{ASYNC} ){
$value = OWX_Verify($master,$hash->{ROM_ID});
$hash->{PRESENT} = $value;
return "$name.present => $value";
#-- old asynchronous mode
}else{
eval { eval {
OWX_ASYNC_RunToCompletion($hash,OWX_ASYNC_PT_Verify($hash)); OWX_ASYNC_RunToCompletion($hash,OWX_ASYNC_PT_Verify($hash));
}; };
return GP_Catch($@) if $@; return GP_Catch($@) if $@;
return "$name.present => ".ReadingsVal($name,"present","unknown"); return "$name.present => ".ReadingsVal($name,"present","unknown");
} else {
$value = OWX_Verify($master,$hash->{ROM_ID});
} }
$hash->{PRESENT} = $value;
return "$name.present => $value";
} }
#-- get interval #-- get interval
@ -733,7 +816,7 @@ sub OWCOUNT_Get($@) {
$value .= $owg_channel[$i]."Y: ".$year2[$i]->[1]." ".$unit. $value .= $owg_channel[$i]."Y: ".$year2[$i]->[1]." ".$unit.
" (yearly sum until now, average ".$year2[$i]->[2]." ".$unit."/d)\n"; " (yearly sum until now, average ".$year2[$i]->[2]." ".$unit."/d)\n";
}else{ }else{
$value .= $owg_channel[$i]."Y: ".$year2[$i]->[1]." ".$unit." (last month)\n"; $value .= $owg_channel[$i]."Y: ".$year2[$i]->[1]." ".$unit."\n";
} }
} }
return $value; return $value;
@ -754,6 +837,10 @@ sub OWCOUNT_Get($@) {
return "OWCOUNT: Wrong memory page requested"; return "OWCOUNT: Wrong memory page requested";
} }
$ret = OWCOUNT_GetPage($hash,$page,1,1); $ret = OWCOUNT_GetPage($hash,$page,1,1);
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWCOUNT: $name getting memory $page, please wait for completion";
}else{
#-- when we have a return code, we have an error #-- when we have a return code, we have an error
if( $ret ){ if( $ret ){
return "OWCOUNT: Could not get values from device $name, reason: ".$ret; return "OWCOUNT: Could not get values from device $name, reason: ".$ret;
@ -761,6 +848,7 @@ sub OWCOUNT_Get($@) {
return "OWCOUNT: $name.$reading [$page] =>".$hash->{owg_str}->[$page]; return "OWCOUNT: $name.$reading [$page] =>".$hash->{owg_str}->[$page];
} }
} }
}
if( $reading eq "midnight" ){ if( $reading eq "midnight" ){
return "OWCOUNT: get needs parameter when reading midnight: <channel>" return "OWCOUNT: get needs parameter when reading midnight: <channel>"
if( int(@a)<3 ); if( int(@a)<3 );
@ -773,6 +861,10 @@ sub OWCOUNT_Get($@) {
return "OWCOUNT: Invalid midnight counter address, must be A, B or defined channel name" return "OWCOUNT: Invalid midnight counter address, must be A, B or defined channel name"
} }
$ret = OWCOUNT_GetPage($hash,$page,1,1); $ret = OWCOUNT_GetPage($hash,$page,1,1);
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWCOUNT: $name getting midnight value $page and counter, please wait for completion";
}else{
#-- when we have a return code, we have an error #-- when we have a return code, we have an error
if( $ret ){ if( $ret ){
return "OWCOUNT: Could not get values from device $name, reason: ".$ret; return "OWCOUNT: Could not get values from device $name, reason: ".$ret;
@ -780,6 +872,7 @@ sub OWCOUNT_Get($@) {
return "OWCOUNT: $name.$reading [$page] =>".$hash->{owg_midnight}->[$page-14]; return "OWCOUNT: $name.$reading [$page] =>".$hash->{owg_midnight}->[$page-14];
} }
} }
}
#-- check syntax for getting counter #-- check syntax for getting counter
if( $reading eq "raw" ){ if( $reading eq "raw" ){
@ -794,21 +887,27 @@ sub OWCOUNT_Get($@) {
return "OWCOUNT: Invalid counter address, must be A, B or defined channel name" return "OWCOUNT: Invalid counter address, must be A, B or defined channel name"
} }
$ret = OWCOUNT_GetPage($hash,$page,1,1); $ret = OWCOUNT_GetPage($hash,$page,1,1);
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWCOUNT: $name getting page $page and counter, please wait for completion";
}else{
#-- when we have a return code, we have an error #-- when we have a return code, we have an error
if( $ret ){ if( $ret ){
return "OWCOUNT: Could not get values from device $name, reason: ".$ret; return "OWCOUNT: Could not get values from device $name, reason: ".$ret;
} }
#-- only one counter will be returned #-- only one counter will be returned
return "OWCOUNT: $name.raw $a[2] => ".$hash->{owg_val}->[$page-14]; return "OWCOUNT: $name.raw $a[2] => ".$hash->{owg_val}->[$page-14];
}
#-- check syntax for getting counters #-- check syntax for getting counters
}elsif( $reading eq "counters" ){ }elsif( $reading eq "counters" ){
return "OWCOUNT: Get needs no parameter when reading counters" return "OWCOUNT: Get needs no parameter when reading counters"
if( int(@a)==1 ); if( int(@a)==1 );
$ret1 = OWCOUNT_GetPage($hash,14,0,1); $ret1 = OWCOUNT_GetPage($hash,14,0,1);
$ret2 = OWCOUNT_GetPage($hash,15,1,1); $ret2 = OWCOUNT_GetPage($hash,15,1,1);
#-- process result
#-- process results if( $master->{ASYNCHRONOUS} ){
return "OWCOUNT: $name getting counters, please wait for completion";
}else{
$ret .= $ret1 $ret .= $ret1
if( defined($ret1) ); if( defined($ret1) );
$ret .= $ret2 $ret .= $ret2
@ -819,6 +918,7 @@ sub OWCOUNT_Get($@) {
#-- both counters will be returned #-- both counters will be returned
return "OWCOUNT: $name.counters => ".$hash->{READINGS}{"state"}{VAL}; return "OWCOUNT: $name.counters => ".$hash->{READINGS}{"state"}{VAL};
} }
}
} }
####################################################################################### #######################################################################################
@ -926,7 +1026,7 @@ sub OWCOUNT_GetMonth($) {
@linarr = split(' ',$line); @linarr = split(' ',$line);
if( int(@linarr)==4+6*int(@owg_fixed) ){ if( int(@linarr)==4+6*int(@owg_fixed) ){
$day = $linarr[3]; $day = $linarr[3];
$day =~ s/D_0+//; $day =~ s/D_+0+//;
@mchannel = (); @mchannel = ();
for (my $i=0;$i<int(@owg_fixed);$i++){ for (my $i=0;$i<int(@owg_fixed);$i++){
$val = $linarr[5+6*$i]; $val = $linarr[5+6*$i];
@ -936,9 +1036,8 @@ sub OWCOUNT_GetMonth($) {
} }
} }
} }
if( int(@month)==0 ){ if( int(@month)<($cday-1) ){
return "invalid logfile format in LogM" Log3 $name,3, "OWCOUNT: warning, found only ".int(@month)." lines in logfile $lf of LogM";
if( $cday!=1 );
} }
} else { } else {
return "cannot open logfile of LogM"; return "cannot open logfile of LogM";
@ -1023,7 +1122,7 @@ sub OWCOUNT_GetYear($) {
@linarr = split(' ',$line); @linarr = split(' ',$line);
if( int(@linarr)==4+6*int(@owg_fixed) ){ if( int(@linarr)==4+6*int(@owg_fixed) ){
$month = $linarr[3]; $month = $linarr[3];
$month =~ s/M_0+//; $month =~ s/M_+0+//;
@mchannel = (); @mchannel = ();
for (my $i=0;$i<int(@owg_fixed);$i++){ for (my $i=0;$i<int(@owg_fixed);$i++){
$val = $linarr[5+6*$i]; $val = $linarr[5+6*$i];
@ -1033,9 +1132,8 @@ sub OWCOUNT_GetYear($) {
} }
} }
} }
if( int(@year)==0 ){ if( int(@year)<($cmonth-1) ){
return "invalid logfile format in LogY" Log3 $name,3, "OWCOUNT: warning, found only ".int(@year)." lines in logfile $lf of LogY";
if($cmonth != 1);
} }
} else { } else {
return "cannot open logfile of LogY"; return "cannot open logfile of LogY";
@ -1046,13 +1144,13 @@ sub OWCOUNT_GetYear($) {
my @month2 = OWCOUNT_GetMonth($hash); my @month2 = OWCOUNT_GetMonth($hash);
for (my $i=0;$i<int(@owg_fixed);$i++){ for (my $i=0;$i<int(@owg_fixed);$i++){
$total = 0.0; $total = 0.0;
#-- summing only if mode daily (means daily reset !)
$daily = 0; $daily = 0;
if( defined($attr{$name}{$owg_fixed[$i]."Mode"} )){ if( defined($attr{$name}{$owg_fixed[$i]."Mode"} )){
if( $attr{$name}{$owg_fixed[$i]."Mode"} eq "daily"){ if( $attr{$name}{$owg_fixed[$i]."Mode"} eq "daily"){
$daily = 1; $daily = 1;
} }
} }
#-- sum previous months only in daily mode
if( $daily==1){ if( $daily==1){
for (my $j=0;$j<int(@year);$j++){ for (my $j=0;$j<int(@year);$j++){
$total += $year[$j][$i]; $total += $year[$j][$i];
@ -1061,10 +1159,12 @@ sub OWCOUNT_GetYear($) {
$total = $year[int(@year)-1][$i] $total = $year[int(@year)-1][$i]
if (int(@year)>0); if (int(@year)>0);
}; };
#-- add data from current day also for non-summed mode
$total = int($total*100)/100; $total = int($total*100)/100;
$total2 = int(100*($total+$month2[$i]->[1]))/100; #-- data from this month is
$total2 = int(100*($month2[$i]->[1]))/100;
#-- add data from this month and previous months in daily mode
$total2+=$total
if( $daily==1 );
#-- number of days so far, including the present day #-- number of days so far, including the present day
my $deltim = $cyday+($chour+$cmin/60.0 + $csec/3600.0)/24.0; my $deltim = $cyday+($chour+$cmin/60.0 + $csec/3600.0)/24.0;
my $av = $deltim>0 ? int(100*$total2/$deltim)/100 : -1; my $av = $deltim>0 ? int(100*$total2/$deltim)/100 : -1;
@ -1111,106 +1211,6 @@ sub OWCOUNT_GetValues($) {
if( $ret ne "" ){ if( $ret ne "" ){
return "OWCOUNT: Could not get values from device $name, reason: ".$ret; return "OWCOUNT: Could not get values from device $name, reason: ".$ret;
} }
return undef;
}
########################################################################################
#
# OWCOUNT_InitializeDevice - delayed setting of initial readings and channel names
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWCOUNT_InitializeDevice($) {
my ($hash) = @_;
my $name = $hash->{NAME};
#-- get memory page/counter according to interface type
my $master= $hash->{IODev};
my $interface= $hash->{IODev}->{TYPE};
my $olddata = "";
my $newdata = "OWCOUNT ".$owx_version;
my $ret;
#-- initial values
for( my $i=0;$i<int(@owg_fixed);$i++) {
#-- initial readings
$hash->{owg_val}->[$i] = "";
$hash->{owg_midnight}->[$i] = "";
$hash->{owg_str}->[$i] = "";
}
#-- testing if it is the emulator
#-- The model may be DS2423, DS2423enew or DS2423eold. Some weird people are violating 1-Wire integrity by using the
# the same family ID although the DS2423emu does not fully support the DS2423 commands.
# Model attribute will be modified now after checking for memory
#-- OWX interface
if( $interface eq "OWX" ){
$ret = OWXCOUNT_GetPage($hash,14,0);
$olddata = $hash->{owg_str}->[14];
$ret = OWXCOUNT_SetPage($hash,14,$newdata);
$ret = OWXCOUNT_GetPage($hash,14,0);
$ret = OWXCOUNT_SetPage($hash,14,$olddata);
}elsif( $interface eq "OWX_ASYNC" ){
eval {
$ret = OWX_ASYNC_RunToCompletion($hash,OWXCOUNT_PT_InitializeDevicePage($hash,14,$newdata));
};
$ret = GP_Catch($@) if $@;
#-- OWFS interface
}elsif( $interface eq "OWServer" ){
$ret = OWFSCOUNT_GetPage($hash,14,0);
$olddata = $hash->{owg_str}->[14];
$ret = OWFSCOUNT_SetPage($hash,14,$newdata);
$ret = OWFSCOUNT_GetPage($hash,14,0);
$ret = OWFSCOUNT_SetPage($hash,14,$olddata);
#-- Unknown interface
}else{
return "OWCOUNT: InitializeDevice with wrong IODev type $interface";
}
#Log 1,"FIRST CHECK: written $newdata, read ".substr($hash->{owg_str}->[14],0,length($newdata));
my $nomid = ( substr($hash->{owg_str}->[14],0,length($newdata)) ne $newdata );
#-- OWX interface
if( $interface eq "OWX" ){
$ret = OWXCOUNT_GetPage($hash,0,0);
$olddata = $hash->{owg_str}->[0];
$ret = OWXCOUNT_SetPage($hash,0,$newdata);
$ret = OWXCOUNT_GetPage($hash,0,0);
$ret = OWXCOUNT_SetPage($hash,0,$olddata);
}elsif( $interface eq "OWX_ASYNC" ){
eval {
$ret = OWX_ASYNC_RunToCompletion($hash,OWXCOUNT_PT_InitializeDevicePage($hash,0,$newdata));
};
$ret = GP_Catch($@) if $@;
#-- OWFS interface
}elsif( $interface eq "OWServer" ){
$ret = OWFSCOUNT_GetPage($hash,0,0);
$olddata = $hash->{owg_str}->[0];
$ret = OWFSCOUNT_SetPage($hash,0,$newdata);
$ret = OWFSCOUNT_GetPage($hash,0,0);
$ret = OWFSCOUNT_SetPage($hash,0,$olddata);
#-- Unknown interface
}else{
return "OWCOUNT: InitializeDevice with wrong IODev type $interface";
}
#Log 1,"SECOND CHECK: written $newdata, read ".substr($hash->{owg_str}->[0],0,length($newdata));
my $nomem = ( substr($hash->{owg_str}->[0],0,length($newdata)) ne $newdata );
#-- Here we test if writing the memory is ok.
if( !$nomid && $nomem ){
Log3 $name,1,"OWCOUNT: model attribute of $name set to DS2423enew";
CommandAttr (undef,"$name model DS2423enew");
CommandAttr (undef,"$name nomemory 0");
} elsif( $nomid && $nomem ){
Log3 $name,1,"OWCOUNT: model attribute of $name set to DS2423eold because no memory found";
CommandAttr (undef,"$name model DS2423eold");
CommandAttr (undef,"$name nomemory 1");
}
#-- Set state to initialized
readingsSingleUpdate($hash,"state","initialized",1);
return undef; return undef;
} }
@ -1315,7 +1315,7 @@ sub OWCOUNT_Set($@) {
$data.=" ".$a[$i]; $data.=" ".$a[$i];
} }
if( length($data) > 32 ){ if( length($data) > 32 ){
Log3 $name,1,"OWXCOUNT: Memory data truncated to 32 characters"; Log3 $name,3,"OWCOUNT: Memory data truncated to 32 characters";
$data=substr($data,0,32); $data=substr($data,0,32);
}elsif( length($data) < 32 ){ }elsif( length($data) < 32 ){
for(my $i=length($data)-1;$i<32;$i++){ for(my $i=length($data)-1;$i<32;$i++){
@ -1360,7 +1360,7 @@ sub OWCOUNT_Set($@) {
$hash->{READINGS}{$owg_channel[$page-14]}{FACTOR} - $a[3]; $hash->{READINGS}{$owg_channel[$page-14]}{FACTOR} - $a[3];
$data = sprintf("%4d-%02d-%02d midnight %7.2f", $data = sprintf("%4d-%02d-%02d midnight %7.2f",
$year+1900,$month+1,$day,$midnew); $year+1900,$month+1,$day,$midnew);
#Log 1,"OLD MIDNIGHT ".$hash->{owg_midnight}->[$page-14]." NEW $midnew"; Log3 $name,5,"OWCOUNT: old midnight vakue ".$hash->{owg_midnight}->[$page-14].", replaced by $midnew";
$ret = OWCOUNT_SetPage($hash,$page,$data); $ret = OWCOUNT_SetPage($hash,$page,$data);
} }
} }
@ -1447,12 +1447,12 @@ sub OWCOUNT_store($$$) {
} else { } else {
Log3 $name,1,"OWCOUNT_store: Cannot open $filename for writing!"; Log3 $name,1,"OWCOUNT_store: Cannot open $filename for writing!";
} }
return undef; return $ret;
} }
######################################################################################## ########################################################################################
# #
# Recall daily start value from a file # OWCOUNT_recall Recall daily start value from a file
# #
# Parameter hash,filename # Parameter hash,filename
# #
@ -1470,8 +1470,18 @@ sub OWCOUNT_recall($$) {
close(OWXFILE); close(OWXFILE);
return $line; return $line;
} }
Log3 $name,1, "OWCOUNT_recall: Cannot open $filename for reading!"; Log3 $name,1, "OWCOUNT_recall: Cannot open $filename for reading, 2nd attempt";
return undef;; $ret = OWCOUNT_store($hash,$filename,0);
if (!$ret){
$ret = open(OWXFILE, "< $mp/FHEM/$filename" );
if( $ret ){
my $line = readline OWXFILE;
close(OWXFILE);
return $line;
}
Log3 $name,1, "OWCOUNT_recall: Cannot open $filename for reading - tried twice";
return "error";
}
} }
######################################################################################## ########################################################################################
@ -1494,6 +1504,8 @@ sub OWCOUNT_Undef ($) {
# The following subroutines in alphabetical order are only for a 1-Wire bus connected # The following subroutines in alphabetical order are only for a 1-Wire bus connected
# via OWFS # via OWFS
# #
# TODO: So far no automatic recognition of DS2423 / Emulator
#
# Prefix = OWFSCOUNT # Prefix = OWFSCOUNT
# #
######################################################################################## ########################################################################################
@ -1603,76 +1615,125 @@ sub OWFSCOUNT_SetPage($$$) {
# OWXCOUNT_BinValues - Process reading from one device - translate binary into raw # OWXCOUNT_BinValues - Process reading from one device - translate binary into raw
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# context = mode for evaluating the binary data
# proc = processing instruction, also passed to OWX_Read.
# bitwise interpretation !!
# if 0, nothing special
# if 1 = bit 0, a reset will be performed not only before, but also after
# the last operation in OWX_Read
# if 2 = bit 1, the initial reset of the bus will be suppressed
# if 8 = bit 3, the fillup of the data with 0xff will be suppressed
# if 16= bit 4, the insertion will be at the top of the queue
# owx_dev = ROM ID of slave device
# crcpart = part of the data that needs to be part of the CRC check
# numread = number of bytes to receive
# res = result string
# #
######################################################################################## #
#######################################################################################
sub OWXCOUNT_BinValues($$$$$) { sub OWXCOUNT_BinValues($$$$$$$) {
my ($hash, $context, $owx_dev, $select, $res) = @_; my ($hash, $context, $proc, $owx_dev, $crcpart, $numread, $res) = @_;
#-- unused are success, reset, data #-- hash of the busmaster
my $master = $hash->{IODev};
return undef unless (defined $context and $context =~ /^(get|set)page\.([\d]+)(\.final|)$/); my $name = $hash->{NAME};
my @data=[];
my $value;
my $msg;
OWX_WDBG($name,"OWCOUNT_BinValues called for device $name in context $context with ",$res)
if( $main::owx_debug>2 );
return undef unless (defined $context and $context =~ /^(get|set|check)page\.([\d]+)(\.final|)$/);
my $cmd = $1; my $cmd = $1;
my $page = $2; my $page = $2;
my $final = $3; my $final = $3;
my $name = $hash->{NAME}; #=============== get memory + counter ===============================
Log3 ($name,5,"OWXCount_BinValues context: $context, $cmd page: $page, final: ".(defined $final ? $final : "undef"));
if ($cmd eq "get") { if ($cmd eq "get") {
my ($i,$j,$k,@data,@writedata,$strval,$value); my (@data,$strval,$value);
my $change = 0; my $change = 0;
@data=split(//,$res);
#-- process results #-- process results
@data=split(//,$res); if(ord($data[17])<=0){
@writedata = split(//,$select); #-- invalid data: do not die, but change memory flags
return "invalid data length, ".int(@data)." instead of 42 bytes in three steps" if( $page > 13 ){
if( int(@data) < 42); $owg_memory[1]=0;
#return "invalid data" }else{
# if (ord($data[17])<=0); $owg_memory[0]=0;
return "invalid CRC, ".ord($data[40])." ".ord($data[41]) }
if (OWX_CRC16($select.substr($res,0,40),$data[40],$data[41]) == 0); $owg_memory[2]=1;
$msg="memory data could not be read";
}else{
if( $page > 13 ){
$owg_memory[1]=1;
}else{
$owg_memory[0]=1;
}
$owg_memory[2]=1;
}
#-- first 3 command, next 32 are memory if( int(@data) < 42){
#my $res2 = "OWCOUNT FIRST 10 BYTES for device $owx_dev ARE "; $msg="$name returns invalid data length, ".int(@data)." instead of 42 bytes";
#for($i=0;$i<10;$i++){ }elsif (OWX_CRC16($crcpart.substr($res,0,40),$data[40],$data[41]) == 0){
# $j=int(ord(substr($res,$i,1))/16); $msg="$name returns invalid CRC, ".ord($data[40])." ".ord($data[41]);
# $k=ord(substr($res,$i,1))%16; }
# $res2.=sprintf "0x%1x%1x ",$j,$k; OWX_WDBG($name,"OWXCOUNT_BinValues: ".$msg,"")
#} if( $main::owx_debug>2 );
#main::Log(1, $res2);
#-- #--
my $nomemory = defined($attr{$name}{"nomemory"}) ? $attr{$name}{"nomemory"} : 0; my $nomemory = defined($attr{$name}{"nomemory"}) ? $attr{$name}{"nomemory"} : 0;
if( $nomemory==0 ){ if( $nomemory==0 ){
#-- memory part, treated as string #-- memory part, treated as string
$strval=substr($res,0,32); $strval=substr($res,0,32);
#Log 1," retrieved on device $owx_dev for page $page STRING $strval"; #Log3 $name,5,"OWCOUNT: retrieved from memory for page $page ==> $strval";
} else { } else {
$strval = OWCOUNT_recall($hash,"OWCOUNT_".$hash->{NAME}."_".$page.".dat"); $strval = OWCOUNT_recall($hash,"OWCOUNT_".$hash->{NAME}."_".$page.".dat");
#Log3 $name,5,"OWCOUNT: retrieved from disk for page $page ==> $strval";
} }
$hash->{owg_str}->[$page]= defined $strval ? $strval : ""; $hash->{owg_str}->[$page]= defined $strval ? $strval : "";
#-- counter part #-- counter part
if( ($page == 14) || ($page == 15) ){ if( ($page == 14) || ($page == 15) ){
@data=split(//,substr($res,32)); @data=split(//,substr($res,32));
if ( ($data[4] | $data[5] | $data[6] | $data[7]) ne "\x00" ){ if ( ($data[4] | $data[5] | $data[6] | $data[7]) ne "\x00" ){
#Log 1, "device $owx_dev returns invalid data ".ord($data[4])." ".ord($data[5])." ".ord($data[6])." ".ord($data[7]); OWX_WDBG($name, "device $name returns invalid data ".ord($data[4])." ".ord($data[5])." ".ord($data[6])." ".ord($data[7])," ");
return "device $owx_dev returns invalid data";
} }
#-- counter value #-- counter value
$value = (ord($data[3])<<24) + (ord($data[2])<<16) +(ord($data[1])<<8) + ord($data[0]); $value = (ord($data[3])<<24) + (ord($data[2])<<16) +(ord($data[1])<<8) + ord($data[0]);
$hash->{owg_val}->[$page-14] = $value; $hash->{owg_val}->[$page-14] = $value;
#-- midnight value #-- midnight value
Log3 $name,5, "OWCOUNT_BinValues ParseMidnight: ".(defined $strval ? $strval : "undef"); #Log3 $name,1, "OWCOUNT_BinValues ParseMidnight: ".(defined $strval ? $strval : "undef");
OWCOUNT_ParseMidnight($hash,$strval,$page); OWCOUNT_ParseMidnight($hash,$strval,$page);
} }
#-- and now from raw to formatted values #-- and now from raw to formatted values
$hash->{PRESENT} = 1; $hash->{PRESENT} = 1;
if( $final ) { if( $final ) {
my $value = OWCOUNT_FormatValues($hash); my $value = OWCOUNT_FormatValues($hash);
Log3 $name,5, "OWCOUNT_BinValues->FormatValues returns: ".(defined $value ? $value : "undef");
} }
#=============== set memory ===============================
#-- for setting a page we need a second step where the scratchpad is copied into memory
}elsif (($cmd eq "set") && !$final ) {
my $select="\x5A".substr($res,0,3);
#### master slave context proc owx_dev data crcpart numread startread callback delay
# 16 inserts at top of queue
OWX_Qomplex($master, $hash, "setpage.$page.final", 16, $owx_dev, $select, 0, 6, 10, \&OWXCOUNT_BinValues, 0);
#-- and a third step where this is finalized
}elsif (($cmd eq "set") && $final ) {
if( substr($res,4,1) ne "\xAA" ){
if( $page > 13 ){
$owg_memory[1]=0;
}else{
$owg_memory[0]=0;
}
}else{
if( $page > 13){
$owg_memory[1]=1;
}else{
$owg_memory[0]=1;
}
}
#-- change applied
$owg_memory[2]=1;
} }
return undef; return undef;
} }
@ -1699,8 +1760,6 @@ sub OWXCOUNT_GetPage($$$) {
#-- reset presence #-- reset presence
$hash->{PRESENT} = 0; $hash->{PRESENT} = 0;
my ($i,$j,$k);
#=============== wrong value requested =============================== #=============== wrong value requested ===============================
if( ($page<0) || ($page>15) ){ if( ($page<0) || ($page>15) ){
return "wrong memory page requested"; return "wrong memory page requested";
@ -1713,6 +1772,8 @@ sub OWXCOUNT_GetPage($$$) {
$select=sprintf("\xA5%c%c",$ta1,$ta2); $select=sprintf("\xA5%c%c",$ta1,$ta2);
my $context = "getpage.".$page.($final ? ".final" : ""); my $context = "getpage.".$page.($final ? ".final" : "");
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
#-- reset the bus #-- reset the bus
OWX_Reset($master); OWX_Reset($master);
#-- reading 9 + 3 + 40 data bytes (32 byte memory, 4 byte counter + 4 byte zeroes) and 2 CRC bytes = 54 bytes #-- reading 9 + 3 + 40 data bytes (32 byte memory, 4 byte counter + 4 byte zeroes) and 2 CRC bytes = 54 bytes
@ -1739,7 +1800,17 @@ sub OWXCOUNT_GetPage($$$) {
if( $res eq 0 ); if( $res eq 0 );
return "$owx_dev has returned invalid data" return "$owx_dev has returned invalid data"
if( length($res)!=54); if( length($res)!=54);
return OWXCOUNT_BinValues($hash,$context,$owx_dev,$select,substr($res,12)); eval {
OWXCOUNT_BinValues($hash,$context,0,$owx_dev,$select,45,substr($res,12));
};
return $@ ? $@ : undef;
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
# 1 additional reset after last action
OWX_Qomplex($master, $hash, $context, 1, $owx_dev, $select, $select, 45, 12, \&OWXCOUNT_BinValues, 0);
return undef;
}
} }
######################################################################################## ########################################################################################
@ -1747,7 +1818,8 @@ sub OWXCOUNT_GetPage($$$) {
# OWXCOUNT_SetPage - Set one memory page of device # OWXCOUNT_SetPage - Set one memory page of device
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# page = "alarm" or "status" # page = 0..15
# data = string to set into memory
# #
######################################################################################## ########################################################################################
@ -1757,8 +1829,6 @@ sub OWXCOUNT_SetPage($$$) {
my ($select, $res, $res2, $res3); my ($select, $res, $res2, $res3);
my ($i,$j,$k);
#-- ID of the device, hash of the busmaster #-- ID of the device, hash of the busmaster
my $owx_dev = $hash->{ROM_ID}; my $owx_dev = $hash->{ROM_ID};
my $master = $hash->{IODev}; my $master = $hash->{IODev};
@ -1778,23 +1848,14 @@ sub OWXCOUNT_SetPage($$$) {
my $ta1 = ($page*32) & 255; my $ta1 = ($page*32) & 255;
#Log 1, "OWXCOUNT: setting page Nr. $ta2 $ta1 $data"; #Log 1, "OWXCOUNT: setting page Nr. $ta2 $ta1 $data";
$select=sprintf("\x0F%c%c",$ta1,$ta2).$data; $select=sprintf("\x0F%c%c",$ta1,$ta2).$data;
#-- OLD OWX interface
#-- first command, next 2 are address, then data if( !$master->{ASYNCHRONOUS} ){
#$res2 = "OWCOUNT SET PAGE 1 device $owx_dev ";
#for($i=0;$i<10;$i++){
# $j=int(ord(substr($select,$i,1))/16);
# $k=ord(substr($select,$i,1))%16;
# $res2.=sprintf "0x%1x%1x ",$j,$k;
#}
#main::Log(1, $res2);
#-- reset the bus #-- reset the bus
OWX_Reset($master); OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,0); $res=OWX_Complex($master,$owx_dev,$select,0);
if( $res eq 0 ){ if( $res eq 0 ){
return "device $owx_dev not accessible in writing scratchpad"; return "OWCOUNT: device $owx_dev not accessible in writing scratchpad";
} }
#-- issue the match ROM command \x55 and the read scratchpad command #-- issue the match ROM command \x55 and the read scratchpad command
# \xAA, receiving 2 address bytes, 1 status byte and scratchpad content # \xAA, receiving 2 address bytes, 1 status byte and scratchpad content
$select = "\xAA"; $select = "\xAA";
@ -1804,37 +1865,41 @@ sub OWXCOUNT_SetPage($$$) {
# TODO: sometimes much less than 28 # TODO: sometimes much less than 28
$res=OWX_Complex($master,$owx_dev,$select,28); $res=OWX_Complex($master,$owx_dev,$select,28);
if( length($res) < 13 ){ if( length($res) < 13 ){
return "device $owx_dev not accessible in reading scratchpad"; return "OWCOUNT: device $owx_dev not accessible in reading scratchpad";
} }
#-- first 1 command, next 2 are address, then data
#$res3 = substr($res,9,10);
#$res2 = "OWCOUNT SET PAGE 2 device $owx_dev ";
#for($i=0;$i<10;$i++){
# $j=int(ord(substr($res3,$i,1))/16);
# $k=ord(substr($res3,$i,1))%16;
# $res2.=sprintf "0x%1x%1x ",$j,$k;
#}
#main::Log(1, $res2);
#-- issue the match ROM command \x55 and the copy scratchpad command #-- issue the match ROM command \x55 and the copy scratchpad command
# \x5A followed by 3 byte authentication code obtained in previous read # \x5A followed by 3 byte authentication code obtained in previous read
$select="\x5A".substr($res,10,3); $select="\x5A".substr($res,10,3);
#-- first command, next 2 are address, then data
#$res2 = "OWCOUNT SET PAGE 3 device $owx_dev ";
#for($i=0;$i<10;$i++){
# $j=int(ord(substr($select,$i,1))/16);
# $k=ord(substr($select,$i,1))%16;
# $res2.=sprintf "0x%1x%1x ",$j,$k;
#}
#main::Log(1, $res2);
#-- reset the bus #-- reset the bus
OWX_Reset($master); OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,6); $res=OWX_Complex($master,$owx_dev,$select,6);
#-- process results #-- process results
if( $res eq 0 ){ if( $res eq 0 ){
return "device $owx_dev not accessible for copying scratchpad"; return "OWCOUNT: device $owx_dev not accessible for copying scratchpad";
}
if( substr($res,13,1) ne "\xAA" ){
if( $page > 13){
$owg_memory[1]=0;
}else{
$owg_memory[0]=0;
}
}else{
if( $page > 13){
$owg_memory[1]=1;
}else{
$owg_memory[0]=1;
}
}
$owg_memory[2]=1;
return undef;
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
# 8 prevents from filling up with 0xFF
OWX_Qomplex($master, $hash, undef, 8, $owx_dev, $select, $select, 35, 10, undef, 0);
#-- The third step of copying the scratchpad into memory can be scheduled only when the authorization code has been received
# will be done in the callback of the following line
OWX_Qomplex($master, $hash, "setpage.".$page, 0, $owx_dev, "\xAA", 0, 37, 10, \&OWXCOUNT_BinValues, 0);
} }
return undef; return undef;
} }
@ -1885,7 +1950,7 @@ sub OWXCOUNT_PT_GetPage($$$) {
PT_WAIT_THREAD($thread->{pt_execute}); PT_WAIT_THREAD($thread->{pt_execute});
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR); die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
if (my $ret = OWXCOUNT_BinValues($hash,"getpage.".$page.($final ? ".final" : ""),$owx_dev,$thread->{'select'},$thread->{response})) { if (my $ret = OWXCOUNT_BinValues($hash,"getpage.".$page.($final ? ".final" : ""),0,$owx_dev,$thread->{'select'},0,$thread->{response})) {
die $ret; die $ret;
} }
PT_END; PT_END;
@ -2026,13 +2091,13 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
<br /><h4>Example</h4><br /> <br /><h4>Example</h4><br />
<code>define OWC OWCOUNT 1D.CE780F000000 60</code> <code>define OWC OWCOUNT 1D.CE780F000000 60</code>
<br /> <br />
<code>attr OWC AName Energie|energy</code> <code>attr OWC AName energy|W</code>
<br /> <br />
<code>attr OWC AUnit kWh|kWh</code> <code>attr OWC AUnit kWh</code>
<br /> <br />
<code>attr OWC APeriod hour</code> <code>attr OWC APeriod hour</code>
<br /> <br />
<code>attr OWC ARate Leistung|power</code> <code>attr OWC ARate power|P</code>
<br /> <br />
<code>attr OWX_AMode daily</code> <code>attr OWX_AMode daily</code>
<br /> <br />
@ -2138,13 +2203,13 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
<ul> <ul>
<li><a name="owcount_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name <li><a name="owcount_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
&lt;string&gt;[|&lt;string&gt;]</code></a> &lt;string&gt;[|&lt;string&gt;]</code></a>
<br />name for the channel [|name used in state reading]. </li> <br />name for the channel [|short name used in state reading]. </li>
<li><a name="owcount_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit <li><a name="owcount_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit
&lt;string&gt;[|&lt;string&gt;]</code></a> &lt;string&</code></a>
<br />unit of measurement for this channel [|unit used in state reading.] </li> <br />unit of measurement used in state reading (default "cts", set to "none" for empty).</li>
<li><a name="owcount_crate"><code>attr &lt;name&gt; &lt;channel&gt;Rate <li><a name="owcount_crate"><code>attr &lt;name&gt; &lt;channel&gt;Rate
&lt;string&gt;[|&lt;string&gt;]</code></a> &lt;string&gt;[|&lt;string&gt;]</code></a>
<br />name for the channel rate [|name used in state reading]</li> <br />name for the channel rate [|short name used in state reading]</li>
<li><a name="owcount_coffset"><code>attr &lt;name&gt; &lt;channel&gt;Offset <li><a name="owcount_coffset"><code>attr &lt;name&gt; &lt;channel&gt;Offset
&lt;float&gt;</code></a> &lt;float&gt;</code></a>
<br />offset added to the reading in this channel. </li> <br />offset added to the reading in this channel. </li>
@ -2157,12 +2222,7 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
<li><a name="owcount_cperiod"><code>attr &lt;name&gt; &lt;channel&gt;Period hour(default) | minute | <li><a name="owcount_cperiod"><code>attr &lt;name&gt; &lt;channel&gt;Period hour(default) | minute |
second</code></a> second</code></a>
<br />period for rate calculation </li> <br />period for rate calculation </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a
href="#stateFormat">stateFormat</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#verbose">verbose</a>,
<a href="#webCmd">webCmd</a></li>
</ul> </ul>
=end html =end html

View File

@ -66,9 +66,9 @@ BEGIN {
use GPUtils qw(:all); use GPUtils qw(:all);
use ProtoThreads; use ProtoThreads;
no warnings 'deprecated'; no warnings 'deprecated';
sub Log($$); sub Log3($$$);
my $owx_version="5.15"; my $owx_version="6.0beta6";
#-- declare variables #-- declare variables
my %gets = ( my %gets = (
"present" => "", "present" => "",
@ -107,8 +107,7 @@ sub OWID_Initialize ($) {
$hash->{AttrFn} = "OWID_Attr"; $hash->{AttrFn} = "OWID_Attr";
$hash->{NotifyFn} = "OWID_Notify"; $hash->{NotifyFn} = "OWID_Notify";
$hash->{InitFn} = "OWID_Init"; $hash->{InitFn} = "OWID_Init";
$hash->{AttrList} = "IODev do_not_notify:0,1 showtime:0,1 model loglevel:0,1,2,3,4,5 ". $hash->{AttrList} = "IODev do_not_notify:0,1 showtime:0,1 model interval".
"interval ".
$readingFnAttributes; $readingFnAttributes;
#--make sure OWX is loaded so OWX_CRC is available if running with OWServer #--make sure OWX is loaded so OWX_CRC is available if running with OWServer
@ -212,7 +211,7 @@ sub OWID_Define ($$) {
$modules{OWID}{defptr}{$id} = $hash; $modules{OWID}{defptr}{$id} = $hash;
#-- #--
readingsSingleUpdate($hash,"state","Defined",1); readingsSingleUpdate($hash,"state","Defined",1);
Log 3, "OWID: Device $name defined."; Log3 $name,1, "OWID: Device $name defined.";
$hash->{NOTIFYDEV} = "global"; $hash->{NOTIFYDEV} = "global";
@ -240,7 +239,7 @@ sub OWID_Notify ($$) {
######################################################################################### #########################################################################################
# #
# OWID_Define - Implements InitFn function # OWID_Init - Implements InitFn function
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# #
@ -531,6 +530,10 @@ sub OWID_Undef ($) {
</a> </a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li> <br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
</ul> </ul>
<h4>Attributes</h4>
<ul>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
=end html =end html
=cut =cut

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@
# get <name> reading => measurement value obtained from VFunction # get <name> reading => measurement value obtained from VFunction
# get <name> temperature => temperature measurement # get <name> temperature => temperature measurement
# get <name> VDD => supply voltage measurement # get <name> VDD => supply voltage measurement
# get <name> V|raw => raw external voltage measurement # get <name> V|I|raw => external voltage/external current/raw measurement
# get <name> version => OWX version number # get <name> version => OWX version number
# #
# set <name> interval => set period for measurement # set <name> interval => set period for measurement
@ -38,12 +38,17 @@
# #
# attr <name> tempOffset <float> = temperature offset in degree Celsius added to the raw temperature reading # 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, default is Celsius # attr <name> tempUnit <string> = unit of measurement, e.g. Celsius/Kelvin/Fahrenheit, default is Celsius
# attr <name> VName <string>[|<string>] = name for the channel [|name used in state reading] # attr <name> VName <string>[|<string>] = name for the voltage channel [|short name used in state reading]
# attr <name> VUnit <string>[|<string>] = unit of measurement for the channel [|unit used in state reading] # attr <name> VUnit <string> = unit of measurement for the voltage channel (default V, none for empty)
# attr <name> Vfunction <string> = arbitrary functional expression involving the values VDD, V, T # attr <name> Vfunction <string> = arbitrary functional expression involving the values VDD, V, W, T
# VDD is replaced by the measured supply voltage in Volt, # VDD is replaced by the measured supply voltage in Volt,
# V by the measured external voltage (the channel) # V by the measured external voltage channel
# W by the measured external sense channel
# T by the measured and corrected temperature in its unit # T by the measured and corrected temperature in its unit
# attr <name> WName <string>[|<string>] = name for the sense channel [|short name used in state reading]
# attr <name> WUnit <string>[|<string>] = unit of measurement for the sense channel (default 1/16384 V, none for empty)
# attr <name> Wfunction <string> = arbitrary functional expression involving the values VDD, V, W, T
#
# #
######################################################################################## ########################################################################################
# #
@ -82,9 +87,9 @@ no warnings 'deprecated';
sub Log($$); sub Log($$);
my $owx_version="5.23"; my $owx_version="6.0";
#-- flexible channel name #-- flexible channel name
my $owg_channel; my ($owg_channel,$owg_schannel);
my %gets = ( my %gets = (
"id" => "", "id" => "",
@ -112,17 +117,14 @@ my %updates = (
# #
# Prefix = OWMULTI # Prefix = OWMULTI
# #
## ########################################################################################
# Parameters:
# hash - hash of device addressed
# #
# Called By: # OWMULTI_Initialize
# FHEM - Main Loop
# Gargelmargel - dunno where
# #
#Calling: # Parameter hash = hash of device addressed
# None #
## ########################################################################################
sub OWMULTI_Initialize ($) { sub OWMULTI_Initialize ($) {
my ($hash) = @_; my ($hash) = @_;
@ -136,16 +138,17 @@ sub OWMULTI_Initialize ($) {
#tempOffset = a temperature offset added to the temperature reading for correction #tempOffset = a temperature offset added to the temperature reading for correction
#tempUnit = a unit of measure: C/F/K #tempUnit = a unit of measure: C/F/K
$hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 model:DS2438 loglevel:0,1,2,3,4,5 ". $hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 model:DS2438 verbose:0,1,2,3,4,5 ".
"tempOffset tempUnit:Celsius,Fahrenheit,Kelvin ". "tempOffset tempUnit:Celsius,Fahrenheit,Kelvin ".
"VName VUnit VFunction ". "VName VUnit VFunction WName WUnit WFunction ".
"interval ". "interval ".
$readingFnAttributes; $readingFnAttributes;
#-- temperature and voltage globals - always the raw values from the device #-- temperature and voltage globals - always the raw values from the device
$hash->{owg_val}->[0] = undef; $hash->{owg_val}->[0] = undef;
$hash->{owg_val}->[2] = undef;
$hash->{owg_val}->[1] = undef; $hash->{owg_val}->[1] = undef;
$hash->{owg_val}->[2] = undef;
$hash->{owg_val}->[3] = undef;
#-- make sure OWX is loaded so OWX_CRC is available if running with OWServer #-- make sure OWX is loaded so OWX_CRC is available if running with OWServer
main::LoadModule("OWX"); main::LoadModule("OWX");
@ -336,29 +339,48 @@ sub OWMULTI_ChannelNames($) {
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $state = $hash->{READINGS}{"state"}{VAL}; my $state = $hash->{READINGS}{"state"}{VAL};
my ($cname,@cnama,$unit,@unarr); my ($cname,@cnama,$unit);
my ($tunit,$toffset,$tfactor,$tabbr,$vfunc); my ($tunit,$toffset,$tfactor,$tabbr,$vfunc,$wfunc);
#-- Set channel name, channel unit for voltage channel #-- Set channel name, channel unit for voltage channel
$cname = defined($attr{$name}{"VName"}) ? $attr{$name}{"VName"} : "voltage"; $cname = defined($attr{$name}{"VName"}) ? $attr{$name}{"VName"} : "voltage|vad";
@cnama = split(/\|/,$cname); @cnama = split(/\|/,$cname);
if( int(@cnama)!=2){ if( int(@cnama)!=2){
push(@cnama,$cnama[0]); push(@cnama,$cnama[0]);
} }
#-- unit #-- unit
$unit = defined($attr{$name}{"VUnit"}) ? $attr{$name}{"VUnit"} : "Volt|V"; $unit = defined($attr{$name}{"VUnit"}) ? $attr{$name}{"VUnit"} : "V";
@unarr= split(/\|/,$unit); $unit = ""
if( int(@unarr)!=2 ){ if($unit eq "none");
push(@unarr,$unarr[0]);
}
#-- put into readings #-- put into readings
$owg_channel = $cnama[0]; $owg_channel = $cnama[0];
$hash->{READINGS}{$owg_channel}{VAL} = " "; $hash->{READINGS}{$owg_channel}{VAL} = " ";
$hash->{READINGS}{$owg_channel}{ABBR} = $cnama[1]; $hash->{READINGS}{$owg_channel}{ABBR} = $cnama[1];
$hash->{READINGS}{$owg_channel}{UNIT} = $unarr[0]; $hash->{READINGS}{$owg_channel}{UNIT} = " ".$unit;
$hash->{READINGS}{$owg_channel}{UNITABBR} = $unarr[1];
#-- Set channel name, channel unit for sense channel
$cname = defined($attr{$name}{"WName"}) ? $attr{$name}{"WName"} : "sense|s";
@cnama = split(/\|/,$cname);
if( int(@cnama)!=2){
push(@cnama,$cnama[0]);
}
#-- unit
$unit = defined($attr{$name}{"WUnit"}) ? $attr{$name}{"WUnit"} : "V";
if($unit eq "none"){
$unit = ""
}else{
$unit = " ".$unit
}
#-- put into readings
$owg_schannel = $cnama[0];
$hash->{READINGS}{$owg_schannel}{VAL} = " ";
$hash->{READINGS}{$owg_schannel}{ABBR} = $cnama[1];
$hash->{READINGS}{$owg_schannel}{UNIT} = $unit;
#-- temperature scale #-- temperature scale
$hash->{READINGS}{"temperature"}{UNIT} = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : "Celsius"; $hash->{READINGS}{"temperature"}{UNIT} = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : "Celsius";
@ -366,13 +388,15 @@ sub OWMULTI_ChannelNames($) {
$toffset = defined($attr{$name}{"tempOffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ; $toffset = defined($attr{$name}{"tempOffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ;
$tfactor = 1.0; $tfactor = 1.0;
if( $tunit eq "Celsius" ){ if( $tunit eq "none" ){
$tabbr = "°C"; $tabbr = "";
}elsif( $tunit eq "Celsius" ){
$tabbr = " °C";
} elsif ($tunit eq "Kelvin" ){ } elsif ($tunit eq "Kelvin" ){
$tabbr = "K"; $tabbr = " K";
$toffset += "273.16" $toffset += "273.16"
} elsif ($tunit eq "Fahrenheit" ){ } elsif ($tunit eq "Fahrenheit" ){
$tabbr = "°F"; $tabbr = " °F";
$toffset = ($toffset+32)/1.8; $toffset = ($toffset+32)/1.8;
$tfactor = 1.8; $tfactor = 1.8;
} else { } else {
@ -382,8 +406,7 @@ sub OWMULTI_ChannelNames($) {
#-- these values are rather complex to obtain, therefore save them in the hash #-- these values are rather complex to obtain, therefore save them in the hash
$hash->{READINGS}{"temperature"}{ABBR} = "T"; $hash->{READINGS}{"temperature"}{ABBR} = "T";
$hash->{READINGS}{"temperature"}{UNIT} = $tunit; $hash->{READINGS}{"temperature"}{UNIT} = $tabbr;
$hash->{READINGS}{"temperature"}{UNITABBR} = $tabbr;
$hash->{tempf}{offset} = $toffset; $hash->{tempf}{offset} = $toffset;
$hash->{tempf}{factor} = $tfactor; $hash->{tempf}{factor} = $tfactor;
} }
@ -400,11 +423,11 @@ sub OWMULTI_FormatValues($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my ($toffset,$tfactor,$tval,$vfunc,$vval); my ($toffset,$tfactor,$tval,$vfunc,$wfunc,$vval,$wval);
my $svalue = ""; my $svalue = "";
#-- no change in any value if invalid reading #-- no change in any value if invalid reading
return if( ($hash->{owg_val}->[0] eq "") || ($hash->{owg_val}->[1] eq "") || ($hash->{owg_val}->[2] eq "") ); return if( ($hash->{owg_val}->[0] eq "") || ($hash->{owg_val}->[1] eq "") || ($hash->{owg_val}->[2] eq "") || ($hash->{owg_val}->[3] eq ""));
#-- obtain channel names #-- obtain channel names
OWMULTI_ChannelNames($hash); OWMULTI_ChannelNames($hash);
@ -414,35 +437,53 @@ sub OWMULTI_FormatValues($) {
$tfactor = $hash->{tempf}{factor}; $tfactor = $hash->{tempf}{factor};
$tval = int(10*($hash->{owg_val}->[0] + $toffset)*$tfactor+0.5)/10; $tval = int(10*($hash->{owg_val}->[0] + $toffset)*$tfactor+0.5)/10;
#-- attribute VFunction defined ? #-- attribute V/WFunction defined ?
$vfunc = defined($attr{$name}{"VFunction"}) ? $attr{$name}{"VFunction"} : "V"; $vfunc = defined($attr{$name}{"VFunction"}) ? $attr{$name}{"VFunction"} : "V";
$wfunc = defined($attr{$name}{"WFunction"}) ? $attr{$name}{"WFunction"} : "W";
#-- replace by proper values #-- replace by proper values
$vfunc =~ s/VDD/\$hash->{owg_val}->[1]/g; $vfunc =~ s/VDD/\$hash->{owg_val}->[1]/g;
$vfunc =~ s/V/\$hash->{owg_val}->[2]/g; $vfunc =~ s/V/\$hash->{owg_val}->[2]/g;
$vfunc =~ s/W/\$hash->{owg_val}->[3]/g;
$vfunc =~ s/T/\$tval/g; $vfunc =~ s/T/\$tval/g;
$wfunc =~ s/VDD/\$hash->{owg_val}->[1]/g;
$wfunc =~ s/V/\$hash->{owg_val}->[2]/g;
$wfunc =~ s/W/\$hash->{owg_val}->[3]/g;
$wfunc =~ s/T/\$tval/g;
#-- determine the measured value from the function #-- determine the measured value from the function
$vfunc = "\$hash->{owg_val}->[1] = $hash->{owg_val}->[1]; \$hash->{owg_val}->[2] = $hash->{owg_val}->[2]; \$tval = $tval; ".$vfunc; $vfunc = "\$hash->{owg_val}->[1] = $hash->{owg_val}->[1]; \$hash->{owg_val}->[2] = $hash->{owg_val}->[2]; \$hash->{owg_val}->[3] = $hash->{owg_val}->[3]; \$tval = $tval; ".$vfunc;
#Log 1, "vfunc= ".$vfunc; #Log 1, "vfunc= ".$vfunc;
$vfunc = eval($vfunc); $vfunc = eval($vfunc);
if( !$vfunc ){ if( !$vfunc ){
$vval = ""; $vval = 0.0;
} elsif( $vfunc ne "" ){ } elsif( $vfunc ne "" ){
$vval = int( $vfunc*10+0.5)/10; $vval = int( $vfunc*100+0.5)/100;
} else { } else {
#-- todo ? $vval = "???";
}
$wfunc = "\$hash->{owg_val}->[1] = $hash->{owg_val}->[1]; \$hash->{owg_val}->[2] = $hash->{owg_val}->[2]; \$hash->{owg_val}->[3] = $hash->{owg_val}->[3]; \$tval = $tval; ".$wfunc;
#Log 1, "wfunc= ".$wfunc;
$wfunc = eval($wfunc);
if( !$wfunc ){
$wval = 0.0;
} elsif( $wfunc ne "" ){
$wval = int( $wfunc*100+0.5)/100;
} else {
$wval = "???";
} }
#-- string buildup for return value, STATE #-- string buildup for return value, STATE
$svalue .= sprintf( "%s: %5.1f %s (T: %5.1f %s)", $svalue .= sprintf( "%s: %5.2f%s (T: %5.1f%s %s: %5.2f%s)",
$hash->{READINGS}{$owg_channel}{ABBR}, $vval,$hash->{READINGS}{$owg_channel}{UNITABBR}, $hash->{READINGS}{$owg_channel}{ABBR}, $vval,$hash->{READINGS}{$owg_channel}{UNIT},
$tval,$hash->{READINGS}{"temperature"}{UNITABBR}); $tval,$hash->{READINGS}{"temperature"}{UNIT}, $hash->{READINGS}{$owg_schannel}{ABBR}, $wval,$hash->{READINGS}{$owg_schannel}{UNIT});
#-- put into READINGS #-- put into READINGS
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
readingsBulkUpdate($hash,$owg_channel,$vval); readingsBulkUpdate($hash,$owg_channel,$vval);
readingsBulkUpdate($hash,"VDD",sprintf("%4.2f %s",$hash->{owg_val}->[1],"V")); readingsBulkUpdate($hash,$owg_schannel,$wval);
readingsBulkUpdate($hash,"VDD",sprintf("%4.2f",$hash->{owg_val}->[1]));
readingsBulkUpdate($hash,"temperature",$tval); readingsBulkUpdate($hash,"temperature",$tval);
#-- STATE #-- STATE
@ -466,6 +507,7 @@ sub OWMULTI_Get($@) {
my $reading = $a[1]; my $reading = $a[1];
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL}; my $model = $hash->{OW_MODEL};
my $value = undef; my $value = undef;
my $ret = ""; my $ret = "";
@ -538,7 +580,10 @@ sub OWMULTI_Get($@) {
return "OWMULTI: Get with wrong IODev type $interface"; return "OWMULTI: Get with wrong IODev type $interface";
} }
#-- process results #-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWSMULTI: $name getting readings, please wait for completion";
}else{
if( defined($ret) ){ if( defined($ret) ){
return "OWMULTI: Could not get values from device $name, reason $ret"; return "OWMULTI: Could not get values from device $name, reason $ret";
} }
@ -558,7 +603,8 @@ sub OWMULTI_Get($@) {
} }
if ( $reading eq "raw") { if ( $reading eq "raw") {
return "OWMULTI: $name.raw => ". return "OWMULTI: $name.raw => ".
$hash->{owg_val}->[2]; $hash->{owg_val}->[2]." V ".$hash->{owg_val}->[3]." V";
}
} }
return undef; return undef;
} }
@ -630,8 +676,9 @@ sub OWMULTI_InitializeDevice($) {
#-- Initial readings #-- Initial readings
$hash->{owg_val}->[0] = ""; $hash->{owg_val}->[0] = "";
$hash->{owg_val}->[2] = "";
$hash->{owg_val}->[1] = ""; $hash->{owg_val}->[1] = "";
$hash->{owg_val}->[2] = "";
$hash->{owg_val}->[3] = "";
#-- Set state to initialized #-- Set state to initialized
readingsSingleUpdate($hash,"state","initialized",1); readingsSingleUpdate($hash,"state","initialized",1);
@ -766,16 +813,16 @@ sub OWFSMULTI_GetValues($) {
$hash->{owg_val}->[0] = OWServer_Read($master,"/$owx_add/temperature"); $hash->{owg_val}->[0] = OWServer_Read($master,"/$owx_add/temperature");
$hash->{owg_val}->[1] = OWServer_Read($master,"/$owx_add/VDD"); $hash->{owg_val}->[1] = OWServer_Read($master,"/$owx_add/VDD");
$hash->{owg_val}->[2] = OWServer_Read($master,"/$owx_add/VAD"); $hash->{owg_val}->[2] = OWServer_Read($master,"/$owx_add/VAD");
$hash->{owg_val}->[3] = OWServer_Read($master,"/$owx_add/vis");
return "no return from OWServer" return "no return from OWServer"
if( (!defined($hash->{owg_val}->[0])) || (!defined($hash->{owg_val}->[1])) || (!defined($hash->{owg_val}->[2])) ); if( (!defined($hash->{owg_val}->[0])) || (!defined($hash->{owg_val}->[1])) || (!defined($hash->{owg_val}->[2])) || (!defined($hash->{owg_val}->[3])) );
return "empty return from OWServer" return "empty return from OWServer"
if( ($hash->{owg_val}->[0] eq "") || ($hash->{owg_val}->[1] eq "") || ($hash->{owg_val}->[2] eq "") ); if( ($hash->{owg_val}->[0] eq "") || ($hash->{owg_val}->[1] eq "") || ($hash->{owg_val}->[2] eq "") || ($hash->{owg_val}->[3] eq "") );
#-- and now from raw to formatted values #-- and now from raw to formatted values
$hash->{PRESENT} = 1; $hash->{PRESENT} = 1;
my $value = OWMULTI_FormatValues($hash); my $value = OWMULTI_FormatValues($hash);
Log 5, $value;
return undef; return undef;
} }
@ -802,40 +849,65 @@ sub OWFSMULTI_SetValues($@) {
# #
######################################################################################## ########################################################################################
# #
# OWXMULTI_BinValues - Binary readings into clear values # OWXMULTI_BinValues - Process reading from one device - translate binary into raw
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# context = mode for evaluating the binary data
# proc = processing instruction, also passed to OWX_Read.
# bitwise interpretation !!
# if 0, nothing special
# if 1 = bit 0, a reset will be performed not only before, but also after
# the last operation in OWX_Read
# if 2 = bit 1, the initial reset of the bus will be suppressed
# if 8 = bit 3, the fillup of the data with 0xff will be suppressed
# if 16= bit 4, the insertion will be at the top of the queue
# owx_dev = ROM ID of slave device
# crcpart = part of the data that needs to be part of the CRC check
# numread = number of bytes to receive
# res = result string
#
# #
######################################################################################## ########################################################################################
sub OWXMULTI_BinValues($$$$$$$$) { sub OWXMULTI_BinValues($$$$$$$) {
my ($hash, $context, $success, $reset, $owx_dev, $command, $numread, $res) = @_; my ($hash, $context, $proc, $owx_dev, $crcpart, $numread, $res) = @_;
#-- hash of the busmaster
my $master = $hash->{IODev};
my $name = $hash->{NAME};
my @data=[];
my ($value,$lsb,$msb,$sign);
my $msg;
OWX_WDBG($name,"OWXMULTI_BinValues called for device $name in context $context with ",$res)
if( $main::owx_debug>2 );
#-- always check for success, unused are reset, numread #-- always check for success, unused are reset, numread
return unless ($success and $context =~ /^ds2438.getv[ad]d$/); return unless ($context =~ /^ds2438.getv[ad]d$/);
#Log 1,"OWXMULTI_BinValues context = $context"; #Log 1,"OWXMULTI_BinValues context = $context";
#-- process results #-- process results
my @data=split(//,$res); @data=split(//,$res);
if (@data != 9) { if (@data != 9) {
return "invalid data length, ".int(@data)." instead of 9 bytes"; $msg="$name returns invalid data length, ".int(@data)." instead of 9 bytes";
} }elsif ((ord($data[0]) & 112)!=0) {
if ((ord($data[0]) & 112)!=0) { $msg="$name: conversion not complete or data invalid";
return "conversion not complete or data invalid"; }elsif (OWX_CRC8(substr($res,0,8),$data[8])==0) {
} $msg="$name returns invalid CRC";
if (OWX_CRC8(substr($res,0,8),$data[8])==0) { }else{
return "invalid CRC"; $msg="No error";
} }
OWX_WDBG($name,"OWXMULTI_BinValues: ".$msg,"")
if( $main::owx_debug>2 );
#-- this must be different for the different device types #-- this must be different for the different device types
# family = 26 => DS2438 # family = 26 => DS2438
#-- transform binary rep of VDD #-- transform binary rep of VDD
if( $context eq "ds2438.getvdd") { if( $context eq "ds2438.getvdd") {
#-- temperature #-- temperature
my $lsb = ord($data[1]); $lsb = ord($data[1]);
my $msb = ord($data[2]) & 127; $msb = ord($data[2]) & 127;
my $sign = ord($data[2]) & 128; $sign = ord($data[2]) & 128;
#-- test with -55 degrees #-- test with -55 degrees
#$lsb = 0; #$lsb = 0;
@ -843,7 +915,7 @@ sub OWXMULTI_BinValues($$$$$$$$) {
#$msb = 73; #$msb = 73;
#-- 2's complement form = signed bytes #-- 2's complement form = signed bytes
$hash->{owg_val}->[0] = $msb+ $lsb/256; $hash->{owg_val}->[0] = $msb+ $lsb/256.;
if( $sign !=0 ){ if( $sign !=0 ){
$hash->{owg_val}->[0] = -128+$hash->{owg_val}->[0]; $hash->{owg_val}->[0] = -128+$hash->{owg_val}->[0];
} }
@ -857,25 +929,31 @@ sub OWXMULTI_BinValues($$$$$$$$) {
#$msb = 1; #$msb = 1;
#-- supply voltage #-- supply voltage
$hash->{owg_val}->[1] = ($msb*256+ $lsb)/100; $hash->{owg_val}->[1] = ($msb*256+ $lsb)/100.;
};
#-- transform binary rep of VAD #-- transform binary rep of VAD
if( $context eq "ds2438.getvad") { }elsif( $context eq "ds2438.getvad") {
#-- voltage #-- voltage
my $lsb = ord($data[3]); $lsb = ord($data[3]);
my $msb = ord($data[4]) & 3; $msb = ord($data[4]) & 3;
#-- test with 7.2 V #-- test with 7.2 V
#$lsb = 208; #$lsb = 208;
#$msb = 2; #$msb = 2;
#-- external voltage #-- external voltage
$hash->{owg_val}->[2] = ($msb*256+ $lsb)/100; $hash->{owg_val}->[2] = ($msb*256+ $lsb)/100.;
#-- current
$lsb = ord($data[5]);
$msb = ord($data[6]) & 3;
#-- external current
$hash->{owg_val}->[3] = ($msb*256.+ $lsb)/4096;
#-- and now from raw to formatted values #-- and now from raw to formatted values
$hash->{PRESENT} = 1; $hash->{PRESENT} = 1;
my $value = OWMULTI_FormatValues($hash); my $value = OWMULTI_FormatValues($hash);
Log 5, $value;
}; };
return undef; return undef;
} }
@ -893,7 +971,7 @@ sub OWXMULTI_GetValues($) {
my ($hash) = @_; my ($hash) = @_;
my ($i,$j,$k,$res,$ret); my ($res,$ret);
#-- ID of the device #-- ID of the device
my $owx_dev = $hash->{ROM_ID}; my $owx_dev = $hash->{ROM_ID};
@ -905,8 +983,11 @@ sub OWXMULTI_GetValues($) {
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
#-- switch the device to current measurement off, VDD only #-- switch the device to current measurement off, VDD only
#-- issue the match ROM command \x55 and the write scratchpad command #-- issue the match ROM command \x55 and the write scratchpad command
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
if( OWX_Complex($master,$owx_dev,"\x4E\x00\x08",0) eq 0 ){ #if( OWX_Complex($master,$owx_dev,"\x4E\x00\x08",0) eq 0 ){
if( OWX_Complex($master,$owx_dev,"\x4E\x00\x09",0) eq 0 ){
return "$owx_dev write status failed"; return "$owx_dev write status failed";
} }
@ -930,7 +1011,7 @@ sub OWXMULTI_GetValues($) {
#-- conversion needs some 6 ms ! #-- conversion needs some 6 ms !
#-- issue the match ROM command \x55 and the start conversion command #-- issue the match ROM command \x55 and the start conversion command
OWX_Reset($master); OWX_Reset($master);
if( OWX_Complex($master,$owx_dev,"\xB4",0) eq 0 ){ if( OWX_Complex($master,$owx_dev,"\xB4",0.01) eq 0 ){
return "$owx_dev voltage conversion failed"; return "$owx_dev voltage conversion failed";
} }
select(undef,undef,undef,0.006); select(undef,undef,undef,0.006);
@ -939,7 +1020,7 @@ sub OWXMULTI_GetValues($) {
#-- copy needs some 12 ms ! #-- copy needs some 12 ms !
#-- issue the match ROM command \x55 and the recall memory command #-- issue the match ROM command \x55 and the recall memory command
OWX_Reset($master); OWX_Reset($master);
if( OWX_Complex($master,$owx_dev,"\xB8\x00",0) eq 0 ){ if( OWX_Complex($master,$owx_dev,"\xB8\x00",0.02) eq 0 ){
return "$owx_dev recall memory failed"; return "$owx_dev recall memory failed";
} }
select(undef,undef,undef,0.012); select(undef,undef,undef,0.012);
@ -953,13 +1034,14 @@ sub OWXMULTI_GetValues($) {
if( $res eq 0 ); if( $res eq 0 );
return "$owx_dev has returned invalid data" return "$owx_dev has returned invalid data"
if( length($res)!=20); if( length($res)!=20);
$ret = OWXMULTI_BinValues($hash,"ds2438.getvdd",1,undef,$owx_dev,undef,undef,substr($res,11)); $ret = OWXMULTI_BinValues($hash,"ds2438.getvdd",undef,$owx_dev,undef,undef,substr($res,11));
return $ret if (defined $ret); return $ret if (defined $ret);
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
#-- switch the device to current measurement off, V external only #-- switch the device to current measurement off, V external only
#-- issue the match ROM command \x55 and the write scratchpad command #-- issue the match ROM command \x55 and the write scratchpad command
OWX_Reset($master); OWX_Reset($master);
if( OWX_Complex($master,$owx_dev,"\x4E\x00\x00",0) eq 0 ){ #if( OWX_Complex($master,$owx_dev,"\x4E\x00\x00",0) eq 0 ){
if( OWX_Complex($master,$owx_dev,"\x4E\x00\x01",0) eq 0 ){
return "$owx_dev write status failed"; return "$owx_dev write status failed";
} }
#-- copy scratchpad to register #-- copy scratchpad to register
@ -972,7 +1054,7 @@ sub OWXMULTI_GetValues($) {
#-- conversion needs some 6 ms ! #-- conversion needs some 6 ms !
#-- issue the match ROM command \x55 and the start conversion command #-- issue the match ROM command \x55 and the start conversion command
OWX_Reset($master); OWX_Reset($master);
if( OWX_Complex($master,$owx_dev,"\xB4",0) eq 0 ){ if( OWX_Complex($master,$owx_dev,"\xB4",0.01) eq 0 ){
return "$owx_dev voltage conversion failed"; return "$owx_dev voltage conversion failed";
} }
select(undef,undef,undef,0.006); select(undef,undef,undef,0.006);
@ -981,7 +1063,7 @@ sub OWXMULTI_GetValues($) {
#-- copy needs some 12 ms ! #-- copy needs some 12 ms !
#-- issue the match ROM command \x55 and the recall memory command #-- issue the match ROM command \x55 and the recall memory command
OWX_Reset($master); OWX_Reset($master);
if( OWX_Complex($master,$owx_dev,"\xB8\x00",0) eq 0 ){ if( OWX_Complex($master,$owx_dev,"\xB8\x00",0.02) eq 0 ){
return "$owx_dev recall memory failed"; return "$owx_dev recall memory failed";
} }
select(undef,undef,undef,0.012); select(undef,undef,undef,0.012);
@ -997,9 +1079,85 @@ sub OWXMULTI_GetValues($) {
if( $res eq 0 ); if( $res eq 0 );
return "$owx_dev has returned invalid data" return "$owx_dev has returned invalid data"
if( length($res)!=20); if( length($res)!=20);
return OWXMULTI_BinValues($hash,$context,1,undef,$owx_dev,undef,undef,substr($res,11)); return OWXMULTI_BinValues($hash,$context,undef,$owx_dev,undef,undef,substr($res,11));
} #-- NEW OWX interface
}else{
#-- switch the device to current measurement off, VDD only
#-- issue the match ROM command \x55 and the write scratchpad command
#### master slave context proc owx_dev data crcpart numread startread callback delay
#OWX_Qomplex($master, $hash, "write SP", 0, $owx_dev, "\x4E\x00\x08", 0, 0, 0, undef, 0);
#-- switch the device to current measurement on, VDD only
#-- issue the match ROM command \x55 and the write scratchpad command
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "write SP", 0, $owx_dev, "\x4E\x00\x09", 0, 0, 0, undef, 0);
#-- copy scratchpad to register
#-- issue the match ROM command \x55 and the copy scratchpad command
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "copy SP", 0, $owx_dev, "\x48\x00", 0, 0, 0, undef, 0);
#-- initiate temperature conversion
#-- conversion needs some 12 ms !
#-- issue the match ROM command \x55 and the start conversion command
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "T conversion", 0, $owx_dev, "\x44", 0, 0, 0, undef, 0);
#-- initiate voltage conversion
#-- conversion needs some 6 ms !
#-- issue the match ROM command \x55 and the start conversion command
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "V conversion", 0, $owx_dev, "\xB4", 0, 0, 0, undef, 0);
#-- from memory to scratchpad
#-- copy needs some 12 ms !
#-- issue the match ROM command \x55 and the recall memory command
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "recall", 0, $owx_dev, "\xB8\x00", 0, 0, 0, undef, 0);
#-- NOW ask the specific device
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
#-- reading 9 + 2 + 9 data bytes = 20 bytes
#### master slave context proc owx_dev data crcpart numread startread callback delay
# 1 provides additional reset after last operattion
OWX_Qomplex($master, $hash, "ds2438.getvdd", 1, $owx_dev, "\xBE\x00\x08", 0, 9, 11, \&OWXMULTI_BinValues, 0);
#-- switch the device to current measurement off, V external only
#-- issue the match ROM command \x55 and the write scratchpad command
#### master slave context proc owx_dev data crcpart numread startread callback delay
#OWX_Qomplex($master, $hash, "write SP", 0, $owx_dev, "\x4E\x00\x00", 0, 0, 0, undef, 0);
#-- switch the device to current measurement on, V external only
#-- issue the match ROM command \x55 and the write scratchpad command
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "write SP", 0, $owx_dev, "\x4E\x00\x01", 0, 0, 0, undef, 0);
#-- copy scratchpad to register
#-- issue the match ROM command \x55 and the copy scratchpad command
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "copy SP", 0, $owx_dev, "\x48\x00", 0, 0, 0, undef, 0);
#-- initiate voltage conversion
#-- conversion needs some 6 ms !
#-- issue the match ROM command \x55 and the start conversion command
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "V conversion", 0, $owx_dev, "\xB4", 0, 0, 0, undef, 0);
#-- from memory to scratchpad
#-- copy needs some 12 ms !
#-- issue the match ROM command \x55 and the recall memory command
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "recall", 0, $owx_dev, "\xB8\x00", 0, 0, 0, undef, 0);
#-- NOW ask the specific device
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
#-- reading 9 + 2 + 9 data bytes = 20 bytes
#### master slave context proc owx_dev data crcpart numread startread callback delay
# 1 provides additional reset after last operattion
OWX_Qomplex($master, $hash, "ds2438.getvad", 1, $owx_dev, "\xBE\x00", 0, 20, 11, \&OWXMULTI_BinValues, 0);
return undef;
}
}
####################################################################################### #######################################################################################
# #
# OWXMULTI_SetValues - Set values in device # OWXMULTI_SetValues - Set values in device
@ -1126,7 +1284,7 @@ sub OWXMULTI_PT_GetValues($) {
unless (defined $res and length($res)==9) { unless (defined $res and length($res)==9) {
PT_EXIT("$owx_dev has returned invalid data"); PT_EXIT("$owx_dev has returned invalid data");
} }
$ret = OWXMULTI_BinValues($hash,"ds2438.getvdd",1,undef,$owx_dev,undef,undef,$res); $ret = OWXMULTI_BinValues($hash,"ds2438.getvdd",undef,$owx_dev,undef,undef,$res);
if ($ret) { if ($ret) {
die $ret; die $ret;
} }
@ -1180,7 +1338,7 @@ sub OWXMULTI_PT_GetValues($) {
unless (defined $res and length($res)==9) { unless (defined $res and length($res)==9) {
PT_EXIT("$owx_dev has returned invalid data"); PT_EXIT("$owx_dev has returned invalid data");
} }
$ret = OWXMULTI_BinValues($hash,"ds2438.getvad",1,undef,$owx_dev,undef,undef,$res); $ret = OWXMULTI_BinValues($hash,"ds2438.getvad",undef,$owx_dev,undef,undef,$res);
if ($ret) { if ($ret) {
die $ret; die $ret;
} }
@ -1250,9 +1408,9 @@ sub OWXMULTI_PT_SetValues($@) {
<p> <p>
<code>define OWX_M OWMULTI 7C5034010000 45</code> <code>define OWX_M OWMULTI 7C5034010000 45</code>
<br /> <br />
<code>attr OWX_M VName relHumidity|humidity</code> <code>attr OWX_M VName humidity|rH</code>
<br /> <br />
<code>attr OWX_M VUnit percent|%</code> <code>attr OWX_M VUnit %</code>
<br /> <br />
<code>attr OWX_M VFunction (161.29 * V / VDD - 25.8065)/(1.0546 - 0.00216 * T)</code> <code>attr OWX_M VFunction (161.29 * V / VDD - 25.8065)/(1.0546 - 0.00216 * T)</code>
</p> </p>
@ -1305,34 +1463,43 @@ sub OWXMULTI_PT_SetValues($@) {
seconds. </li> seconds. </li>
<li><a name="owmulti_reading"> <li><a name="owmulti_reading">
<code>get &lt;name&gt; reading</code></a><br />Obtain the measurement values </li> <code>get &lt;name&gt; reading</code></a><br />Obtain the measurement values </li>
<li><a name="owmulti_vad">
<code>get &lt;name&gt; VAD</code></a><br />Obtain the measurement value from
VFunction. </li>
<li><a name="owmulti_temperature"> <li><a name="owmulti_temperature">
<code>get &lt;name&gt; temperature</code></a><br />Obtain the temperature value. </li> <code>get &lt;name&gt; temperature</code></a><br />Obtain the temperature value. </li>
<li><a name="owmulti_vdd"> <li><a name="owmulti_vdd">
<code>get &lt;name&gt; VDD</code></a><br />Obtain the current supply voltage. </li> <code>get &lt;name&gt; VDD</code></a><br />Obtain the current supply voltage. </li>
<li><a name="owmulti_raw"> <li><a name="owmulti_raw">
<code>get &lt;name&gt; V</code> or <code>get &lt;name&gt; <code>get &lt;name&gt; V</code> or <code>get &lt;name&gt;
raw</code></a><br />Obtain the raw external voltage measurement. </li> raw</code></a><br />Obtain the raw external voltage and external sense measurement. </li>
</ul> </ul>
<a name="OWMULTIattr"></a> <a name="OWMULTIattr"></a>
<h4>Attributes</h4> <h4>Attributes</h4>
<ul> <ul>
<li><a name="owmulti_vname"><code>attr &lt;name&gt; VName <li><a name="owmulti_vname"><code>attr &lt;name&gt; VName
&lt;string&gt;[|&lt;string&gt;]</code></a> &lt;string&gt;[|&lt;string&gt;]</code></a>
<br />name for the channel [|name used in state reading]. </li> <br />name for the voltage channel [|short name used in state reading]. </li>
<li><a name="owmulti_vunit"><code>attr &lt;name&gt; VUnit <li><a name="owmulti_vunit"><code>attr &lt;name&gt; VUnit
&lt;string&gt;[|&lt;string&gt;]</code></a> &lt;string&gt;</code></a>
<br />unit of measurement for this channel [|unit used in state reading]. </li> <br />unit of measurement for the voltage channel used in state reading (default "V", set to "none" for empty).</li>
<li><a name="owmulti_vfunction"><code>attr &lt;name&gt; VFunction <li><a name="owmulti_vfunction"><code>attr &lt;name&gt; VFunction
&lt;string&gt;</code></a> &lt;string&gt;</code></a>
<br />arbitrary functional expression involving the values VDD, V, T. Example see <br />arbitrary functional expression involving the values VDD, V, W and T. Example see
above. <ul> above. <ul>
<li>VDD is replaced by the measured supply voltage in Volt,</li> <li>VDD is replaced by the measured supply voltage in Volt,</li>
<li> V by the measured external voltage (the channel),</li> <li>V by the measured external voltage channel,</li>
<li>W by the measured external sense channel,</li>
<li>T by the measured and corrected temperature in its unit</li> <li>T by the measured and corrected temperature in its unit</li>
</ul></li> </ul></li>
<li><a name="owmulti_wname"><code>attr &lt;name&gt; WName
&lt;string&gt;[|&lt;string&gt;]</code></a>
<br />name for the sense channel [|short name used in state reading]. </li>
<li><a name="owmulti_wunit"><code>attr &lt;name&gt; WUnit
&lt;string&gt;</code></a>
<br />unit of measurement for the sense channel used in state reading (default “V", set to "none" for empty).</li>
<li><a name="owmulti_wfunction"><code>attr &lt;name&gt; WFunction
&lt;string&gt;</code></a>
<br />arbitrary functional expression involving the values VDD, V, W and T. Example and usage see
above.</li>
<li><a name="owmulti_tempOffset"><code>attr &lt;name&gt; tempOffset &lt;float&gt;</code> <li><a name="owmulti_tempOffset"><code>attr &lt;name&gt; tempOffset &lt;float&gt;</code>
</a> </a>
<br />temperature offset in &deg;C added to the raw temperature reading. </li> <br />temperature offset in &deg;C added to the raw temperature reading. </li>
@ -1340,12 +1507,7 @@ sub OWXMULTI_PT_SetValues($@) {
Celsius|Kelvin|Fahrenheit</code> Celsius|Kelvin|Fahrenheit</code>
</a> </a>
<br />unit of measurement (temperature scale), default is Celsius = &deg;C </li> <br />unit of measurement (temperature scale), default is Celsius = &deg;C </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a
href="#stateFormat">stateFormat</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
</ul> </ul>
=end html =end html

View File

@ -16,7 +16,7 @@
# where <name> may be replaced by any name string # where <name> may be replaced by any name string
# #
# <model> is a 1-Wire device type. If omitted, we assume this to be an # <model> is a 1-Wire device type. If omitted, we assume this to be an
# DS2413. Allowed values are DS2413, DS2406 # DS2413. Allowed values are DS2413, DS2406, DS2408
# <fam> is a 1-Wire family id, currently allowed values are 12, 29, 3A # <fam> is a 1-Wire family id, currently allowed values are 12, 29, 3A
# <ROM_ID> is a 12 character (6 byte) 1-Wire ROM ID # <ROM_ID> is a 12 character (6 byte) 1-Wire ROM ID
# without Family ID, e.g. A2D90D000800 # without Family ID, e.g. A2D90D000800
@ -45,10 +45,8 @@
# Additional attributes are defined in fhem.cfg, in some cases per channel, where <channel>=A,B # 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. # Note: attributes are read only during initialization procedure - later changes are not used.
# #
# attr <name> stateS <string> = character string denoting external shortening condition, default is (ext) # attr <name> stateS <string> = character string denoting external shortening condition, default is X
# overwritten by an attribute setting "red angled arrow downward" # attr <name> <channel>Name <string>|<string> = name for the channel [|short name used in state reading]
#
# attr <name> <channel>Name <string>|<string> = name for the channel [|name used in state reading]
# attr <name> <channel>Unit <string>|<string> = values to display in state variable for on|off condition # attr <name> <channel>Unit <string>|<string> = values to display in state variable for on|off condition
# #
######################################################################################## ########################################################################################
@ -89,7 +87,7 @@ no warnings 'deprecated';
sub Log($$); sub Log($$);
my $owx_version="5.24"; my $owx_version="6.0";
#-- fixed raw channel name, flexible channel name #-- fixed raw channel name, flexible channel name
my @owg_fixed = ("A","B","C","D","E","F","G","H"); my @owg_fixed = ("A","B","C","D","E","F","G","H");
my @owg_channel = ("A","B","C","D","E","F","G","H"); my @owg_channel = ("A","B","C","D","E","F","G","H");
@ -131,8 +129,6 @@ my %cnumber = (
# #
# OWSWITCH_Initialize # OWSWITCH_Initialize
# #
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed # Parameter: hash = hash of device addressed
# #
######################################################################################## ########################################################################################
@ -148,7 +144,7 @@ sub OWSWITCH_Initialize ($) {
$hash->{InitFn} = "OWSWITCH_Init"; $hash->{InitFn} = "OWSWITCH_Init";
$hash->{AttrFn} = "OWSWITCH_Attr"; $hash->{AttrFn} = "OWSWITCH_Attr";
my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2413,DS2406,DS2408 loglevel:0,1,2,3,4,5 ". my $attlist = "IODev do_not_notify:0,1 showtime:0,1 model:DS2413,DS2406,DS2408 ".
"stateS interval ". "stateS interval ".
$readingFnAttributes; $readingFnAttributes;
@ -172,8 +168,6 @@ sub OWSWITCH_Initialize ($) {
# #
# OWSWITCH_Define - Implements DefFn function # OWSWITCH_Define - Implements DefFn function
# #
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed, def = definition string # Parameter: hash = hash of device addressed, def = definition string
# #
######################################################################################### #########################################################################################
@ -280,8 +274,6 @@ sub OWSWITCH_Define ($$) {
# #
# OWSWITCH_Notify - Implements Notify function # OWSWITCH_Notify - Implements Notify function
# #
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed, def = definition string # Parameter: hash = hash of device addressed, def = definition string
# #
######################################################################################### #########################################################################################
@ -298,8 +290,6 @@ sub OWSWITCH_Notify ($$) {
# #
# OWSWITCH_Init - Implements Init function # OWSWITCH_Init - Implements Init function
# #
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed, def = definition string # Parameter: hash = hash of device addressed, def = definition string
# #
######################################################################################### #########################################################################################
@ -316,8 +306,6 @@ sub OWSWITCH_Init ($) {
# #
# OWSWITCH_Attr - Set one attribute value for device # OWSWITCH_Attr - Set one attribute value for device
# #
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed # Parameter: hash = hash of device addressed
# a = argument array # a = argument array
# #
@ -362,8 +350,6 @@ sub OWSWITCH_Attr(@) {
# #
# OWSWITCH_ChannelNames - find the real channel names # OWSWITCH_ChannelNames - find the real channel names
# #
# CalledBy: OWSWITCH_FormatValues, OWSWITCH_Get, OWSWITCH_Set
# Calling: --
# Parameter: hash = hash of device addressed # Parameter: hash = hash of device addressed
# #
######################################################################################## ########################################################################################
@ -378,7 +364,7 @@ sub OWSWITCH_ChannelNames($) {
for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){
#-- name #-- name
$cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : $owg_fixed[$i]; $cname = defined($attr{$name}{$owg_fixed[$i]."Name"}) ? $attr{$name}{$owg_fixed[$i]."Name"} : "$owg_fixed[$i]";
@cnama = split(/\|/,$cname); @cnama = split(/\|/,$cname);
if( int(@cnama)!=2){ if( int(@cnama)!=2){
push(@cnama,$cnama[0]); push(@cnama,$cnama[0]);
@ -398,7 +384,6 @@ sub OWSWITCH_ChannelNames($) {
#-- put into readings #-- put into readings
$hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unit; $hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unit;
$hash->{READINGS}{$owg_channel[$i]}{UNITABBR} = $unit;
} }
} }
@ -406,8 +391,6 @@ sub OWSWITCH_ChannelNames($) {
# #
# OWSWITCH_FormatValues - put together various format strings # OWSWITCH_FormatValues - put together various format strings
# #
# CalledBy: OWSWITCH_Get, OWSWITCH_Set
# Calling: --
# Parameter; hash = hash of device addressed, fs = format string # Parameter; hash = hash of device addressed, fs = format string
# #
######################################################################################## ########################################################################################
@ -420,7 +403,9 @@ sub OWSWITCH_FormatValues($) {
my $svalue = ""; my $svalue = "";
#-- external shortening signature #-- external shortening signature
my $sname = defined($attr{$name}{"stateS"}) ? $attr{$name}{"stateS"} : "&#x2607;"; my $sname = defined($attr{$name}{"stateS"}) ? $attr{$name}{"stateS"} : "X";
$sname = ""
if($sname eq "none");
#-- obtain channel names #-- obtain channel names
OWSWITCH_ChannelNames($hash); OWSWITCH_ChannelNames($hash);
@ -466,10 +451,6 @@ sub OWSWITCH_FormatValues($) {
# #
# OWSWITCH_Get - Implements GetFn function # OWSWITCH_Get - Implements GetFn function
# #
# CalledBy: FHEM
# Calling: OWSWITCH_ChannelNames,OWSWITCH_FormatValues,
# OWFSSWITCH_GetState,OWXSWITCH_GetState,
# OWX_Verify
# Parameter: hash = hash of device addressed, a = argument array # Parameter: hash = hash of device addressed, a = argument array
# #
######################################################################################## ########################################################################################
@ -480,6 +461,7 @@ sub OWSWITCH_Get($@) {
my $reading = $a[1]; my $reading = $a[1];
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL}; my $model = $hash->{OW_MODEL};
my ($value,$value2,$value3) = (undef,undef,undef); my ($value,$value2,$value3) = (undef,undef,undef);
my $ret = ""; my $ret = "";
my ($offset,$factor,$page,$cname,@cnama,@channel); my ($offset,$factor,$page,$cname,@cnama,@channel);
@ -550,7 +532,7 @@ sub OWSWITCH_Get($@) {
#-- OWX interface #-- OWX interface
if( $interface eq "OWX" ){ if( $interface eq "OWX" ){
$ret = OWXSWITCH_GetState($hash); OWXSWITCH_GetModState($hash,undef,undef);
}elsif( $interface eq "OWX_ASYNC") { }elsif( $interface eq "OWX_ASYNC") {
eval { eval {
$ret = OWX_ASYNC_RunToCompletion($hash,OWXSWITCH_PT_GetState($hash)); $ret = OWX_ASYNC_RunToCompletion($hash,OWXSWITCH_PT_GetState($hash));
@ -563,8 +545,12 @@ sub OWSWITCH_Get($@) {
}else{ }else{
return "OWSWITCH: Get with wrong IODev type $interface"; return "OWSWITCH: Get with wrong IODev type $interface";
} }
#-- process results #-- process result
if( ($master->{ASYNCHRONOUS}) && ($interface ne "OWFS") ){
return "OWSWITCH: $name getting input, please wait for completion";
}else{
return $name.".".$a[2]." => ".$hash->{READINGS}{$owg_channel[$fnd]}{VAL}; return $name.".".$a[2]." => ".$hash->{READINGS}{$owg_channel[$fnd]}{VAL};
}
#-- get all states #-- get all states
}elsif( $reading eq "gpio" ){ }elsif( $reading eq "gpio" ){
@ -572,7 +558,7 @@ sub OWSWITCH_Get($@) {
if( int(@a)==1 ); if( int(@a)==1 );
if( $interface eq "OWX" ){ if( $interface eq "OWX" ){
$ret = OWXSWITCH_GetState($hash); $ret = OWXSWITCH_GetModState($hash,undef,undef);
}elsif( $interface eq "OWX_ASYNC" ){ }elsif( $interface eq "OWX_ASYNC" ){
eval { eval {
$ret = OWX_ASYNC_RunToCompletion($hash,OWXSWITCH_PT_GetState($hash)); $ret = OWX_ASYNC_RunToCompletion($hash,OWXSWITCH_PT_GetState($hash));
@ -584,11 +570,15 @@ sub OWSWITCH_Get($@) {
return "OWSWITCH: Get with wrong IODev type $interface"; return "OWSWITCH: Get with wrong IODev type $interface";
} }
#-- process results #-- process results
if( $master->{ASYNCHRONOUS} ){
return "OWSWITCH: $name getting gpio, please wait for completion";
}else{
if( defined($ret) ){ if( defined($ret) ){
return "OWSWITCH: Could not get values from device $name, reason $ret"; return "OWSWITCH: Could not get values from device $name, reason $ret";
} }
return "OWSWITCH: $name.$reading => ".$hash->{READINGS}{"state"}{VAL}; return "OWSWITCH: $name.$reading => ".$hash->{READINGS}{"state"}{VAL};
} }
}
} }
####################################################################################### #######################################################################################
@ -620,7 +610,7 @@ sub OWSWITCH_GetValues($) {
if( $interface eq "OWX" ){ if( $interface eq "OWX" ){
#-- max 3 tries #-- max 3 tries
for(my $try=0; $try<3; $try++){ for(my $try=0; $try<3; $try++){
$ret = OWXSWITCH_GetState($hash); $ret = OWXSWITCH_GetModState($hash,undef,undef);
return if( !defined($ret) ); return if( !defined($ret) );
} }
}elsif( $interface eq "OWX_ASYNC" ){ }elsif( $interface eq "OWX_ASYNC" ){
@ -652,6 +642,7 @@ sub OWSWITCH_GetValues($) {
######################################################################################## ########################################################################################
# #
# OWSWITCH_InitializeDevice - initial readings # OWSWITCH_InitializeDevice - initial readings
#
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# #
######################################################################################## ########################################################################################
@ -738,24 +729,24 @@ sub OWSWITCH_Set($@) {
return "OWSWITCH: Set needs parameter when writing output: <channel>" return "OWSWITCH: Set needs parameter when writing output: <channel>"
if( int(@a)<2 ); if( int(@a)<2 );
#-- find out which channel we have #-- find out which channel we have
my $fnd=undef; my $outfnd=undef;
for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){
if( ($a[2] eq $owg_channel[$i]) || ($a[2] eq $owg_fixed[$i]) ){ if( ($a[2] eq $owg_channel[$i]) || ($a[2] eq $owg_fixed[$i]) ){
$fnd=$i; $outfnd=$i;
last; last;
} }
} }
return "OWSWITCH: Invalid output address, must be A,B,... or defined channel name" return "OWSWITCH: Invalid output address, must be A,B,... or defined channel name"
if( !defined($fnd) ); if( !defined($outfnd) );
#-- prepare gpio value #-- prepare gpio value
my $nval; my $outval;
my $ntim; my $ntim;
my $nstr=""; my $nstr="";
if( lc($a[3]) eq "on" ){ if( lc($a[3]) eq "on" ){
$nval = 0; $outval = 0;
}elsif( lc($a[3]) eq "off" ){ }elsif( lc($a[3]) eq "off" ){
$nval = 1; $outval = 1;
}elsif( lc($a[3]) =~ m/for-timer/ ){ }elsif( lc($a[3]) =~ m/for-timer/ ){
if( !($a[4] =~ m/\d\d\:\d\d\:\d\d/) ){ if( !($a[4] =~ m/\d\d\:\d\d\:\d\d/) ){
if( !($a[4] =~ m/\d{1,4}/ )){ if( !($a[4] =~ m/\d{1,4}/ )){
@ -767,10 +758,10 @@ sub OWSWITCH_Set($@) {
$ntim= $a[4]; $ntim= $a[4];
} }
if( lc($a[3]) eq "on-for-timer" ){ if( lc($a[3]) eq "on-for-timer" ){
$nval = 0; $outval = 0;
$nstr = "$a[0] $a[1] $a[2] off"; $nstr = "$a[0] $a[1] $a[2] off";
}elsif( lc($a[3]) eq "off-for-timer" ){ }elsif( lc($a[3]) eq "off-for-timer" ){
$nval = 1; $outval = 1;
$nstr = "$a[0] $a[1] $a[2] on"; $nstr = "$a[0] $a[1] $a[2] on";
} }
}else{ }else{
@ -778,36 +769,31 @@ sub OWSWITCH_Set($@) {
} }
if ($nstr ne ""){ if ($nstr ne ""){
fhem("define ".$a[0].".".$owg_fixed[$fnd]."Timer at +".$ntim." set ".$nstr); fhem("define ".$a[0].".".$owg_fixed[$outfnd]."Timer at +".$ntim." set ".$nstr);
} }
#-- OWX interface #-- OWX interface
if( $interface eq "OWX" ){ if( $interface eq "OWX" ){
$ret1 = OWXSWITCH_GetState($hash); $ret1 = OWXSWITCH_GetModState($hash,$outfnd,$outval);
$value = 0;
#-- vax or val ?
for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){
$value += ($hash->{owg_vax}->[$i]<<$i)
if( $i != $fnd );
$value += ($nval<<$i)
if( $i == $fnd );
}
$ret2 = OWXSWITCH_SetState($hash,$value);
}elsif( $interface eq "OWX_ASYNC"){ }elsif( $interface eq "OWX_ASYNC"){
eval { eval {
OWX_ASYNC_Schedule( $hash, OWXSWITCH_PT_SetOutput($hash,$fnd,$nval) ); OWX_ASYNC_Schedule( $hash, OWXSWITCH_PT_SetOutput($hash,$outfnd,$outval) );
}; };
$ret2 = GP_Catch($@) if $@; $ret2 = GP_Catch($@) if $@;
#-- OWFS interface #-- OWFS interface
}elsif( $interface eq "OWServer" ){ }elsif( $interface eq "OWServer" ){
$ret1 = OWFSSWITCH_GetState($hash); $ret1 = OWFSSWITCH_GetState($hash);
$value = 0; my $gpio = 0;
#-- vax or val ? #--
for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){ for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){
$value += ($hash->{owg_vax}->[$i]<<$i) if( $outval==0 ){
if( $i != $fnd ); $gpio += ($hash->{owg_vax}->[$i]<<$i)
$value += ($nval<<$i) if( $i != $outfnd );
if( $i == $fnd ); }else{
$gpio += ($hash->{owg_vax}->[$i]<<$i);
$gpio += (1<<$i)
if( $i == $outfnd );
}
} }
$ret2 = OWFSSWITCH_SetState($hash,$value); $ret2 = OWFSSWITCH_SetState($hash,$value);
#-- Unknown interface #-- Unknown interface
@ -848,7 +834,7 @@ sub OWSWITCH_Set($@) {
} }
#-- process results - we have to reread the device #-- process results - we have to reread the device
OWSWITCH_GetValues($hash); #OWSWITCH_GetValues($hash);
Log 4, "OWSWITCH: Set $hash->{NAME} $key $value"; Log 4, "OWSWITCH: Set $hash->{NAME} $key $value";
return undef; return undef;
} }
@ -1009,124 +995,216 @@ sub OWFSSWITCH_SetState($$) {
# #
######################################################################################## ########################################################################################
# #
# OWXSWITCH_BinValues - Binary readings into clear values # OWXSWITCH_BinValues - Process reading from one device - translate binary into raw
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# context = mode for evaluating the binary data
# proc = processing instruction, also passed to OWX_Read.
# bitwise interpretation !!
# if 0, nothing special
# if 1 = bit 0, a reset will be performed not only before, but also after
# the last operation in OWX_Read
# if 2 = bit 1, the initial reset of the bus will be suppressed
# if 8 = bit 3, the fillup of the data with 0xff will be suppressed
# if 16= bit 4, the insertion will be at the top of the queue
# owx_dev = ROM ID of slave device
# crcpart = part of the data that needs to be part of the CRC check
# numread = number of bytes to receive
# res = result string
#
# #
######################################################################################## ########################################################################################
sub OWXSWITCH_BinValues($$$$$$$$) { sub OWXSWITCH_BinValues($$$$$$$) {
my ($hash, $context, $success, $reset, $owx_dev, $command, $numread, $res) = @_; my ($hash, $context, $reset, $owx_dev, $crcpart, $numread, $res) = @_;
#-- always check for success, unused are reset, numread
return unless ($success and $context);
#Log 1,"OWXSWITCH_BinValues context = $context";
my @data=[];
my $value;
#-- hash of the busmaster #-- hash of the busmaster
my $master = $hash->{IODev}; my $master = $hash->{IODev};
my $name = $hash->{NAME};
my @data=[];
my $value;
my $msg;
my $cmd;
my $chip;
my $outfnd;
my $outval;
OWX_WDBG($name,"OWXSWITCH_BinValues called for device $name in context $context with data ",$res)
if( $main::owx_debug>2 );
#-- note: value 1 corresponds to OFF, 0 to ON normally #-- note: value 1 corresponds to OFF, 0 to ON normally
# val = input value, vax = output value # val = input value, vax = output value
#-- Outer if - check get or set #-- Outer if - check get or set
if ( $context =~ /.*getstate.*/ ){ if ( $context =~ /^(......)\.(get|mod)state\.?(\d)?\.?(\d)?/){
$cmd = $2;
$chip = $1;
$outfnd = $3;
$outval = $4;
#-- family = 12 => DS2406 ------------------------------------------------------- #-- family = 12 => DS2406 -------------------------------------------------------
if( ($context eq "getstate.ds2406") or ($context eq "ds2406.getstate") ) { if( $chip eq "ds2406" ) {
@data=split(//,$res); @data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 4 bytes" if (@data != 4){
if (@data != 4); $msg="Error - $name returns invalid data length, ".int(@data)." instead of 4 bytes, ";
return "invalid CRC" }elsif(OWX_CRC16($crcpart.substr($res,0,2),$data[2],$data[3]) == 0){
if ( OWX_CRC16($command.substr($res,0,2),$data[2],$data[3]) == 0); $msg="Error - state could not be set for device $name, invalid CRC, ";
$hash->{owg_val}->[0] = (ord($data[0])>>2) & 1; }else{
$hash->{owg_vax}->[0] = ord($data[0]) & 1; $msg="No error, ";
$hash->{owg_val}->[1] = (ord($data[0])>>3) & 1; $value=ord($data[0]);
$hash->{owg_vax}->[1] = (ord($data[0])>>1) & 1; $hash->{owg_val}->[0] = ($value>>2) & 1;
$hash->{owg_vax}->[0] = $value & 1;
$hash->{owg_val}->[1] = ($value>>3) & 1;
$hash->{owg_vax}->[1] = ($value>>1) & 1;
}
OWX_WDBG($name,"OWXSWITCH_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#-- family = 29 => DS2408 ------------------------------------------------------- #-- family = 29 => DS2408 -------------------------------------------------------
}elsif( ($context eq "getstate.ds2408") or ($context eq "ds2408.getstate") ) { }elsif( $chip eq "ds2408" ) {
@data=split(//,$res); @data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 10 bytes" if (@data != 10){
if (@data != 10); $msg="Error - $name returns invalid data length, ".int(@data)." instead of 10 bytes, ";
return "invalid data" }elsif(ord($data[6])!=255){
if (ord($data[6])!=255); $msg="Error - $name returns invalid data, ";
return "invalid CRC" }elsif(OWX_CRC16($crcpart.substr($res,0,8),$data[8],$data[9]) == 0){
if( OWX_CRC16($command.substr($res,0,8),$data[8],$data[9]) == 0); $msg="Error - state could not be set for device $name, invalid CRC, ";
}else{
$msg="No error, ";
for(my $i=0;$i<8;$i++){ for(my $i=0;$i<8;$i++){
$hash->{owg_val}->[$i] = (ord($data[0])>>$i) & 1; $hash->{owg_val}->[$i] = (ord($data[0])>>$i) & 1;
$hash->{owg_vax}->[$i] = (ord($data[1])>>$i) & 1; $hash->{owg_vax}->[$i] = (ord($data[1])>>$i) & 1;
}; };
}
OWX_WDBG($name,"OWXSWITCH_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#-- family = 3A => DS2413 ------------------------------------------------------- #-- family = 3A => DS2413 -------------------------------------------------------
}elsif( ($context eq "getstate.ds2413") or ($context eq "ds2413.getstate") ){ }elsif( $chip eq "ds2413" ){
@data=split(//,$res); @data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 2 bytes" if (@data != 2){
if (@data != 2); $msg="Error - $name returns invalid data length, ".int(@data)." instead of 2 bytes, ";
return "invalid data" }elsif((15- (ord($data[0])>>4)) != (ord($data[0]) & 15)){
if ( (15- (ord($data[0])>>4)) != (ord($data[0]) & 15) ); $msg="Error - $name returns invalid data, ";
}else{
$msg="No error, ";
$hash->{owg_val}->[0] = ord($data[0]) & 1; $hash->{owg_val}->[0] = ord($data[0]) & 1;
$hash->{owg_vax}->[0] = (ord($data[0])>>1) & 1; $hash->{owg_vax}->[0] = (ord($data[0])>>1) & 1;
$hash->{owg_val}->[1] = (ord($data[0])>>2) & 1; $hash->{owg_val}->[1] = (ord($data[0])>>2) & 1;
$hash->{owg_vax}->[1] = (ord($data[0])>>3) & 1; $hash->{owg_vax}->[1] = (ord($data[0])>>3) & 1;
}
OWX_WDBG($name,"OWXSWITCH_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#-- #--
}else{ }else{
return "unknown device family $hash->{OW_FAMILY} in OWXSWITCH_BinValues getstate\n"; die "OWSWITCH: $name has unknown device family $hash->{OW_FAMILY} in OWXSWITCH_BinValues getstate\n";
}; };
#-- now only if data has to be overwritten
if( $cmd eq "mod" ){
my $gpio = 0;
#--
for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){
if( $outval==0 ){
$gpio += ($hash->{owg_vax}->[$i]<<$i)
if( $i != $outfnd );
}else{
$gpio += ($hash->{owg_vax}->[$i]<<$i);
$gpio += (1<<$i)
if( $i == $outfnd );
}
}
#-- re-set the state
OWXSWITCH_SetState($hash,$gpio);
}
#-- Now for context setstate #-- Now for context setstate
}elsif ( $context =~ /.*setstate.*/){ }elsif ( $context =~ /^(......)\.setstate\.?(\d+)?\.?(\d+)?/){
$chip = $1;
$value = $2;
#-- family = 12 => DS2406 ------------------------------------------------------- #-- family = 12 => DS2406 -------------------------------------------------------
if( ($context =~ /setstate\.ds2406\..*/) or ($context =~ /ds2406\.setstate\..*/) ) { if( $chip eq "ds2406" ) {
$value = substr($context,-1);
@data=split(//,$res); @data=split(//,$res);
return "state could not be set for device $owx_dev" if (@data != 2){
if( int(@data) != 2); $msg="Error - $name returns invalid data length, ".int(@data)." instead of 2 bytes, ";
return "invalid CRC" }elsif(OWX_CRC16($crcpart,$data[0],$data[1]) == 0){
if (OWX_CRC16($command,$data[0],$data[1]) == 0); $msg="Error - state could not be set for device $name, invalid CRC, ";
#-- put into local buffer]"; }else{
$hash->{owg_val}->[0] = $value % 2; $msg="No error, ";
$hash->{owg_vax}->[0] = $value % 2; $outval = $value % 2;
$hash->{owg_val}->[1] = int($value / 2); $hash->{owg_vax}->[0] = $outval;
$hash->{owg_vax}->[1] = int($value / 2); $hash->{owg_val}->[0] = 0
if( $outval ==0);
$outval = int($value / 2);
$hash->{owg_vax}->[1] = $outval;
$hash->{owg_val}->[1] = 0
if( $outval ==0);
}
OWX_WDBG($name,"OWXSWITCH_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#-- family = 29 => DS2408 ------------------------------------------------------- #-- family = 29 => DS2408 -------------------------------------------------------
}elsif( ($context eq "setstate.ds2408") or ($context eq "ds2408.setstate") ) { }elsif( $chip eq "ds2408" ) {
@data=split(//,$res); if (length($res)!=1){
return "invalid data length, ".int(@data)." instead of 1 bytes" $msg="Error - $name returns invalid data length, ".length($res)." instead of 1 bytes, ";
if (@data != 1); }elsif($res ne "\xAA"){
return "state could not be set for device $owx_dev" $msg="Error - state could not be set for device $name, ";
if( $data[0] ne "\xAA"); }else{
$msg="No error, ";
for(my $i=0;$i<8;$i++){
$outval = ($value >>$i) & 1;
$hash->{owg_vax}->[$i] = $outval;
$hash->{owg_val}->[$i] = 0
if( $outval ==0);
};
}
OWX_WDBG($name,"OWXSWITCH_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#-- family = 3A => DS2413 ------------------------------------------------------- #-- family = 3A => DS2413 -------------------------------------------------------
}elsif( ($context eq "setstate.ds2413") or ($context eq "ds2413.setstate") ){ }elsif( $chip eq "ds2413" ){
@data=split(//,$res); @data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 1 bytes" if (@data != 2){
if (@data != 1); $msg="Error - $name returns invalid data length, ".int(@data)." instead of 2 bytes, ";
return "state could not be set for device $owx_dev" }elsif( $data[0] ne "\xAA"){
if( $data[0] ne "\xAA"); $msg="Error - state could not be set for device $name, ";
}else{
$msg="No error, ";
$outval = (ord($data[1])>>1) & 1;
$hash->{owg_vax}->[0] = $outval;
$hash->{owg_val}->[0] = 0
if( $outval ==0);
$outval = (ord($data[1])>>3) & 1;
$hash->{owg_vax}->[1] = $outval;
$hash->{owg_val}->[1] = 0
if( $outval ==0);
}
OWX_WDBG($name,"OWXSWITCH_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#-- #--
}else{ }else{
return "unknown device family $hash->{OW_FAMILY} in OWXSWITCH_BinValues setstate\n"; die "OWSWITCH: $name has unknown device family $hash->{OW_FAMILY} in OWXSWITCH_BinValues setstate\n";
}; };
OWXSWITCH_GetModState($hash,undef,undef);
}else{ }else{
return "unknown context in OWXSWITCH_BinValues"; die "OWSWITCH: unknown context $context in OWXSWITCH_BinValues";
} }
#-- and now from raw to formatted values #-- and now from raw to formatted values
$hash->{PRESENT} = 1; $hash->{PRESENT} = 1;
$value = OWSWITCH_FormatValues($hash); $value = OWSWITCH_FormatValues($hash);
Log 5, $value;
return undef; return undef;
} }
######################################################################################## ########################################################################################
# #
# OWXSWITCH_GetState - Get gpio ports from device # OWXSWITCH_GetModState - Get gpio ports from device and overwrite
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# mod = if 1, overwrite state with new data
# #
######################################################################################## ########################################################################################
sub OWXSWITCH_GetState($@) { sub OWXSWITCH_GetModState($$$) {
my ($hash,$sync) = @_; my ($hash,$outfnd,$outval) = @_;
my ($select, $res, @data); my ($select, $res, @data);
@ -1137,11 +1215,23 @@ sub OWXSWITCH_GetState($@) {
#-- hash of the busmaster #-- hash of the busmaster
my $master = $hash->{IODev}; my $master = $hash->{IODev};
my $name = $hash->{NAME};
#-- reset presence #-- reset presence
$hash->{PRESENT} = 0; $hash->{PRESENT} = 0;
my ($i,$j,$k); #-- what do we have to do
my $context;
my $proc;
if( !defined($outfnd) ){
$context = "getstate";
#-- take your time
$proc = 0;
}else{
$context = "modstate.$outfnd.$outval";
#-- faster !
$proc = 16;
}
#-- family = 12 => DS2406 #-- family = 12 => DS2406
if( $hash->{OW_FAMILY} eq "12" ) { if( $hash->{OW_FAMILY} eq "12" ) {
@ -1150,45 +1240,78 @@ sub OWXSWITCH_GetState($@) {
# \xF5 plus the two byte channel control and the value # \xF5 plus the two byte channel control and the value
#-- reading 9 + 3 + 2 data bytes + 2 CRC bytes = 16 bytes #-- reading 9 + 3 + 2 data bytes + 2 CRC bytes = 16 bytes
$select=sprintf("\xF5\xDD\xFF"); $select=sprintf("\xF5\xDD\xFF");
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,4); $res=OWX_Complex($master,$owx_dev,$select,4);
return "$owx_dev not accessible in reading" return "OWSWITCH: $name not accessible in reading"
if( $res eq 0 ); if( $res eq 0 );
return "$owx_dev has returned invalid data" return "OWSWITCH: $name has returned invalid data"
if( length($res)!=16); if( length($res)!=16);
OWX_Reset($master); #OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2406.getstate",1,undef,$owx_dev,substr($res,9,3),undef,substr($res,12)); eval {
OWXSWITCH_BinValues($hash,"ds2406.$context",undef,$owx_dev,$select,4,substr($res,12));
};
return $@ ? $@ : undef;
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "ds2406.$context", $proc, $owx_dev, $select, $select, 4, 12, \&OWXSWITCH_BinValues, 0);
return undef;
}
#-- family = 29 => DS2408 #-- family = 29 => DS2408
}elsif( $hash->{OW_FAMILY} eq "29" ) { }elsif( $hash->{OW_FAMILY} eq "29" ) {
#=============== get gpio values =============================== #=============== get gpio values ===============================
#-- issue the match ROM command \x55 and the read PIO rtegisters command #-- issue the match ROM command \x55 and the read PIO registers command
# \xF5 plus the two byte channel target address # \xF5 plus the two byte channel target address
#-- reading 9 + 3 + 8 data bytes + 2 CRC bytes = 22 bytes #-- reading 9 + 3 + 8 data bytes + 2 CRC bytes = 22 bytes
$select=sprintf("\xF0\x88\x00"); $select=sprintf("\xF0\x88\x00");
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,10); $res=OWX_Complex($master,$owx_dev,$select,10);
return "$owx_dev not accessible in reading" return "OWSWITCH: $name not accessible in reading"
if( $res eq 0 ); if( $res eq 0 );
return "$owx_dev has returned invalid data" return "OWSWITCH: $name has returned invalid data"
if( length($res)!=22); if( length($res)!=22);
OWX_Reset($master); #OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2408.getstate",1,undef,$owx_dev,substr($res,9,3),undef,substr($res,12)); eval {
OWXSWITCH_BinValues($hash,"ds2408.$context",0,$owx_dev,$select,4,substr($res,12));
};
return $@ ? $@ : undef;
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "ds2408.$context", $proc, $owx_dev, $select, $select,10, 12, \&OWXSWITCH_BinValues, 0);
return undef;
}
#-- family = 3A => DS2413 #-- family = 3A => DS2413
}elsif( $hash->{OW_FAMILY} eq "3A" ) { }elsif( $hash->{OW_FAMILY} eq "3A" ) {
#=============== get gpio values =============================== #=============== get gpio values ===============================
#-- issue the match ROM command \x55 and the read gpio command #-- issue the match ROM command \x55 and the read gpio command
# \xF5 plus 2 empty bytes # \xF5 plus 2 empty bytes
#-- reading 9 + 1 + 2 data bytes = 12 bytes #-- reading 9 + 1 + 2 data bytes = 12 bytes
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,"\xF5",2); $res=OWX_Complex($master,$owx_dev,"\xF5",2);
return "$owx_dev not accessible in reading" return "OWSWITCH: $name not accessible in reading"
if( $res eq 0 ); if( $res eq 0 );
return "$owx_dev has returned invalid data" return "OWSWITCH: $name has returned invalid data"
if( length($res)!=12); if( length($res)!=12);
#OWX_Reset($master); #OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2413.getstate",1,undef,$owx_dev,substr($res,9,1),undef,substr($res,10)); eval {
OWXSWITCH_BinValues($hash,"ds2413.$context",0,$owx_dev,substr($res,9,1),2,substr($res,10));
};
return $@ ? $@ : undef;
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "ds2413.$context", $proc, $owx_dev, "\xF5", "\xF5", 2, 10, \&OWXSWITCH_BinValues, 0);
return undef;
}
} else { } else {
return "unknown device family $hash->{OW_FAMILY}\n"; return "OWSWITCH: $name has unknown device family $hash->{OW_FAMILY}\n";
} }
} }
@ -1197,7 +1320,7 @@ sub OWXSWITCH_GetState($@) {
# OWXSWITCH_SetState - Set gpio ports of device # OWXSWITCH_SetState - Set gpio ports of device
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# value = integer value for device outputs # value = integer value for device gpio output
# #
######################################################################################## ########################################################################################
@ -1205,7 +1328,6 @@ sub OWXSWITCH_SetState($$) {
my ($hash,$value) = @_; my ($hash,$value) = @_;
my ($select, $res, $res2, @data); my ($select, $res, $res2, @data);
#-- ID of the device #-- ID of the device
@ -1216,8 +1338,6 @@ sub OWXSWITCH_SetState($$) {
#-- hash of the busmaster #-- hash of the busmaster
my $master = $hash->{IODev}; my $master = $hash->{IODev};
my ($i,$j,$k);
#-- family = 12 => DS2406 #-- family = 12 => DS2406
if( $hash->{OW_FAMILY} eq "12" ) { if( $hash->{OW_FAMILY} eq "12" ) {
#=============== set gpio values =============================== #=============== set gpio values ===============================
@ -1240,42 +1360,66 @@ sub OWXSWITCH_SetState($$) {
# \x55 at address TA1 = \x07 TA2 = \x00 # \x55 at address TA1 = \x07 TA2 = \x00
#-- reading 9 + 4 + 2 data bytes = 15 bytes #-- reading 9 + 4 + 2 data bytes = 15 bytes
$select=sprintf("\x55\x07\x00%c",$statneu); $select=sprintf("\x55\x07\x00%c",$statneu);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,2); $res=OWX_Complex($master,$owx_dev,$select,2);
if( $res eq 0 ){ if( $res eq 0 ){
return "device $owx_dev not accessible in writing"; return "device $owx_dev not accessible in writing";
} }
OWX_Reset($master); #OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2406.setstate.$value",1,undef,$owx_dev,substr($res,9,4),undef,substr($res,13)); return OWXSWITCH_BinValues($hash,"ds2406.setstate.$value",0,$owx_dev,$select,2,substr($res,13));
return; #-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
# 16 pushes this to the top of the queue
OWX_Qomplex($master, $hash, "ds2406.setstate.$value", 16, $owx_dev, $select, $select, 2, 13, \&OWXSWITCH_BinValues, 0);
return undef;
}
#-- family = 29 => DS2408 #-- family = 29 => DS2408
} elsif( $hash->{OW_FAMILY} eq "29" ) { } elsif( $hash->{OW_FAMILY} eq "29" ) {
#=============== set gpio values =============================== #=============== set gpio values ===============================
#-- issue the match ROM command \x55 and the write gpio command #-- issue the match ROM command \x55 and the write gpio command
# \x5A plus the value byte and its complement # \x5A plus the value byte and its complement
$select=sprintf("\x5A%c%c",$value,255-$value); $select=sprintf("\x5A%c%c",$value,255-$value);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,1); $res=OWX_Complex($master,$owx_dev,$select,1);
if( $res eq 0 ){ if( $res eq 0 ){
return "device $owx_dev not accessible in writing"; return "device $owx_dev not accessible in writing";
} }
OWX_Reset($master); OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2408.setstate",1,undef,$owx_dev,undef,undef,substr($res,12)); return OWXSWITCH_BinValues($hash,"ds2408.setstate.$value",0,$owx_dev,0,1,substr($res,12));
return; #-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
# 16 pushes this to the top of the queue
OWX_Qomplex($master, $hash, "ds2408.setstate.$value", 16, $owx_dev, $select, 0, 1, 12, \&OWXSWITCH_BinValues, 0);
return undef;
}
#-- family = 3A => DS2413 #-- family = 3A => DS2413
} elsif( $hash->{OW_FAMILY} eq "3A" ) { } elsif( $hash->{OW_FAMILY} eq "3A" ) {
#=============== set gpio values =============================== #=============== set gpio values ===============================
#-- issue the match ROM command \x55 and the write gpio command #-- issue the match ROM command \x55 and the write gpio command
# \x5A plus the value byte and its complement # \x5A plus the value byte and its complement
$select=sprintf("\x5A%c%c",252+$value,3-$value); $select=sprintf("\x5A%c%c",252+$value,3-$value);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,1); $res=OWX_Complex($master,$owx_dev,$select,1);
if( $res eq 0 ){ if( $res eq 0 ){
return "device $owx_dev not accessible in writing"; return "device $owx_dev not accessible in writing";
} }
OWX_Reset($master); OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2413.setstate",1,undef,$owx_dev,undef,undef,substr($res,12)); return OWXSWITCH_BinValues($hash,"ds2413.setstate",0,$owx_dev,0,2,substr($res,12));
return; #-- NEW OWX interface
}else{
#### master slave context proc owx_dev data cmd numread startread callback delay
# 16 pushes this to the top of the queue
OWX_Qomplex($master, $hash, "ds2413.setstate", 16, $owx_dev, $select, 0, 2, 12, \&OWXSWITCH_BinValues, 0);
return undef;
}
}else { }else {
return "unknown device family $hash->{OW_FAMILY}\n"; return "unknown device family $hash->{OW_FAMILY}\n";
} }
@ -1322,7 +1466,7 @@ sub OWXSWITCH_PT_GetState($) {
unless (length($response) == 4) { unless (length($response) == 4) {
PT_EXIT("$owx_dev has returned invalid data"); PT_EXIT("$owx_dev has returned invalid data");
} }
$ret = OWXSWITCH_BinValues($hash,"ds2406.getstate",1,1,$owx_dev,$thread->{'select'},4,$response); $ret = OWXSWITCH_BinValues($hash,"ds2406.getstate",1,$owx_dev,$thread->{'select'},4,$response);
if (defined $ret) { if (defined $ret) {
PT_EXIT($ret); PT_EXIT($ret);
} }
@ -1340,7 +1484,7 @@ sub OWXSWITCH_PT_GetState($) {
unless (length($response) == 10) { unless (length($response) == 10) {
PT_EXIT("$owx_dev has returned invalid data") PT_EXIT("$owx_dev has returned invalid data")
}; };
$ret = OWXSWITCH_BinValues($hash,"ds2408.getstate",1,1,$owx_dev,$thread->{'select'},10,$response); $ret = OWXSWITCH_BinValues($hash,"ds2408.getstate",1,$owx_dev,$thread->{'select'},10,$response);
if (defined $ret) { if (defined $ret) {
PT_EXIT($ret); PT_EXIT($ret);
} }
@ -1358,7 +1502,7 @@ sub OWXSWITCH_PT_GetState($) {
unless (length($response) == 2) { unless (length($response) == 2) {
PT_EXIT("$owx_dev has returned invalid data"); PT_EXIT("$owx_dev has returned invalid data");
} }
$ret = OWXSWITCH_BinValues($hash,"ds2413.getstate",1,1,$owx_dev,$thread->{'select'},2,$response); $ret = OWXSWITCH_BinValues($hash,"ds2413.getstate",1,$owx_dev,$thread->{'select'},2,$response);
if (defined $ret) { if (defined $ret) {
PT_EXIT($ret); PT_EXIT($ret);
} }
@ -1534,7 +1678,7 @@ sub OWXSWITCH_PT_SetOutput($$$) {
<p> <p>
<code>define OWX_S OWSWITCH DS2413 B5D502000000 60</code> <code>define OWX_S OWSWITCH DS2413 B5D502000000 60</code>
<br /> <br />
<code>attr OWX_S AName Lampe|light</code> <code>attr OWX_S AName light-a|la</code>
<br /> <br />
<code>attr OWX_S AUnit AN|AUS</code> <code>attr OWX_S AUnit AN|AUS</code>
</p> </p>
@ -1597,7 +1741,7 @@ sub OWXSWITCH_PT_SetOutput($$$) {
</a> </a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li> <br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owswitch_interval2"> <li><a name="owswitch_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval in <code>get &lt;name&gt; interval</code></a><br />Measurement interval in
seconds. </li> seconds. </li>
<li><a name="owswitch_input"> <li><a name="owswitch_input">
<code>get &lt;name&gt; input &lt;channel-name&gt;</code></a><br /> state for <code>get &lt;name&gt; input &lt;channel-name&gt;</code></a><br /> state for
@ -1605,7 +1749,7 @@ sub OWXSWITCH_PT_SetOutput($$$) {
not necessarily the one set as output state, because the output transistors are open 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 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 state of 1 = OFF, but a measured state of 0 = ON can also be due to an external
shortening of the output.</li> shortening of the output, it will be signaled by appending the value of the attribute stateS to the reading.</li>
<li><a name="owswitch_gpio"> <li><a name="owswitch_gpio">
<code>get &lt;name&gt; gpio</code></a><br />Obtain state of all channels</li> <code>get &lt;name&gt; gpio</code></a><br />Obtain state of all channels</li>
</ul> </ul>
@ -1613,19 +1757,14 @@ sub OWXSWITCH_PT_SetOutput($$$) {
<h4>Attributes</h4> For each of the following attributes, the channel identification A,B,... <h4>Attributes</h4> For each of the following attributes, the channel identification A,B,...
may be used. <ul> may be used. <ul>
<li><a name="owswitch_states"><code>&lt;name&gt; stateS &lt;string&gt;</code></a> <li><a name="owswitch_states"><code>&lt;name&gt; stateS &lt;string&gt;</code></a>
<br/> character string denoting external shortening condition, default is "red angled arrow downward"</li> <br/> character string denoting external shortening condition (default is X, set to "none" for empty).</li>
<li><a name="owswitch_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name <li><a name="owswitch_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
&lt;string&gt;[|&lt;string&gt;]</code></a> &lt;string&gt;[|&lt;string&gt;]</code></a>
<br />name for the channel [|name used in state reading] </li> <br />name for the channel [|short name used in state reading] </li>
<li><a name="owswitch_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit <li><a name="owswitch_cunit"><code>attr &lt;name&gt; &lt;channel&gt;Unit
&lt;string&gt;|&lt;string&gt;</code></a> &lt;string&gt;|&lt;string&gt;</code></a>
<br />display for on | off condition </li> <br />display for on | off condition </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a
href="#stateFormat">stateFormat</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
</ul> </ul>
=end html =end html

View File

@ -35,8 +35,8 @@
# #
# Additional attributes are defined in fhem.cfg # Additional attributes are defined in fhem.cfg
# #
# attr <name> stateAL "<string>" = character string for denoting low alarm condition, default is down triangle # attr <name> stateAL "<string>" = character string for denoting low alarm condition, default is
# attr <name> stateAH "<string>" = character string for denoting high alarm condition, default is up triangle # attr <name> stateAH "<string>" = character string for denoting high alarm condition, default is
# attr <name> tempOffset <float> = temperature offset in degree Celsius added to the raw temperature reading # 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, default is Celsius # attr <name> tempUnit <string> = unit of measurement, e.g. Celsius/Kelvin/Fahrenheit, default is Celsius
# attr <name> tempConv onkick|onread = determines, whether a temperature measurement will happen when "kicked" # attr <name> tempConv onkick|onread = determines, whether a temperature measurement will happen when "kicked"
@ -86,7 +86,7 @@ no warnings 'deprecated';
sub Log3($$$); sub Log3($$$);
sub AttrVal($$$); sub AttrVal($$$);
my $owx_version="5.28"; my $owx_version="6.0";
my %gets = ( my %gets = (
"id" => "", "id" => "",
@ -141,7 +141,7 @@ sub OWTHERM_Initialize ($) {
$hash->{NotifyFn}= "OWTHERM_Notify"; $hash->{NotifyFn}= "OWTHERM_Notify";
$hash->{InitFn} = "OWTHERM_Init"; $hash->{InitFn} = "OWTHERM_Init";
$hash->{AttrFn} = "OWTHERM_Attr"; $hash->{AttrFn} = "OWTHERM_Attr";
$hash->{AttrList}= "IODev model:DS1820,DS18B20,DS1822 loglevel:0,1,2,3,4,5 ". $hash->{AttrList}= "IODev model:DS1820,DS18B20,DS1822 ".
"stateAL stateAH ". "stateAL stateAH ".
"tempOffset tempUnit:Celsius,Fahrenheit,Kelvin ". "tempOffset tempUnit:Celsius,Fahrenheit,Kelvin ".
"tempConv:onkick,onread tempLow tempHigh ". "tempConv:onkick,onread tempLow tempHigh ".
@ -264,6 +264,16 @@ sub OWTHERM_Define ($$) {
return undef; return undef;
} }
#######################################################################################
#
# OWTHERM_Notify - Implements the Notify function
#
# Parameter hash = hash of device addressed
# a = argument array
#
########################################################################################
sub OWTHERM_Notify ($$) { sub OWTHERM_Notify ($$) {
my ($hash,$dev) = @_; my ($hash,$dev) = @_;
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) { if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
@ -272,6 +282,16 @@ sub OWTHERM_Notify ($$) {
} }
} }
#######################################################################################
#
# OWTHERM_Init - Implements the Init function
#
# Parameter hash = hash of device addressed
# a = argument array
#
########################################################################################
sub OWTHERM_Init ($) { sub OWTHERM_Init ($) {
my ($hash)=@_; my ($hash)=@_;
#-- Start timer for updates #-- Start timer for updates
@ -355,28 +375,29 @@ sub OWTHERM_FormatValues($) {
my $svalue = ""; my $svalue = "";
#-- attributes defined ? #-- attributes defined ?
$stateal = AttrVal($name,"stateAL","&#x25BE;"); $stateal = AttrVal($name,"stateAL","");
$stateah = AttrVal($name,"stateAH","&#x25B4;"); $stateah = AttrVal($name,"stateAH","");
$unit = AttrVal($name,"tempUnit","Celsius"); $unit = AttrVal($name,"tempUnit","Celsius");
$offset = AttrVal($name,"tempOffset",0.0); $offset = AttrVal($name,"tempOffset",0.0);
$factor = 1.0; $factor = 1.0;
if( $unit eq "Celsius" ){ if( $unit eq "none" ){
$abbr = "°C"; $abbr = "";
}elsif( $unit eq "Celsius" ){
$abbr = " °C";
} elsif ($unit eq "Kelvin" ){ } elsif ($unit eq "Kelvin" ){
$abbr = "K"; $abbr = " K";
$offset += "273.16" $offset += "273.16"
} elsif ($unit eq "Fahrenheit" ){ } elsif ($unit eq "Fahrenheit" ){
$abbr = "°F"; $abbr = " °F";
$offset = ($offset+32)/1.8; $offset = ($offset+32)/1.8;
$factor = 1.8; $factor = 1.8;
} else { } else {
$abbr="?"; $abbr=" ?";
Log3 $name, 3, "OWTHERM_FormatValues: Unknown temperature unit $unit"; Log3 $name, 3, "OWTHERM_FormatValues: Unknown temperature unit $unit";
} }
#-- these values are rather complex 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"}{UNIT} = $abbr;
$hash->{READINGS}{"temperature"}{UNITABBR} = $abbr;
$hash->{tempf}{offset} = $offset; $hash->{tempf}{offset} = $offset;
$hash->{tempf}{factor} = $factor; $hash->{tempf}{factor} = $factor;
@ -392,7 +413,7 @@ sub OWTHERM_FormatValues($) {
$main::attr{$name}{"tempHigh"} = $vhigh; $main::attr{$name}{"tempHigh"} = $vhigh;
#-- formats for output #-- formats for output
$statef = "T: %5.2f ".$abbr; $statef = "T: %5.2f".$abbr;
$svalue = sprintf($statef,$vval); $svalue = sprintf($statef,$vval);
#-- Test for alarm condition #-- Test for alarm condition
@ -431,6 +452,7 @@ sub OWTHERM_Get($@) {
my $reading = $a[1]; my $reading = $a[1];
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL}; my $model = $hash->{OW_MODEL};
my $value = undef; my $value = undef;
my $ret = ""; my $ret = "";
@ -450,6 +472,7 @@ sub OWTHERM_Get($@) {
#-- hash of the busmaster #-- hash of the busmaster
my $master = $hash->{IODev}; my $master = $hash->{IODev};
#-- Get other values according to interface type #-- Get other values according to interface type
my $interface= $hash->{IODev}->{TYPE}; my $interface= $hash->{IODev}->{TYPE};
@ -503,10 +526,13 @@ sub OWTHERM_Get($@) {
} }
#-- process results #-- process results
if( $master->{ASYNCHRONOUS} ){
return "OWTHERM: $name getting values, please wait for completion";
}else{
#-- when we have a return code, we have an error
if( defined($ret) ){ if( defined($ret) ){
return "OWTHERM: Could not get values from device $name, return was $ret"; return "OWTHERM: Could not get values from device $name, return was $ret";
} }
#-- return the special reading #-- return the special reading
if ($reading eq "temperature") { if ($reading eq "temperature") {
return "OWTHERM: $name.temperature => ". return "OWTHERM: $name.temperature => ".
@ -514,8 +540,10 @@ sub OWTHERM_Get($@) {
} elsif ($reading eq "alarm") { } elsif ($reading eq "alarm") {
return "OWTHERM: $name.alarm => L ".$main::attr{$name}{"tempLow"}. return "OWTHERM: $name.alarm => L ".$main::attr{$name}{"tempLow"}.
" H ".$main::attr{$name}{"tempHigh"}; " H ".$main::attr{$name}{"tempHigh"};
} } else {
return undef; return undef;
}
}
} }
####################################################################################### #######################################################################################
@ -616,8 +644,7 @@ sub OWTHERM_InitializeDevice($) {
} }
#-- these values are rather complex to obtain, therefore save them in the hash #-- these values are rather complex to obtain, therefore save them in the hash
$hash->{READINGS}{"temperature"}{TYPE} = "temperature"; $hash->{READINGS}{"temperature"}{TYPE} = "temperature";
$hash->{READINGS}{"temperature"}{UNIT} = $unit; $hash->{READINGS}{"temperature"}{UNIT} = $abbr;
$hash->{READINGS}{"temperature"}{UNITABBR} = $abbr;
$hash->{ERRCOUNT} = 0; $hash->{ERRCOUNT} = 0;
$hash->{tempf}{offset} = $offset; $hash->{tempf}{offset} = $offset;
$hash->{tempf}{factor} = $factor; $hash->{tempf}{factor} = $factor;
@ -894,32 +921,53 @@ sub OWFSTHERM_SetValues($$) {
# #
######################################################################################## ########################################################################################
# #
# OWXTHERM_BinValues - Binary readings into clear values # OWXTHERM_BinValues - Process reading from one device - translate binary into raw
# #
# Parameter hash = hash of device addressed # Parameter hash = hash of device addressed
# context = mode for evaluating the binary data
# proc = processing instruction, also passed to OWX_Read.
# bitwise interpretation !!
# if 0, nothing special
# if 1 = bit 0, a reset will be performed not only before, but also after
# the last operation in OWX_Read
# if 2 = bit 1, the initial reset of the bus will be suppressed
# if 8 = bit 3, the fillup of the data with 0xff will be suppressed
# if 16= bit 4, the insertion will be at the top of the queue
# owx_dev = ROM ID of slave device
# crcpart = part of the data that needs to be part of the CRC check
# numread = number of bytes to receive
# res = result string
#
# #
######################################################################################## ########################################################################################
sub OWXTHERM_BinValues($$$$$$) { sub OWXTHERM_BinValues($$$$$$$) {
my ($hash, $reset, $owx_dev, $command, $numread, $res) = @_; my ($hash, $context, $reset, $owx_dev, $crcpart, $numread, $res) = @_;
#Log3 $name, 1,"OWXTHERM_BinValues context = $context";
my ($i,$j,$k,@data,$ow_thn,$ow_tln); my ($i,$j,$k,@data,$ow_thn,$ow_tln);
my $change = 0; my $change = 0;
my $name = $hash->{NAME};
#Log3 $name, 1,"OWXTHERM: data length from reading device is ".length($res)." bytes"; my $msg;
#-- process results OWX_WDBG($name,"OWTHERM_BinValues called for device $name with ",$res)
die "$owx_dev not accessible in 2nd step" unless ( defined $res and $res ne 0 ); if( $main::owx_debug>2 );
#-- process results #-- process results
@data=split(//,$res); @data=split(//,$res);
die "invalid data length, ".int(@data)." instead of 9 bytes" if (@data != 9){
if (@data != 9); $msg="Error - $name returns invalid data length, ".int(@data)." instead of 9 bytes, ";
die "invalid data" }elsif(ord($data[7])<=0){
if (ord($data[7])<=0); $msg="Error - $name returns invalid data, ";
die "invalid CRC" }elsif(OWX_CRC8(substr($res,0,8),$data[8])==0){
if (OWX_CRC8(substr($res,0,8),$data[8])==0); $msg="Error - invalid data from device $name, invalid CRC, ";
}else{
$msg="No error, ";
for(my $i=0;$i<8;$i++){
$hash->{owg_val}->[$i] = (ord($data[0])>>$i) & 1;
$hash->{owg_vax}->[$i] = (ord($data[1])>>$i) & 1;
};
}
OWX_WDBG($name,"OWXTHERM_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#-- this must be different for the different device types #-- this must be different for the different device types
# family = 10 => DS1820, DS18S20 # family = 10 => DS1820, DS18S20
@ -967,7 +1015,7 @@ sub OWXTHERM_BinValues($$$$$$) {
$ow_tln = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]); $ow_tln = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]);
} else { } else {
die "OWXTHERM: Unknown device family $hash->{OW_FAMILY}\n"; die "OWTHERM: $name: Unknown device family $hash->{OW_FAMILY}\n";
} }
#-- process alarm settings #-- process alarm settings
@ -977,7 +1025,6 @@ sub OWXTHERM_BinValues($$$$$$) {
#-- and now from raw to formatted values #-- and now from raw to formatted values
$hash->{PRESENT} = 1; $hash->{PRESENT} = 1;
my $value = OWTHERM_FormatValues($hash); my $value = OWTHERM_FormatValues($hash);
Log3 $hash->{NAME}, 5, $value;
return undef; return undef;
} }
@ -1003,34 +1050,50 @@ sub OWXTHERM_GetValues($) {
my $master = $hash->{IODev}; my $master = $hash->{IODev};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $res;
#-- check, if the conversion has been called before for all sensors #-- check, if the conversion has been called before for all sensors
if( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){ if( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){
$con=0; $con=0;
} }
#-- if the conversion has not been called before #-- if the conversion has not been called before
if( $con==1 ){
#-- issue the match ROM command \x55 and the start conversion command \x44 #-- issue the match ROM command \x55 and the start conversion command \x44
#-- conversion needs some 950 ms - but we may also do it in shorter time !
if( $con==1 ){
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
if( OWX_Complex($master,$owx_dev,"\x44",0) eq 0 ){ if( OWX_Complex($master,$owx_dev,"\x44",0) eq 0 ){
return "$owx_dev not accessible"; return "OWTHERM: $name not accessible";
} }
#-- conversion needs some 950 ms - but we may also do it in shorter time !
select(undef,undef,undef,$convtimes{AttrVal($name,"resolution",12)}*0.001); select(undef,undef,undef,$convtimes{AttrVal($name,"resolution",12)}*0.001);
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, undef, 0, $owx_dev, "\x44", 0, 0, undef, undef, $convtimes{AttrVal($name,"resolution",12)}*0.001);
}
} }
#-- NOW ask the specific device #-- NOW ask the specific device
#-- issue the match ROM command \x55 and the read scratchpad command \xBE #-- issue the match ROM command \x55 and the read scratchpad command \xBE
#-- reading 9 + 1 + 8 data bytes and 1 CRC byte = 19 bytes #-- reading 9 + 1 + 8 data bytes and 1 CRC byte = 19 bytes
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
my $res=OWX_Complex($master,$owx_dev,"\xBE",9); my $res=OWX_Complex($master,$owx_dev,"\xBE",9);
return "$owx_dev not accessible in reading" return "OWTHERM: $name not accessible in reading"
if( $res eq 0 ); if( $res eq 0 );
return "$owx_dev has returned invalid data" return "OWTHERM: $name has returned invalid data"
if( length($res)!=19); if( length($res)!=19);
eval { eval {
OWXTHERM_BinValues($hash,undef,$owx_dev,undef,undef,substr($res,10,9)); OWXTHERM_BinValues($hash,undef,$owx_dev,undef,undef,9,substr($res,10,9));
}; };
return $@ ? $@ : undef; return $@ ? $@ : undef;
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, undef, 0, $owx_dev, "\xBE", 0, 9, 10, \&OWXTHERM_BinValues, 0);
return undef;
}
} }
####################################################################################### #######################################################################################
@ -1045,8 +1108,6 @@ sub OWXTHERM_GetValues($) {
sub OWXTHERM_SetValues($$) { sub OWXTHERM_SetValues($$) {
my ($hash, $args) = @_; my ($hash, $args) = @_;
my ($i,$j,$k);
my $name = $hash->{NAME}; my $name = $hash->{NAME};
#-- ID of the device #-- ID of the device
@ -1079,12 +1140,18 @@ sub OWXTHERM_SetValues($$) {
# 3. \x48 sent by WriteBytePower after match ROM => command ok, no effect on EEPROM # 3. \x48 sent by WriteBytePower after match ROM => command ok, no effect on EEPROM
my $select=sprintf("\x4E%c%c%c",$thp,$tlp,$cfg); my $select=sprintf("\x4E%c%c%c",$thp,$tlp,$cfg);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master); OWX_Reset($master);
my $res=OWX_Complex($master,$owx_dev,$select,3); my $res=OWX_Complex($master,$owx_dev,$select,3);
if( $res eq 0 ){ if( $res eq 0 ){
return "OWXTHERM: Device $owx_dev not accessible"; return "OWTHERM: $name not accessible for setting";
}
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, undef, 0, $owx_dev, $select, 0, 3, 10, undef, 0);
} }
return undef; return undef;
} }
@ -1137,7 +1204,7 @@ sub OWXTHERM_PT_GetValues($) {
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xBE",9); $thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xBE",9);
PT_WAIT_THREAD($thread->{pt_execute}); PT_WAIT_THREAD($thread->{pt_execute});
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR); die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
OWXTHERM_BinValues($hash,1,$owx_dev,undef,9,$thread->{pt_execute}->PT_RETVAL()); OWXTHERM_BinValues($hash,undef,1,$owx_dev,undef,9,$thread->{pt_execute}->PT_RETVAL());
PT_END; PT_END;
}); });
} }
@ -1299,12 +1366,10 @@ sub OWXTHERM_PT_SetValues($$) {
<ul> <ul>
<li><a name="owtherm_stateAL"><code>attr &lt;name&gt; stateAL &lt;string&gt;</code> <li><a name="owtherm_stateAL"><code>attr &lt;name&gt; stateAL &lt;string&gt;</code>
</a> </a>
<br />character string for denoting low alarm condition, default is down triangle, <br />character string for denoting low alarm condition, default is ↓</li>
e.g. the code &amp;#x25BE; leading to the sign &#x25BE; </li>
<li><a name="owtherm_stateAH"><code>attr &lt;name&gt; stateAH &lt;string&gt;</code> <li><a name="owtherm_stateAH"><code>attr &lt;name&gt; stateAH &lt;string&gt;</code>
</a> </a>
<br />character string for denoting high alarm condition, default is upward <br />character string for denoting high alarm condition, default is ↑</li>
triangle, e.g. the code &amp;#x25B4; leading to the sign &#x25B4; </li>
<li><a name="owtherm_tempConv"> <li><a name="owtherm_tempConv">
<code>attr &lt;name&gt; tempConv onkick|onread</code> <code>attr &lt;name&gt; tempConv onkick|onread</code>
</a> </a>
@ -1315,9 +1380,9 @@ sub OWXTHERM_PT_SetValues($$) {
</a> </a>
<br />temperature offset in °C added to the raw temperature reading. </li> <br />temperature offset in °C added to the raw temperature reading. </li>
<li><a name="owtherm_tempUnit"><code>attr &lt;name&gt; tempUnit <li><a name="owtherm_tempUnit"><code>attr &lt;name&gt; tempUnit
Celsius|Kelvin|Fahrenheit</code> none|Celsius|Kelvin|Fahrenheit</code>
</a> </a>
<br />unit of measurement (temperature scale), default is Celsius = °C </li> <br />unit of measurement (temperature scale) for state reading (default is Celsius = °C, use "none" for empty).</li>
<li><a name="owtherm_resolution"> <li><a name="owtherm_resolution">
<code>attr &lt;name&gt; resolution 9|10|11|12</code></a><br /> Temperature <code>attr &lt;name&gt; resolution 9|10|11|12</code></a><br /> Temperature
resolution in bit, only relevant for DS18B20 </li> resolution in bit, only relevant for DS18B20 </li>
@ -1336,13 +1401,7 @@ sub OWXTHERM_PT_SetValues($$) {
</a> </a>
<br /> low alarm temperature (on the temperature scale chosen by the attribute <br /> low alarm temperature (on the temperature scale chosen by the attribute
value). </li> value). </li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></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="#stateFormat">stateFormat</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
</ul> </ul>
=end html =end html