2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-07 06:48:43 +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> stateAH0 "<string>" = character string for denoting high normal condition, default is empty
# attr <name> stateAL1 "<string>" = character string for denoting low alarm condition, default is down triangle
# attr <name> stateAH1 "<string>" = character string for denoting high alarm condition, default is up triangle
# attr <name> stateAL1 "<string>" = character string for denoting low alarm condition, default is
# 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>Unit <string>[|<string>] = unit of measurement for this channel [|unit used in state reading]
#
# 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>Unit <string> = unit of measurement for this channel used in state reading (default V, none for empty)
# attr <name> <channel>Function <string> = arbitrary functional expression involving the values V<channel>=VA,VB,VC,VD
# VA is replaced by the measured voltage in channel A, etc.
#
# attr <name> <channel>Alarm <string> = alarm setting in this channel, either both, low, high or none (default)
# attr <name> <channel>Low <float> = measurement value (on the scale determined by offset and factor) for low alarm
# attr <name> <channel>High <float> = measurement value (on the scale determined by offset and factor) for high alarm
# 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 function) for high alarm
#
########################################################################################
#
@ -88,9 +84,9 @@ BEGIN {
use ProtoThreads;
no warnings 'deprecated';
sub Log($$);
sub Log3($$$);
my $owx_version="5.20";
my $owx_version="6.0";
#-- fixed raw channel name, flexible channel name
my @owg_fixed = ("A","B","C","D");
my @owg_channel = ("A","B","C","D");
@ -161,15 +157,13 @@ sub OWAD_Initialize ($) {
$hash->{InitFn} = "OWAD_Init";
$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 ".
"interval ".
$readingFnAttributes;
for( my $i=0;$i<int(@owg_fixed);$i++ ){
$attlist .= " ".$owg_fixed[$i]."Name";
$attlist .= " ".$owg_fixed[$i]."Offset";
$attlist .= " ".$owg_fixed[$i]."Factor";
$attlist .= " ".$owg_fixed[$i]."Function";
$attlist .= " ".$owg_fixed[$i]."Unit";
$attlist .= " ".$owg_fixed[$i]."Alarm:none,low,high,both";
@ -391,11 +385,11 @@ sub OWAD_ChannelNames($) {
my $name = $hash->{NAME};
my $state = $hash->{READINGS}{"state"}{VAL};
my ($cname,@cnama,$unit,@unarr);
my ($cname,@cnama,$unit);
for (my $i=0;$i<int(@owg_fixed);$i++){
#-- 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);
if( int(@cnama)!=2){
push(@cnama,$cnama[0]);
@ -403,16 +397,16 @@ sub OWAD_ChannelNames($) {
$owg_channel[$i]=$cnama[0];
#-- unit
$unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "Volt|V";
@unarr= split(/\|/,$unit);
if( int(@unarr)!=2 ){
push(@unarr,$unarr[0]);
$unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "V";
if($unit eq "none"){
$unit = "";
}else{
$unit = " ".$unit;
}
#-- put into readings
$hash->{READINGS}{$owg_channel[$i]}{ABBR} = $cnama[1];
$hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unarr[0];
$hash->{READINGS}{$owg_channel[$i]}{UNITABBR} = $unarr[1];
$hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unit;
}
}
@ -429,7 +423,7 @@ sub OWAD_FormatValues($) {
my $name = $hash->{NAME};
my $interface = $hash->{IODev}->{TYPE};
my ($offset,$factor,$vval,$vlow,$vhigh,$vfunc,$ret);
my ($vval,$vlow,$vhigh,$vfunc,$ret);
my $vfuncall = "";
my $svalue = "";
@ -445,8 +439,8 @@ sub OWAD_FormatValues($) {
$hash->{ALARM} = 0;
#-- alarm signatures
my $stateal1 = defined($attr{$name}{stateAL1}) ? $attr{$name}{stateAL1} : "&#x25BE;";
my $stateah1 = defined($attr{$name}{stateAH1}) ? $attr{$name}{stateAH1} : "&#x25B4;";
my $stateal1 = defined($attr{$name}{stateAL1}) ? $attr{$name}{stateAL1} : "";
my $stateah1 = defined($attr{$name}{stateAH1}) ? $attr{$name}{stateAH1} : "";
my $stateal0 = defined($attr{$name}{stateAL0}) ? $attr{$name}{stateAL0} : "";
my $stateah0 = defined($attr{$name}{stateAH0}) ? $attr{$name}{stateAH0} : "";
@ -463,13 +457,7 @@ sub OWAD_FormatValues($) {
#-- formats for output
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]."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"})){
if (defined($attr{$name}{$owg_fixed[$i]."Function"})){
$vfunc = $attr{$name}{$owg_fixed[$i]."Function"};
} else {
$vfunc = "V$owg_fixed[$i]";
@ -504,7 +492,7 @@ sub OWAD_FormatValues($) {
$main::attr{$name}{$owg_fixed[$i]."High"}=$vhigh;
#-- 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
$alarm = "none";
@ -542,6 +530,7 @@ sub OWAD_FormatValues($) {
}
#-- put into READINGS
$vval = sprintf( "%5.3f", $vval);
readingsBulkUpdate($hash,"$owg_channel[$i]",$vval);
#-- insert space
if( $i<int(@owg_fixed)-1 ){
@ -578,8 +567,6 @@ sub OWAD_Get($@) {
my $interface= $hash->{IODev}->{TYPE};
my ($value,$value2,$value3) = (undef,undef,undef);
my $ret = "";
my $offset;
my $factor;
#-- check syntax
return "OWAD: Get argument is missing @a"
@ -642,7 +629,10 @@ sub OWAD_Get($@) {
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) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){
@ -652,7 +642,7 @@ sub OWAD_Get($@) {
}
return "OWAD: $name.reading => ".$hash->{READINGS}{"state"}{VAL};
}
}
#-- get alarm values according to interface type
if($a[1] eq "alarm") {
#-- OWX interface
@ -671,7 +661,10 @@ sub OWAD_Get($@) {
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) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){
@ -689,6 +682,7 @@ sub OWAD_Get($@) {
}
return "OWAD: $name.alarm => $value";
}
}
#-- get status values according to interface type
if($a[1] eq "status") {
@ -708,7 +702,10 @@ sub OWAD_Get($@) {
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) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){
@ -751,6 +748,7 @@ sub OWAD_Get($@) {
return "OWAD: $name.status => ".$value;
}
}
}
#######################################################################################
#
@ -939,8 +937,6 @@ sub OWAD_Set($@) {
my $ret = undef;
my $channon = undef;
my $channo = undef;
my $factor;
my $offset;
my $condx;
my $name = $hash->{NAME};
@ -1024,7 +1020,7 @@ sub OWAD_Set($@) {
#-- set alarm values (alarm voltages)
}elsif( $key =~ m/(.*)(Low|High)/ ) {
#-- find upper and lower boundaries for given offset/factor
#-- find upper and lower boundaries
my $mmin = 0.0;
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
# 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($$$$$$$$) {
my ($hash, $context, $success, $reset, $owx_dev, $command, $numread, $res) = @_;
sub OWXAD_BinValues($$$$$$$) {
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 ($i,$j,$k,@data,$ow_thn,$ow_tln);
my ($ow_thn,$ow_tln);
#-- process results
@data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 10 bytes"
if (@data != 10);
return "invalid CRC"
if (OWX_CRC16($command.substr($res,0,8),$data[8],$data[9])==0);
if (@data != 10){
$msg="$name returns invalid data length, ".int(@data)." instead of 10 bytes ";
}elsif (OWX_CRC16($crcpart.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 ===============================
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;
}
#=============== get the alarm reading ===============================
} 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_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;
if( $final ){
my $value = OWAD_FormatValues($hash);
Log 5, $value;
}
return undef
}
@ -1465,6 +1484,8 @@ sub OWXAD_GetPage($$$@) {
return "wrong memory page requested from $owx_dev";
}
my $context = "ds2450.get".$page.($final ? ".final" : "");
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
#-- reset the bus
OWX_Reset($master);
#-- 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"
if( length($res)!=22);
#-- 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 {
return "wrong memory page write attempt";
}
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,0);
if( $res eq 0 ){
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;
}
@ -1613,7 +1648,7 @@ sub OWXAD_PT_GetPage($$$) {
PT_WAIT_THREAD($thread->{pt_execute});
die $thread->{pt_execute}->PT_CAUSE() if ($thread->{pt_execute}->PT_STATE() == PT_ERROR);
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) {
die $res;
}
@ -1716,16 +1751,14 @@ sub OWXAD_PT_SetPage($$) {
<br />
<code>attr OWX_AD DAlarm high</code>
<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 />
<code>attr OWX_AD DHigh 50.0</code>
<br />
<code>attr OWX_AD DName RelHumidity|humidity</code>
<br />
<code>attr OWX_AD DOffset -0.8088</code>
<br />
<code>attr OWX_AD DUnit percent|%</code>
<br />
</p><br />
<a name="OWADdefine"></a>
<h4>Define</h4>
@ -1792,46 +1825,31 @@ sub OWXAD_PT_SetPage($$) {
<li><a name="owad_stateAH0"><code>attr &lt;name&gt; stateAH0 &lt;string&gt;</code></a>
<br />character string for denoting high normal condition, default is empty </li>
<li><a name="owad_stateAL1"><code>attr &lt;name&gt; stateAL1 &lt;string&gt;</code></a>
<br />character string for denoting low alarm condition, default is down triangle,
e.g. the code &amp;#x25BE; leading to the sign &#x25BE;</li>
<br />character string for denoting low alarm condition, default is ↓</li>
<li><a name="owad_stateAH1"><code>attr &lt;name&gt; stateAH1 &lt;string&gt;</code></a>
<br />character string for denoting high alarm condition, default is upward
triangle, e.g. the code &amp;#x25B4; leading to the sign &#x25B4; </li>
<br />character string for denoting high alarm condition, default is ↑</li>
</ul> For each of the following attributes, the channel identification A,B,C,D may be used. <ul>
<li><a name="owad_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
&lt;string&gt;[|&lt;string&gt;]</code></a>
<br />name for the channel [|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
&lt;string&gt;[|&lt;string&gt;]</code></a>
<br />unit of measurement for this channel [|unit used in state reading]. </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>
&lt;string&gt;</code></a>
<br />unit of measurement for this channel used in state reading (default "V", set to "none" for empty). </li>
<li><a name="owad_cfunction"> <code>attr &lt;name&gt; &lt;channel&gt;Function
&lt;string&gt;</code></a>
<br />arbitrary functional expression involving the values VA,VB,VC,VD. VA is replaced by
the measured voltage in channel A, etc. This attribute allows linearization of measurement
curves as well as the mixing of various channels. <b>Replacement for Offset/Factor !</b></li>
<br />arbitrary functional expression involving the variables VA,VB,VC,VD. VA is replaced by
the (raw) measured voltage in channel A, etc. This attribute allows linearization of measurement
curves as well as the mixing of various channels. </li>
<li><a name="owad_calarm"><code>attr &lt;name&gt; &lt;channel&gt;Alarm
&lt;string&gt;</code></a>
<br />alarm setting in this channel, either both, low, high or none (default). </li>
<li><a name="owad_clow"><code>attr &lt;name&gt; &lt;channel&gt;Low
&lt;float&gt;</code></a>
<br />measurement value (on the scale determined by offset and factor) for low
alarm. </li>
<br />measurement value for low alarm. </li>
<li><a name="owad_chigh"><code>attr &lt;name&gt; &lt;channel&gt;High
&lt;float&gt;</code></a>
<br />measurement value (on the scale determined by offset and factor) for high
alarm. </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a
href="#stateFormat">stateFormat</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#verbose">verbose</a>,
<a href="#webCmd">webCmd</a></li>
<br />measurement value for highalarm. </li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
=end html

View File

@ -44,9 +44,9 @@
# 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> 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>Unit <string>[|<string>] = unit of measurement for this channel [|unit used in state reading]
# attr <name> <channel>Rate <string>[|<string>] = name for the channel rate [|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> = unit of measurement used in state reading (default cts, none for empty)
# 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>Factor <float> = factor multiplied to (reading+offset) in this channel
# attr <name> <channel>Mode <string> = counting mode = normal(default) or daily
@ -99,11 +99,13 @@ no warnings 'deprecated';
sub Log3($$$);
my $owx_version="5.33";
my $owx_version="6.0";
#-- fixed raw channel name, flexible channel name
my @owg_fixed = ("A","B");
my @owg_channel = ("A","B");
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 = (
"id" => "",
@ -229,13 +231,16 @@ sub OWCOUNT_Define ($$) {
if( $model eq "DS2423" ){
$fam = "1D";
CommandAttr (undef,"$name model DS2423");
@owg_memory = (1,1,0);
}elsif( $model eq "DS2423enew" ){
$fam = "1D";
@owg_memory = (1,1,0);
CommandAttr (undef,"$name model DS2423enew");
}elsif( $model eq "DS2423eold" ){
$fam = "1D";
CommandAttr (undef,"$name model DS2423eold");
CommandAttr (undef,"$name nomemory 1");
@owg_memory = (0,0,0);
}else{
return "OWCOUNT: Wrong 1-Wire device model $model";
}
@ -301,12 +306,61 @@ sub OWCOUNT_Notify ($$) {
sub OWCOUNT_Init ($) {
my ($hash)=@_;
#-- Start timer for updates
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+10, "OWCOUNT_GetValues", $hash, 0);
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
@ -369,56 +423,56 @@ sub OWCOUNT_ChannelNames($) {
for (my $i=0;$i<int(@owg_fixed);$i++){
#-- 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);
if( int(@cnama)!=2){
push(@cnama,$cnama[0]);
}
#-- unit
$unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "counts|cts";
@unarr= split(/\|/,$unit);
if( int(@unarr)!=2 ){
push(@unarr,$unarr[0]);
$unit = defined($attr{$name}{$owg_fixed[$i]."Unit"}) ? $attr{$name}{$owg_fixed[$i]."Unit"} : "cts";
if( $unit eq "none" ){
$unit = "";
}else{
$unit = " ".$unit;
}
#-- put into readings
$owg_channel[$i]=$cnama[0];
$hash->{READINGS}{$owg_channel[$i]}{ABBR} = $cnama[1];
$hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unarr[0];
$hash->{READINGS}{$owg_channel[$i]}{UNITABBR} = $unarr[1];
$hash->{READINGS}{$owg_channel[$i]}{UNIT} = $unit;
$period = defined($attr{$name}{$owg_fixed[$i]."Period"}) ? $attr{$name}{$owg_fixed[$i]."Period"} : "hour";
#-- put into readings
$hash->{READINGS}{$owg_channel[$i]}{PERIOD} = $period;
#-- 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);
if( int(@cnama)!=2){
push(@cnama,$cnama[0]);
}
#-- rate unit
my $runit = "";
if( $unit ne " " ){
if( $period eq "hour" ){
$runit = "/h";
$unit .= "/h";
}elsif( $period eq "minute" ){
$runit = "/min";
$unit .= "/min";
} 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
# Energy/Power
$hash->{READINGS}{$owg_rate[$i]}{UNIT} = "kW"
if ($unarr[0].$runit eq "kWh/h" );
$hash->{READINGS}{$owg_rate[$i]}{UNITABBR} = "kW"
if ($unarr[1].$runit eq "kWh/h" );
$unit = " kW"
if ($unit 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);
#-- 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
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]}{FACTOR} = $factor;
$unit = $hash->{READINGS}{$owg_channel[$i]}{UNITABBR};
$unit = $hash->{READINGS}{$owg_channel[$i]}{UNIT};
$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
if( $hash->{owg_val}->[$i] eq ""){
$svalue .= $owg_channel[$i].": ???";
$svalue .= $owg_channel[$i]." ???";
}else{
#-- only if attribute value mode=daily, take the midnight value from memory
if( $daily == 1){
@ -555,6 +634,7 @@ sub OWCOUNT_FormatValues($) {
my $msg = sprintf("%4d-%02d-%02d midnight %7.2f",
$year+1900,$month+1,$day,$dval2);
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
$dvalue .= sprintf( " %s: %5.2f %s %sM: %%5.2f %s", $owg_channel[$i],$dval,$unit,$owg_channel[$i],$unit);
@ -585,7 +665,7 @@ sub OWCOUNT_FormatValues($) {
#-- put in monthly and yearly sums
if( int(@monthv) == 2 ){
$total0 = $monthv[0]->[1];
$total1 = $monthv[1]->[1];
$total1 = ($day==1)?$total0:$monthv[1]->[1];
$dvalue = sprintf("D%02d ",$day).$dvalue;
$dvalue = sprintf($dvalue,$total0,$total1);
readingsBulkUpdate($hash,"day",$dvalue);
@ -597,7 +677,7 @@ sub OWCOUNT_FormatValues($) {
if( int(@yearv) == 2 ){
$total2 = $yearv[0]->[1];
$total3 = $yearv[1]->[1];
$total3 = ($month==0)?$total2: $yearv[1]->[1];
if ( $monthbreak == 1){
$mvalue = sprintf("M%02d ",$month+1).$mvalue;
$mvalue = sprintf($mvalue,$total0,$total2,$total1,$total3);
@ -631,6 +711,7 @@ sub OWCOUNT_Get($@) {
my $reading = $a[1];
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my $master = $hash->{IODev};
my $value = undef;
my $ret = "";
my $page;
@ -655,18 +736,20 @@ sub OWCOUNT_Get($@) {
if($a[1] eq "present") {
#-- hash of the busmaster
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 {
OWX_ASYNC_RunToCompletion($hash,OWX_ASYNC_PT_Verify($hash));
};
return GP_Catch($@) if $@;
return "$name.present => ".ReadingsVal($name,"present","unknown");
} else {
$value = OWX_Verify($master,$hash->{ROM_ID});
}
$hash->{PRESENT} = $value;
return "$name.present => $value";
}
#-- get interval
@ -733,7 +816,7 @@ sub OWCOUNT_Get($@) {
$value .= $owg_channel[$i]."Y: ".$year2[$i]->[1]." ".$unit.
" (yearly sum until now, average ".$year2[$i]->[2]." ".$unit."/d)\n";
}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;
@ -754,6 +837,10 @@ sub OWCOUNT_Get($@) {
return "OWCOUNT: Wrong memory page requested";
}
$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
if( $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];
}
}
}
if( $reading eq "midnight" ){
return "OWCOUNT: get needs parameter when reading midnight: <channel>"
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"
}
$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
if( $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];
}
}
}
#-- check syntax for getting counter
if( $reading eq "raw" ){
@ -794,21 +887,27 @@ sub OWCOUNT_Get($@) {
return "OWCOUNT: Invalid counter address, must be A, B or defined channel name"
}
$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
if( $ret ){
return "OWCOUNT: Could not get values from device $name, reason: ".$ret;
}
#-- only one counter will be returned
return "OWCOUNT: $name.raw $a[2] => ".$hash->{owg_val}->[$page-14];
}
#-- check syntax for getting counters
}elsif( $reading eq "counters" ){
return "OWCOUNT: Get needs no parameter when reading counters"
if( int(@a)==1 );
$ret1 = OWCOUNT_GetPage($hash,14,0,1);
$ret2 = OWCOUNT_GetPage($hash,15,1,1);
#-- process results
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWCOUNT: $name getting counters, please wait for completion";
}else{
$ret .= $ret1
if( defined($ret1) );
$ret .= $ret2
@ -820,6 +919,7 @@ sub OWCOUNT_Get($@) {
return "OWCOUNT: $name.counters => ".$hash->{READINGS}{"state"}{VAL};
}
}
}
#######################################################################################
#
@ -926,7 +1026,7 @@ sub OWCOUNT_GetMonth($) {
@linarr = split(' ',$line);
if( int(@linarr)==4+6*int(@owg_fixed) ){
$day = $linarr[3];
$day =~ s/D_0+//;
$day =~ s/D_+0+//;
@mchannel = ();
for (my $i=0;$i<int(@owg_fixed);$i++){
$val = $linarr[5+6*$i];
@ -936,9 +1036,8 @@ sub OWCOUNT_GetMonth($) {
}
}
}
if( int(@month)==0 ){
return "invalid logfile format in LogM"
if( $cday!=1 );
if( int(@month)<($cday-1) ){
Log3 $name,3, "OWCOUNT: warning, found only ".int(@month)." lines in logfile $lf of LogM";
}
} else {
return "cannot open logfile of LogM";
@ -1023,7 +1122,7 @@ sub OWCOUNT_GetYear($) {
@linarr = split(' ',$line);
if( int(@linarr)==4+6*int(@owg_fixed) ){
$month = $linarr[3];
$month =~ s/M_0+//;
$month =~ s/M_+0+//;
@mchannel = ();
for (my $i=0;$i<int(@owg_fixed);$i++){
$val = $linarr[5+6*$i];
@ -1033,9 +1132,8 @@ sub OWCOUNT_GetYear($) {
}
}
}
if( int(@year)==0 ){
return "invalid logfile format in LogY"
if($cmonth != 1);
if( int(@year)<($cmonth-1) ){
Log3 $name,3, "OWCOUNT: warning, found only ".int(@year)." lines in logfile $lf of LogY";
}
} else {
return "cannot open logfile of LogY";
@ -1046,13 +1144,13 @@ sub OWCOUNT_GetYear($) {
my @month2 = OWCOUNT_GetMonth($hash);
for (my $i=0;$i<int(@owg_fixed);$i++){
$total = 0.0;
#-- summing only if mode daily (means daily reset !)
$daily = 0;
if( defined($attr{$name}{$owg_fixed[$i]."Mode"} )){
if( $attr{$name}{$owg_fixed[$i]."Mode"} eq "daily"){
$daily = 1;
}
}
#-- sum previous months only in daily mode
if( $daily==1){
for (my $j=0;$j<int(@year);$j++){
$total += $year[$j][$i];
@ -1061,10 +1159,12 @@ sub OWCOUNT_GetYear($) {
$total = $year[int(@year)-1][$i]
if (int(@year)>0);
};
#-- add data from current day also for non-summed mode
$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
my $deltim = $cyday+($chour+$cmin/60.0 + $csec/3600.0)/24.0;
my $av = $deltim>0 ? int(100*$total2/$deltim)/100 : -1;
@ -1111,106 +1211,6 @@ sub OWCOUNT_GetValues($) {
if( $ret ne "" ){
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;
}
@ -1315,7 +1315,7 @@ sub OWCOUNT_Set($@) {
$data.=" ".$a[$i];
}
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);
}elsif( length($data) < 32 ){
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];
$data = sprintf("%4d-%02d-%02d midnight %7.2f",
$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);
}
}
@ -1447,12 +1447,12 @@ sub OWCOUNT_store($$$) {
} else {
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
#
@ -1470,8 +1470,18 @@ sub OWCOUNT_recall($$) {
close(OWXFILE);
return $line;
}
Log3 $name,1, "OWCOUNT_recall: Cannot open $filename for reading!";
return undef;;
Log3 $name,1, "OWCOUNT_recall: Cannot open $filename for reading, 2nd attempt";
$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
# via OWFS
#
# TODO: So far no automatic recognition of DS2423 / Emulator
#
# Prefix = OWFSCOUNT
#
########################################################################################
@ -1603,76 +1615,125 @@ sub OWFSCOUNT_SetPage($$$) {
# OWXCOUNT_BinValues - Process reading from one device - translate binary into raw
#
# 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($$$$$) {
my ($hash, $context, $owx_dev, $select, $res) = @_;
sub OWXCOUNT_BinValues($$$$$$$) {
my ($hash, $context, $proc, $owx_dev, $crcpart, $numread, $res) = @_;
#-- unused are success, reset, data
return undef unless (defined $context and $context =~ /^(get|set)page\.([\d]+)(\.final|)$/);
#-- hash of the busmaster
my $master = $hash->{IODev};
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 $page = $2;
my $final = $3;
my $name = $hash->{NAME};
Log3 ($name,5,"OWXCount_BinValues context: $context, $cmd page: $page, final: ".(defined $final ? $final : "undef"));
#=============== get memory + counter ===============================
if ($cmd eq "get") {
my ($i,$j,$k,@data,@writedata,$strval,$value);
my (@data,$strval,$value);
my $change = 0;
@data=split(//,$res);
#-- process results
@data=split(//,$res);
@writedata = split(//,$select);
return "invalid data length, ".int(@data)." instead of 42 bytes in three steps"
if( int(@data) < 42);
#return "invalid data"
# if (ord($data[17])<=0);
return "invalid CRC, ".ord($data[40])." ".ord($data[41])
if (OWX_CRC16($select.substr($res,0,40),$data[40],$data[41]) == 0);
if(ord($data[17])<=0){
#-- invalid data: do not die, but change memory flags
if( $page > 13 ){
$owg_memory[1]=0;
}else{
$owg_memory[0]=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
#my $res2 = "OWCOUNT FIRST 10 BYTES for device $owx_dev ARE ";
#for($i=0;$i<10;$i++){
# $j=int(ord(substr($res,$i,1))/16);
# $k=ord(substr($res,$i,1))%16;
# $res2.=sprintf "0x%1x%1x ",$j,$k;
#}
#main::Log(1, $res2);
if( int(@data) < 42){
$msg="$name returns invalid data length, ".int(@data)." instead of 42 bytes";
}elsif (OWX_CRC16($crcpart.substr($res,0,40),$data[40],$data[41]) == 0){
$msg="$name returns invalid CRC, ".ord($data[40])." ".ord($data[41]);
}
OWX_WDBG($name,"OWXCOUNT_BinValues: ".$msg,"")
if( $main::owx_debug>2 );
#--
my $nomemory = defined($attr{$name}{"nomemory"}) ? $attr{$name}{"nomemory"} : 0;
if( $nomemory==0 ){
#-- memory part, treated as string
$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 {
$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 : "";
#-- counter part
if( ($page == 14) || ($page == 15) ){
@data=split(//,substr($res,32));
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]);
return "device $owx_dev returns invalid data";
OWX_WDBG($name, "device $name returns invalid data ".ord($data[4])." ".ord($data[5])." ".ord($data[6])." ".ord($data[7])," ");
}
#-- counter value
$value = (ord($data[3])<<24) + (ord($data[2])<<16) +(ord($data[1])<<8) + ord($data[0]);
$hash->{owg_val}->[$page-14] = $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);
}
#-- and now from raw to formatted values
$hash->{PRESENT} = 1;
if( $final ) {
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;
}
@ -1699,8 +1760,6 @@ sub OWXCOUNT_GetPage($$$) {
#-- reset presence
$hash->{PRESENT} = 0;
my ($i,$j,$k);
#=============== wrong value requested ===============================
if( ($page<0) || ($page>15) ){
return "wrong memory page requested";
@ -1713,6 +1772,8 @@ sub OWXCOUNT_GetPage($$$) {
$select=sprintf("\xA5%c%c",$ta1,$ta2);
my $context = "getpage.".$page.($final ? ".final" : "");
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
#-- reset the bus
OWX_Reset($master);
#-- 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 );
return "$owx_dev has returned invalid data"
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
#
# 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 ($i,$j,$k);
#-- ID of the device, hash of the busmaster
my $owx_dev = $hash->{ROM_ID};
my $master = $hash->{IODev};
@ -1778,23 +1848,14 @@ sub OWXCOUNT_SetPage($$$) {
my $ta1 = ($page*32) & 255;
#Log 1, "OWXCOUNT: setting page Nr. $ta2 $ta1 $data";
$select=sprintf("\x0F%c%c",$ta1,$ta2).$data;
#-- first command, next 2 are address, then data
#$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);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
#-- reset the bus
OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,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
# \xAA, receiving 2 address bytes, 1 status byte and scratchpad content
$select = "\xAA";
@ -1804,37 +1865,41 @@ sub OWXCOUNT_SetPage($$$) {
# TODO: sometimes much less than 28
$res=OWX_Complex($master,$owx_dev,$select,28);
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
# \x5A followed by 3 byte authentication code obtained in previous read
$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
OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,6);
#-- process results
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;
}
@ -1885,7 +1950,7 @@ sub OWXCOUNT_PT_GetPage($$$) {
PT_WAIT_THREAD($thread->{pt_execute});
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;
}
PT_END;
@ -2026,13 +2091,13 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
<br /><h4>Example</h4><br />
<code>define OWC OWCOUNT 1D.CE780F000000 60</code>
<br />
<code>attr OWC AName Energie|energy</code>
<code>attr OWC AName energy|W</code>
<br />
<code>attr OWC AUnit kWh|kWh</code>
<code>attr OWC AUnit kWh</code>
<br />
<code>attr OWC APeriod hour</code>
<br />
<code>attr OWC ARate Leistung|power</code>
<code>attr OWC ARate power|P</code>
<br />
<code>attr OWX_AMode daily</code>
<br />
@ -2138,13 +2203,13 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
<ul>
<li><a name="owcount_cname"><code>attr &lt;name&gt; &lt;channel&gt;Name
&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
&lt;string&gt;[|&lt;string&gt;]</code></a>
<br />unit of measurement for this channel [|unit used in state reading.] </li>
&lt;string&</code></a>
<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
&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
&lt;float&gt;</code></a>
<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 |
second</code></a>
<br />period for rate calculation </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>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
=end html

View File

@ -66,9 +66,9 @@ BEGIN {
use GPUtils qw(:all);
use ProtoThreads;
no warnings 'deprecated';
sub Log($$);
sub Log3($$$);
my $owx_version="5.15";
my $owx_version="6.0beta6";
#-- declare variables
my %gets = (
"present" => "",
@ -107,8 +107,7 @@ sub OWID_Initialize ($) {
$hash->{AttrFn} = "OWID_Attr";
$hash->{NotifyFn} = "OWID_Notify";
$hash->{InitFn} = "OWID_Init";
$hash->{AttrList} = "IODev do_not_notify:0,1 showtime:0,1 model loglevel:0,1,2,3,4,5 ".
"interval ".
$hash->{AttrList} = "IODev do_not_notify:0,1 showtime:0,1 model interval".
$readingFnAttributes;
#--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;
#--
readingsSingleUpdate($hash,"state","Defined",1);
Log 3, "OWID: Device $name defined.";
Log3 $name,1, "OWID: Device $name defined.";
$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
#
@ -531,6 +530,10 @@ sub OWID_Undef ($) {
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
</ul>
<h4>Attributes</h4>
<ul>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
=end html
=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> temperature => temperature 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
#
# 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> 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> VUnit <string>[|<string>] = unit of measurement for the channel [|unit used in state reading]
# attr <name> Vfunction <string> = arbitrary functional expression involving the values VDD, V, T
# attr <name> VName <string>[|<string>] = name for the voltage channel [|short name 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, W, T
# 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
# 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($$);
my $owx_version="5.23";
my $owx_version="6.0";
#-- flexible channel name
my $owg_channel;
my ($owg_channel,$owg_schannel);
my %gets = (
"id" => "",
@ -112,17 +117,14 @@ my %updates = (
#
# Prefix = OWMULTI
#
##
# Parameters:
# hash - hash of device addressed
########################################################################################
#
# Called By:
# FHEM - Main Loop
# Gargelmargel - dunno where
# OWMULTI_Initialize
#
#Calling:
# None
##
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWMULTI_Initialize ($) {
my ($hash) = @_;
@ -136,16 +138,17 @@ sub OWMULTI_Initialize ($) {
#tempOffset = a temperature offset added to the temperature reading for correction
#tempUnit = a unit of measure: C/F/K
$hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 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 ".
"VName VUnit VFunction ".
"VName VUnit VFunction WName WUnit WFunction ".
"interval ".
$readingFnAttributes;
#-- temperature and voltage globals - always the raw values from the device
$hash->{owg_val}->[0] = undef;
$hash->{owg_val}->[2] = 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
main::LoadModule("OWX");
@ -336,29 +339,48 @@ sub OWMULTI_ChannelNames($) {
my $name = $hash->{NAME};
my $state = $hash->{READINGS}{"state"}{VAL};
my ($cname,@cnama,$unit,@unarr);
my ($tunit,$toffset,$tfactor,$tabbr,$vfunc);
my ($cname,@cnama,$unit);
my ($tunit,$toffset,$tfactor,$tabbr,$vfunc,$wfunc);
#-- 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);
if( int(@cnama)!=2){
push(@cnama,$cnama[0]);
}
#-- unit
$unit = defined($attr{$name}{"VUnit"}) ? $attr{$name}{"VUnit"} : "Volt|V";
@unarr= split(/\|/,$unit);
if( int(@unarr)!=2 ){
push(@unarr,$unarr[0]);
}
$unit = defined($attr{$name}{"VUnit"}) ? $attr{$name}{"VUnit"} : "V";
$unit = ""
if($unit eq "none");
#-- put into readings
$owg_channel = $cnama[0];
$hash->{READINGS}{$owg_channel}{VAL} = " ";
$hash->{READINGS}{$owg_channel}{ABBR} = $cnama[1];
$hash->{READINGS}{$owg_channel}{UNIT} = $unarr[0];
$hash->{READINGS}{$owg_channel}{UNITABBR} = $unarr[1];
$hash->{READINGS}{$owg_channel}{UNIT} = " ".$unit;
#-- 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
$hash->{READINGS}{"temperature"}{UNIT} = defined($attr{$name}{"tempUnit"}) ? $attr{$name}{"tempUnit"} : "Celsius";
@ -366,7 +388,9 @@ sub OWMULTI_ChannelNames($) {
$toffset = defined($attr{$name}{"tempOffset"}) ? $attr{$name}{"tempOffset"} : 0.0 ;
$tfactor = 1.0;
if( $tunit eq "Celsius" ){
if( $tunit eq "none" ){
$tabbr = "";
}elsif( $tunit eq "Celsius" ){
$tabbr = " °C";
} elsif ($tunit eq "Kelvin" ){
$tabbr = " K";
@ -382,8 +406,7 @@ sub OWMULTI_ChannelNames($) {
#-- these values are rather complex to obtain, therefore save them in the hash
$hash->{READINGS}{"temperature"}{ABBR} = "T";
$hash->{READINGS}{"temperature"}{UNIT} = $tunit;
$hash->{READINGS}{"temperature"}{UNITABBR} = $tabbr;
$hash->{READINGS}{"temperature"}{UNIT} = $tabbr;
$hash->{tempf}{offset} = $toffset;
$hash->{tempf}{factor} = $tfactor;
}
@ -400,11 +423,11 @@ sub OWMULTI_FormatValues($) {
my ($hash) = @_;
my $name = $hash->{NAME};
my ($toffset,$tfactor,$tval,$vfunc,$vval);
my ($toffset,$tfactor,$tval,$vfunc,$wfunc,$vval,$wval);
my $svalue = "";
#-- 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
OWMULTI_ChannelNames($hash);
@ -414,35 +437,53 @@ sub OWMULTI_FormatValues($) {
$tfactor = $hash->{tempf}{factor};
$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";
$wfunc = defined($attr{$name}{"WFunction"}) ? $attr{$name}{"WFunction"} : "W";
#-- replace by proper values
$vfunc =~ s/VDD/\$hash->{owg_val}->[1]/g;
$vfunc =~ s/V/\$hash->{owg_val}->[2]/g;
$vfunc =~ s/W/\$hash->{owg_val}->[3]/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
$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;
$vfunc = eval($vfunc);
if( !$vfunc ){
$vval = "";
$vval = 0.0;
} elsif( $vfunc ne "" ){
$vval = int( $vfunc*10+0.5)/10;
$vval = int( $vfunc*100+0.5)/100;
} 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
$svalue .= sprintf( "%s: %5.1f %s (T: %5.1f %s)",
$hash->{READINGS}{$owg_channel}{ABBR}, $vval,$hash->{READINGS}{$owg_channel}{UNITABBR},
$tval,$hash->{READINGS}{"temperature"}{UNITABBR});
$svalue .= sprintf( "%s: %5.2f%s (T: %5.1f%s %s: %5.2f%s)",
$hash->{READINGS}{$owg_channel}{ABBR}, $vval,$hash->{READINGS}{$owg_channel}{UNIT},
$tval,$hash->{READINGS}{"temperature"}{UNIT}, $hash->{READINGS}{$owg_schannel}{ABBR}, $wval,$hash->{READINGS}{$owg_schannel}{UNIT});
#-- put into READINGS
readingsBeginUpdate($hash);
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);
#-- STATE
@ -466,6 +507,7 @@ sub OWMULTI_Get($@) {
my $reading = $a[1];
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my $value = undef;
my $ret = "";
@ -538,7 +580,10 @@ sub OWMULTI_Get($@) {
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) ){
return "OWMULTI: Could not get values from device $name, reason $ret";
}
@ -558,7 +603,8 @@ sub OWMULTI_Get($@) {
}
if ( $reading eq "raw") {
return "OWMULTI: $name.raw => ".
$hash->{owg_val}->[2];
$hash->{owg_val}->[2]." V ".$hash->{owg_val}->[3]." V";
}
}
return undef;
}
@ -630,8 +676,9 @@ sub OWMULTI_InitializeDevice($) {
#-- Initial readings
$hash->{owg_val}->[0] = "";
$hash->{owg_val}->[2] = "";
$hash->{owg_val}->[1] = "";
$hash->{owg_val}->[2] = "";
$hash->{owg_val}->[3] = "";
#-- Set state to initialized
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}->[1] = OWServer_Read($master,"/$owx_add/VDD");
$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"
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"
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
$hash->{PRESENT} = 1;
my $value = OWMULTI_FormatValues($hash);
Log 5, $value;
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
# 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($$$$$$$$) {
my ($hash, $context, $success, $reset, $owx_dev, $command, $numread, $res) = @_;
sub OWXMULTI_BinValues($$$$$$$) {
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
return unless ($success and $context =~ /^ds2438.getv[ad]d$/);
return unless ($context =~ /^ds2438.getv[ad]d$/);
#Log 1,"OWXMULTI_BinValues context = $context";
#-- process results
my @data=split(//,$res);
@data=split(//,$res);
if (@data != 9) {
return "invalid data length, ".int(@data)." instead of 9 bytes";
}
if ((ord($data[0]) & 112)!=0) {
return "conversion not complete or data invalid";
}
if (OWX_CRC8(substr($res,0,8),$data[8])==0) {
return "invalid CRC";
$msg="$name returns invalid data length, ".int(@data)." instead of 9 bytes";
}elsif ((ord($data[0]) & 112)!=0) {
$msg="$name: conversion not complete or data invalid";
}elsif (OWX_CRC8(substr($res,0,8),$data[8])==0) {
$msg="$name returns invalid CRC";
}else{
$msg="No error";
}
OWX_WDBG($name,"OWXMULTI_BinValues: ".$msg,"")
if( $main::owx_debug>2 );
#-- this must be different for the different device types
# family = 26 => DS2438
#-- transform binary rep of VDD
if( $context eq "ds2438.getvdd") {
#-- temperature
my $lsb = ord($data[1]);
my $msb = ord($data[2]) & 127;
my $sign = ord($data[2]) & 128;
$lsb = ord($data[1]);
$msb = ord($data[2]) & 127;
$sign = ord($data[2]) & 128;
#-- test with -55 degrees
#$lsb = 0;
@ -843,7 +915,7 @@ sub OWXMULTI_BinValues($$$$$$$$) {
#$msb = 73;
#-- 2's complement form = signed bytes
$hash->{owg_val}->[0] = $msb+ $lsb/256;
$hash->{owg_val}->[0] = $msb+ $lsb/256.;
if( $sign !=0 ){
$hash->{owg_val}->[0] = -128+$hash->{owg_val}->[0];
}
@ -857,25 +929,31 @@ sub OWXMULTI_BinValues($$$$$$$$) {
#$msb = 1;
#-- supply voltage
$hash->{owg_val}->[1] = ($msb*256+ $lsb)/100;
};
$hash->{owg_val}->[1] = ($msb*256+ $lsb)/100.;
#-- transform binary rep of VAD
if( $context eq "ds2438.getvad") {
}elsif( $context eq "ds2438.getvad") {
#-- voltage
my $lsb = ord($data[3]);
my $msb = ord($data[4]) & 3;
$lsb = ord($data[3]);
$msb = ord($data[4]) & 3;
#-- test with 7.2 V
#$lsb = 208;
#$msb = 2;
#-- 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
$hash->{PRESENT} = 1;
my $value = OWMULTI_FormatValues($hash);
Log 5, $value;
};
return undef;
}
@ -893,7 +971,7 @@ sub OWXMULTI_GetValues($) {
my ($hash) = @_;
my ($i,$j,$k,$res,$ret);
my ($res,$ret);
#-- ID of the device
my $owx_dev = $hash->{ROM_ID};
@ -905,8 +983,11 @@ sub OWXMULTI_GetValues($) {
#------------------------------------------------------------------------------------
#-- switch the device to current measurement off, VDD only
#-- issue the match ROM command \x55 and the write scratchpad command
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
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";
}
@ -930,7 +1011,7 @@ sub OWXMULTI_GetValues($) {
#-- conversion needs some 6 ms !
#-- issue the match ROM command \x55 and the start conversion command
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";
}
select(undef,undef,undef,0.006);
@ -939,7 +1020,7 @@ sub OWXMULTI_GetValues($) {
#-- copy needs some 12 ms !
#-- issue the match ROM command \x55 and the recall memory command
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";
}
select(undef,undef,undef,0.012);
@ -953,13 +1034,14 @@ sub OWXMULTI_GetValues($) {
if( $res eq 0 );
return "$owx_dev has returned invalid data"
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);
#------------------------------------------------------------------------------------
#-- switch the device to current measurement off, V external only
#-- issue the match ROM command \x55 and the write scratchpad command
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";
}
#-- copy scratchpad to register
@ -972,7 +1054,7 @@ sub OWXMULTI_GetValues($) {
#-- conversion needs some 6 ms !
#-- issue the match ROM command \x55 and the start conversion command
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";
}
select(undef,undef,undef,0.006);
@ -981,7 +1063,7 @@ sub OWXMULTI_GetValues($) {
#-- copy needs some 12 ms !
#-- issue the match ROM command \x55 and the recall memory command
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";
}
select(undef,undef,undef,0.012);
@ -997,9 +1079,85 @@ sub OWXMULTI_GetValues($) {
if( $res eq 0 );
return "$owx_dev has returned invalid data"
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
@ -1126,7 +1284,7 @@ sub OWXMULTI_PT_GetValues($) {
unless (defined $res and length($res)==9) {
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) {
die $ret;
}
@ -1180,7 +1338,7 @@ sub OWXMULTI_PT_GetValues($) {
unless (defined $res and length($res)==9) {
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) {
die $ret;
}
@ -1250,9 +1408,9 @@ sub OWXMULTI_PT_SetValues($@) {
<p>
<code>define OWX_M OWMULTI 7C5034010000 45</code>
<br />
<code>attr OWX_M VName relHumidity|humidity</code>
<code>attr OWX_M VName humidity|rH</code>
<br />
<code>attr OWX_M VUnit percent|%</code>
<code>attr OWX_M VUnit %</code>
<br />
<code>attr OWX_M VFunction (161.29 * V / VDD - 25.8065)/(1.0546 - 0.00216 * T)</code>
</p>
@ -1305,34 +1463,43 @@ sub OWXMULTI_PT_SetValues($@) {
seconds. </li>
<li><a name="owmulti_reading">
<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">
<code>get &lt;name&gt; temperature</code></a><br />Obtain the temperature value. </li>
<li><a name="owmulti_vdd">
<code>get &lt;name&gt; VDD</code></a><br />Obtain the current supply voltage. </li>
<li><a name="owmulti_raw">
<code>get &lt;name&gt; V</code> or <code>get &lt;name&gt;
raw</code></a><br />Obtain the raw external voltage measurement. </li>
raw</code></a><br />Obtain the raw external voltage and external sense measurement. </li>
</ul>
<a name="OWMULTIattr"></a>
<h4>Attributes</h4>
<ul>
<li><a name="owmulti_vname"><code>attr &lt;name&gt; VName
&lt;string&gt;[|&lt;string&gt;]</code></a>
<br />name for the channel [|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
&lt;string&gt;[|&lt;string&gt;]</code></a>
<br />unit of measurement for this channel [|unit used in state reading]. </li>
&lt;string&gt;</code></a>
<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
&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>
<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>
</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>
</a>
<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>
</a>
<br />unit of measurement (temperature scale), default is Celsius = &deg;C </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a
href="#stateFormat">stateFormat</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
=end html

View File

@ -16,7 +16,7 @@
# where <name> may be replaced by any name string
#
# <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
# <ROM_ID> is a 12 character (6 byte) 1-Wire ROM ID
# 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
# 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)
# overwritten by an attribute setting "red angled arrow downward"
#
# attr <name> <channel>Name <string>|<string> = name for the channel [|name used in state reading]
# attr <name> stateS <string> = character string denoting external shortening condition, default is X
# attr <name> <channel>Name <string>|<string> = name for the channel [|short name used in state reading]
# 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($$);
my $owx_version="5.24";
my $owx_version="6.0";
#-- fixed raw channel name, flexible channel name
my @owg_fixed = ("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
#
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed
#
########################################################################################
@ -148,7 +144,7 @@ sub OWSWITCH_Initialize ($) {
$hash->{InitFn} = "OWSWITCH_Init";
$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 ".
$readingFnAttributes;
@ -172,8 +168,6 @@ sub OWSWITCH_Initialize ($) {
#
# OWSWITCH_Define - Implements DefFn function
#
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed, def = definition string
#
#########################################################################################
@ -280,8 +274,6 @@ sub OWSWITCH_Define ($$) {
#
# OWSWITCH_Notify - Implements Notify function
#
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed, def = definition string
#
#########################################################################################
@ -298,8 +290,6 @@ sub OWSWITCH_Notify ($$) {
#
# OWSWITCH_Init - Implements Init function
#
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed, def = definition string
#
#########################################################################################
@ -316,8 +306,6 @@ sub OWSWITCH_Init ($) {
#
# OWSWITCH_Attr - Set one attribute value for device
#
# CalledBy: FHEM
# Calling: --
# Parameter: hash = hash of device addressed
# a = argument array
#
@ -362,8 +350,6 @@ sub OWSWITCH_Attr(@) {
#
# OWSWITCH_ChannelNames - find the real channel names
#
# CalledBy: OWSWITCH_FormatValues, OWSWITCH_Get, OWSWITCH_Set
# Calling: --
# Parameter: hash = hash of device addressed
#
########################################################################################
@ -378,7 +364,7 @@ sub OWSWITCH_ChannelNames($) {
for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){
#-- 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);
if( int(@cnama)!=2){
push(@cnama,$cnama[0]);
@ -398,7 +384,6 @@ sub OWSWITCH_ChannelNames($) {
#-- put into readings
$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
#
# CalledBy: OWSWITCH_Get, OWSWITCH_Set
# Calling: --
# Parameter; hash = hash of device addressed, fs = format string
#
########################################################################################
@ -420,7 +403,9 @@ sub OWSWITCH_FormatValues($) {
my $svalue = "";
#-- 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
OWSWITCH_ChannelNames($hash);
@ -466,10 +451,6 @@ sub OWSWITCH_FormatValues($) {
#
# 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
#
########################################################################################
@ -480,6 +461,7 @@ sub OWSWITCH_Get($@) {
my $reading = $a[1];
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my ($value,$value2,$value3) = (undef,undef,undef);
my $ret = "";
my ($offset,$factor,$page,$cname,@cnama,@channel);
@ -550,7 +532,7 @@ sub OWSWITCH_Get($@) {
#-- OWX interface
if( $interface eq "OWX" ){
$ret = OWXSWITCH_GetState($hash);
OWXSWITCH_GetModState($hash,undef,undef);
}elsif( $interface eq "OWX_ASYNC") {
eval {
$ret = OWX_ASYNC_RunToCompletion($hash,OWXSWITCH_PT_GetState($hash));
@ -563,8 +545,12 @@ sub OWSWITCH_Get($@) {
}else{
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};
}
#-- get all states
}elsif( $reading eq "gpio" ){
@ -572,7 +558,7 @@ sub OWSWITCH_Get($@) {
if( int(@a)==1 );
if( $interface eq "OWX" ){
$ret = OWXSWITCH_GetState($hash);
$ret = OWXSWITCH_GetModState($hash,undef,undef);
}elsif( $interface eq "OWX_ASYNC" ){
eval {
$ret = OWX_ASYNC_RunToCompletion($hash,OWXSWITCH_PT_GetState($hash));
@ -584,12 +570,16 @@ sub OWSWITCH_Get($@) {
return "OWSWITCH: Get with wrong IODev type $interface";
}
#-- process results
if( $master->{ASYNCHRONOUS} ){
return "OWSWITCH: $name getting gpio, please wait for completion";
}else{
if( defined($ret) ){
return "OWSWITCH: Could not get values from device $name, reason $ret";
}
return "OWSWITCH: $name.$reading => ".$hash->{READINGS}{"state"}{VAL};
}
}
}
#######################################################################################
#
@ -620,7 +610,7 @@ sub OWSWITCH_GetValues($) {
if( $interface eq "OWX" ){
#-- max 3 tries
for(my $try=0; $try<3; $try++){
$ret = OWXSWITCH_GetState($hash);
$ret = OWXSWITCH_GetModState($hash,undef,undef);
return if( !defined($ret) );
}
}elsif( $interface eq "OWX_ASYNC" ){
@ -652,6 +642,7 @@ sub OWSWITCH_GetValues($) {
########################################################################################
#
# OWSWITCH_InitializeDevice - initial readings
#
# Parameter hash = hash of device addressed
#
########################################################################################
@ -738,24 +729,24 @@ sub OWSWITCH_Set($@) {
return "OWSWITCH: Set needs parameter when writing output: <channel>"
if( int(@a)<2 );
#-- find out which channel we have
my $fnd=undef;
my $outfnd=undef;
for (my $i=0;$i<$cnumber{$attr{$name}{"model"}};$i++){
if( ($a[2] eq $owg_channel[$i]) || ($a[2] eq $owg_fixed[$i]) ){
$fnd=$i;
$outfnd=$i;
last;
}
}
return "OWSWITCH: Invalid output address, must be A,B,... or defined channel name"
if( !defined($fnd) );
if( !defined($outfnd) );
#-- prepare gpio value
my $nval;
my $outval;
my $ntim;
my $nstr="";
if( lc($a[3]) eq "on" ){
$nval = 0;
$outval = 0;
}elsif( lc($a[3]) eq "off" ){
$nval = 1;
$outval = 1;
}elsif( lc($a[3]) =~ m/for-timer/ ){
if( !($a[4] =~ m/\d\d\:\d\d\:\d\d/) ){
if( !($a[4] =~ m/\d{1,4}/ )){
@ -767,10 +758,10 @@ sub OWSWITCH_Set($@) {
$ntim= $a[4];
}
if( lc($a[3]) eq "on-for-timer" ){
$nval = 0;
$outval = 0;
$nstr = "$a[0] $a[1] $a[2] off";
}elsif( lc($a[3]) eq "off-for-timer" ){
$nval = 1;
$outval = 1;
$nstr = "$a[0] $a[1] $a[2] on";
}
}else{
@ -778,36 +769,31 @@ sub OWSWITCH_Set($@) {
}
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
if( $interface eq "OWX" ){
$ret1 = OWXSWITCH_GetState($hash);
$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);
$ret1 = OWXSWITCH_GetModState($hash,$outfnd,$outval);
}elsif( $interface eq "OWX_ASYNC"){
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 $@;
#-- OWFS interface
}elsif( $interface eq "OWServer" ){
$ret1 = OWFSSWITCH_GetState($hash);
$value = 0;
#-- vax or val ?
my $gpio = 0;
#--
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 );
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 );
}
}
$ret2 = OWFSSWITCH_SetState($hash,$value);
#-- Unknown interface
@ -848,7 +834,7 @@ sub OWSWITCH_Set($@) {
}
#-- process results - we have to reread the device
OWSWITCH_GetValues($hash);
#OWSWITCH_GetValues($hash);
Log 4, "OWSWITCH: Set $hash->{NAME} $key $value";
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
# 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($$$$$$$$) {
my ($hash, $context, $success, $reset, $owx_dev, $command, $numread, $res) = @_;
sub OWXSWITCH_BinValues($$$$$$$) {
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
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
# val = input value, vax = output value
#-- 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 -------------------------------------------------------
if( ($context eq "getstate.ds2406") or ($context eq "ds2406.getstate") ) {
if( $chip eq "ds2406" ) {
@data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 4 bytes"
if (@data != 4);
return "invalid CRC"
if ( OWX_CRC16($command.substr($res,0,2),$data[2],$data[3]) == 0);
$hash->{owg_val}->[0] = (ord($data[0])>>2) & 1;
$hash->{owg_vax}->[0] = ord($data[0]) & 1;
$hash->{owg_val}->[1] = (ord($data[0])>>3) & 1;
$hash->{owg_vax}->[1] = (ord($data[0])>>1) & 1;
if (@data != 4){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 4 bytes, ";
}elsif(OWX_CRC16($crcpart.substr($res,0,2),$data[2],$data[3]) == 0){
$msg="Error - state could not be set for device $name, invalid CRC, ";
}else{
$msg="No error, ";
$value=ord($data[0]);
$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 -------------------------------------------------------
}elsif( ($context eq "getstate.ds2408") or ($context eq "ds2408.getstate") ) {
}elsif( $chip eq "ds2408" ) {
@data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 10 bytes"
if (@data != 10);
return "invalid data"
if (ord($data[6])!=255);
return "invalid CRC"
if( OWX_CRC16($command.substr($res,0,8),$data[8],$data[9]) == 0);
if (@data != 10){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 10 bytes, ";
}elsif(ord($data[6])!=255){
$msg="Error - $name returns invalid data, ";
}elsif(OWX_CRC16($crcpart.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++){
$hash->{owg_val}->[$i] = (ord($data[0])>>$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 -------------------------------------------------------
}elsif( ($context eq "getstate.ds2413") or ($context eq "ds2413.getstate") ){
}elsif( $chip eq "ds2413" ){
@data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 2 bytes"
if (@data != 2);
return "invalid data"
if ( (15- (ord($data[0])>>4)) != (ord($data[0]) & 15) );
if (@data != 2){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 2 bytes, ";
}elsif((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_vax}->[0] = (ord($data[0])>>1) & 1;
$hash->{owg_val}->[1] = (ord($data[0])>>2) & 1;
$hash->{owg_vax}->[1] = (ord($data[0])>>3) & 1;
}
OWX_WDBG($name,"OWXSWITCH_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
#--
}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
}elsif ( $context =~ /.*setstate.*/){
}elsif ( $context =~ /^(......)\.setstate\.?(\d+)?\.?(\d+)?/){
$chip = $1;
$value = $2;
#-- family = 12 => DS2406 -------------------------------------------------------
if( ($context =~ /setstate\.ds2406\..*/) or ($context =~ /ds2406\.setstate\..*/) ) {
$value = substr($context,-1);
if( $chip eq "ds2406" ) {
@data=split(//,$res);
return "state could not be set for device $owx_dev"
if( int(@data) != 2);
return "invalid CRC"
if (OWX_CRC16($command,$data[0],$data[1]) == 0);
#-- put into local buffer]";
$hash->{owg_val}->[0] = $value % 2;
$hash->{owg_vax}->[0] = $value % 2;
$hash->{owg_val}->[1] = int($value / 2);
$hash->{owg_vax}->[1] = int($value / 2);
if (@data != 2){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 2 bytes, ";
}elsif(OWX_CRC16($crcpart,$data[0],$data[1]) == 0){
$msg="Error - state could not be set for device $name, invalid CRC, ";
}else{
$msg="No error, ";
$outval = $value % 2;
$hash->{owg_vax}->[0] = $outval;
$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 -------------------------------------------------------
}elsif( ($context eq "setstate.ds2408") or ($context eq "ds2408.setstate") ) {
@data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 1 bytes"
if (@data != 1);
return "state could not be set for device $owx_dev"
if( $data[0] ne "\xAA");
}elsif( $chip eq "ds2408" ) {
if (length($res)!=1){
$msg="Error - $name returns invalid data length, ".length($res)." instead of 1 bytes, ";
}elsif($res ne "\xAA"){
$msg="Error - state could not be set for device $name, ";
}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 -------------------------------------------------------
}elsif( ($context eq "setstate.ds2413") or ($context eq "ds2413.setstate") ){
}elsif( $chip eq "ds2413" ){
@data=split(//,$res);
return "invalid data length, ".int(@data)." instead of 1 bytes"
if (@data != 1);
return "state could not be set for device $owx_dev"
if( $data[0] ne "\xAA");
if (@data != 2){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 2 bytes, ";
}elsif( $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{
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{
return "unknown context in OWXSWITCH_BinValues";
die "OWSWITCH: unknown context $context in OWXSWITCH_BinValues";
}
#-- and now from raw to formatted values
$hash->{PRESENT} = 1;
$value = OWSWITCH_FormatValues($hash);
Log 5, $value;
return undef;
}
########################################################################################
#
# OWXSWITCH_GetState - Get gpio ports from device
# OWXSWITCH_GetModState - Get gpio ports from device and overwrite
#
# Parameter hash = hash of device addressed
# mod = if 1, overwrite state with new data
#
########################################################################################
sub OWXSWITCH_GetState($@) {
my ($hash,$sync) = @_;
sub OWXSWITCH_GetModState($$$) {
my ($hash,$outfnd,$outval) = @_;
my ($select, $res, @data);
@ -1137,11 +1215,23 @@ sub OWXSWITCH_GetState($@) {
#-- hash of the busmaster
my $master = $hash->{IODev};
my $name = $hash->{NAME};
#-- reset presence
$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
if( $hash->{OW_FAMILY} eq "12" ) {
@ -1150,45 +1240,78 @@ sub OWXSWITCH_GetState($@) {
# \xF5 plus the two byte channel control and the value
#-- reading 9 + 3 + 2 data bytes + 2 CRC bytes = 16 bytes
$select=sprintf("\xF5\xDD\xFF");
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
$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 );
return "$owx_dev has returned invalid data"
return "OWSWITCH: $name has returned invalid data"
if( length($res)!=16);
OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2406.getstate",1,undef,$owx_dev,substr($res,9,3),undef,substr($res,12));
#OWX_Reset($master);
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
}elsif( $hash->{OW_FAMILY} eq "29" ) {
#=============== 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
#-- reading 9 + 3 + 8 data bytes + 2 CRC bytes = 22 bytes
$select=sprintf("\xF0\x88\x00");
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
$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 );
return "$owx_dev has returned invalid data"
return "OWSWITCH: $name has returned invalid data"
if( length($res)!=22);
OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2408.getstate",1,undef,$owx_dev,substr($res,9,3),undef,substr($res,12));
#OWX_Reset($master);
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
}elsif( $hash->{OW_FAMILY} eq "3A" ) {
#=============== get gpio values ===============================
#-- issue the match ROM command \x55 and the read gpio command
# \xF5 plus 2 empty bytes
#-- reading 9 + 1 + 2 data bytes = 12 bytes
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
$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 );
return "$owx_dev has returned invalid data"
return "OWSWITCH: $name has returned invalid data"
if( length($res)!=12);
#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{
return "unknown device family $hash->{OW_FAMILY}\n";
#### 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 {
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
#
# 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 ($select, $res, $res2, @data);
#-- ID of the device
@ -1216,8 +1338,6 @@ sub OWXSWITCH_SetState($$) {
#-- hash of the busmaster
my $master = $hash->{IODev};
my ($i,$j,$k);
#-- family = 12 => DS2406
if( $hash->{OW_FAMILY} eq "12" ) {
#=============== set gpio values ===============================
@ -1240,42 +1360,66 @@ sub OWXSWITCH_SetState($$) {
# \x55 at address TA1 = \x07 TA2 = \x00
#-- reading 9 + 4 + 2 data bytes = 15 bytes
$select=sprintf("\x55\x07\x00%c",$statneu);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,2);
if( $res eq 0 ){
return "device $owx_dev not accessible in writing";
}
OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2406.setstate.$value",1,undef,$owx_dev,substr($res,9,4),undef,substr($res,13));
return;
#OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2406.setstate.$value",0,$owx_dev,$select,2,substr($res,13));
#-- 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
} elsif( $hash->{OW_FAMILY} eq "29" ) {
#=============== set gpio values ===============================
#-- issue the match ROM command \x55 and the write gpio command
# \x5A plus the value byte and its complement
$select=sprintf("\x5A%c%c",$value,255-$value);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,1);
if( $res eq 0 ){
return "device $owx_dev not accessible in writing";
}
OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2408.setstate",1,undef,$owx_dev,undef,undef,substr($res,12));
return;
return OWXSWITCH_BinValues($hash,"ds2408.setstate.$value",0,$owx_dev,0,1,substr($res,12));
#-- 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
} elsif( $hash->{OW_FAMILY} eq "3A" ) {
#=============== set gpio values ===============================
#-- issue the match ROM command \x55 and the write gpio command
# \x5A plus the value byte and its complement
$select=sprintf("\x5A%c%c",252+$value,3-$value);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,1);
if( $res eq 0 ){
return "device $owx_dev not accessible in writing";
}
OWX_Reset($master);
return OWXSWITCH_BinValues($hash,"ds2413.setstate",1,undef,$owx_dev,undef,undef,substr($res,12));
return;
return OWXSWITCH_BinValues($hash,"ds2413.setstate",0,$owx_dev,0,2,substr($res,12));
#-- 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 {
return "unknown device family $hash->{OW_FAMILY}\n";
}
@ -1322,7 +1466,7 @@ sub OWXSWITCH_PT_GetState($) {
unless (length($response) == 4) {
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) {
PT_EXIT($ret);
}
@ -1340,7 +1484,7 @@ sub OWXSWITCH_PT_GetState($) {
unless (length($response) == 10) {
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) {
PT_EXIT($ret);
}
@ -1358,7 +1502,7 @@ sub OWXSWITCH_PT_GetState($) {
unless (length($response) == 2) {
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) {
PT_EXIT($ret);
}
@ -1534,7 +1678,7 @@ sub OWXSWITCH_PT_SetOutput($$$) {
<p>
<code>define OWX_S OWSWITCH DS2413 B5D502000000 60</code>
<br />
<code>attr OWX_S AName Lampe|light</code>
<code>attr OWX_S AName light-a|la</code>
<br />
<code>attr OWX_S AUnit AN|AUS</code>
</p>
@ -1597,7 +1741,7 @@ sub OWXSWITCH_PT_SetOutput($$$) {
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owswitch_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval in
<code>get &lt;name&gt; interval</code></a><br />Measurement interval in
seconds. </li>
<li><a name="owswitch_input">
<code>get &lt;name&gt; input &lt;channel-name&gt;</code></a><br /> state for
@ -1605,7 +1749,7 @@ sub OWXSWITCH_PT_SetOutput($$$) {
not necessarily the one set as output state, because the output transistors are open
collector switches. A measured state of 1 = OFF therefore corresponds to an output
state of 1 = OFF, but a measured state of 0 = ON can also be due to an external
shortening of the output.</li>
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">
<code>get &lt;name&gt; gpio</code></a><br />Obtain state of all channels</li>
</ul>
@ -1613,19 +1757,14 @@ sub OWXSWITCH_PT_SetOutput($$$) {
<h4>Attributes</h4> For each of the following attributes, the channel identification A,B,...
may be used. <ul>
<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
&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
&lt;string&gt;|&lt;string&gt;</code></a>
<br />display for on | off condition </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a
href="#stateFormat">stateFormat</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
=end html

View File

@ -35,8 +35,8 @@
#
# Additional attributes are defined in fhem.cfg
#
# attr <name> stateAL "<string>" = character string for denoting low alarm condition, default is down triangle
# attr <name> stateAH "<string>" = character string for denoting high alarm condition, default is up triangle
# attr <name> stateAL "<string>" = character string for denoting low alarm condition, default is
# 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> 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"
@ -86,7 +86,7 @@ no warnings 'deprecated';
sub Log3($$$);
sub AttrVal($$$);
my $owx_version="5.28";
my $owx_version="6.0";
my %gets = (
"id" => "",
@ -141,7 +141,7 @@ sub OWTHERM_Initialize ($) {
$hash->{NotifyFn}= "OWTHERM_Notify";
$hash->{InitFn} = "OWTHERM_Init";
$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 ".
"tempOffset tempUnit:Celsius,Fahrenheit,Kelvin ".
"tempConv:onkick,onread tempLow tempHigh ".
@ -264,6 +264,16 @@ sub OWTHERM_Define ($$) {
return undef;
}
#######################################################################################
#
# OWTHERM_Notify - Implements the Notify function
#
# Parameter hash = hash of device addressed
# a = argument array
#
########################################################################################
sub OWTHERM_Notify ($$) {
my ($hash,$dev) = @_;
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 ($) {
my ($hash)=@_;
#-- Start timer for updates
@ -355,13 +375,15 @@ sub OWTHERM_FormatValues($) {
my $svalue = "";
#-- attributes defined ?
$stateal = AttrVal($name,"stateAL","&#x25BE;");
$stateah = AttrVal($name,"stateAH","&#x25B4;");
$stateal = AttrVal($name,"stateAL","");
$stateah = AttrVal($name,"stateAH","");
$unit = AttrVal($name,"tempUnit","Celsius");
$offset = AttrVal($name,"tempOffset",0.0);
$factor = 1.0;
if( $unit eq "Celsius" ){
if( $unit eq "none" ){
$abbr = "";
}elsif( $unit eq "Celsius" ){
$abbr = " °C";
} elsif ($unit eq "Kelvin" ){
$abbr = " K";
@ -375,8 +397,7 @@ sub OWTHERM_FormatValues($) {
Log3 $name, 3, "OWTHERM_FormatValues: Unknown temperature unit $unit";
}
#-- these values are rather complex to obtain, therefore save them in the hash
$hash->{READINGS}{"temperature"}{UNIT} = $unit;
$hash->{READINGS}{"temperature"}{UNITABBR} = $abbr;
$hash->{READINGS}{"temperature"}{UNIT} = $abbr;
$hash->{tempf}{offset} = $offset;
$hash->{tempf}{factor} = $factor;
@ -431,6 +452,7 @@ sub OWTHERM_Get($@) {
my $reading = $a[1];
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my $value = undef;
my $ret = "";
@ -450,6 +472,7 @@ sub OWTHERM_Get($@) {
#-- hash of the busmaster
my $master = $hash->{IODev};
#-- Get other values according to interface type
my $interface= $hash->{IODev}->{TYPE};
@ -503,10 +526,13 @@ sub OWTHERM_Get($@) {
}
#-- 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) ){
return "OWTHERM: Could not get values from device $name, return was $ret";
}
#-- return the special reading
if ($reading eq "temperature") {
return "OWTHERM: $name.temperature => ".
@ -514,9 +540,11 @@ sub OWTHERM_Get($@) {
} elsif ($reading eq "alarm") {
return "OWTHERM: $name.alarm => L ".$main::attr{$name}{"tempLow"}.
" H ".$main::attr{$name}{"tempHigh"};
}
} else {
return undef;
}
}
}
#######################################################################################
#
@ -616,8 +644,7 @@ sub OWTHERM_InitializeDevice($) {
}
#-- these values are rather complex to obtain, therefore save them in the hash
$hash->{READINGS}{"temperature"}{TYPE} = "temperature";
$hash->{READINGS}{"temperature"}{UNIT} = $unit;
$hash->{READINGS}{"temperature"}{UNITABBR} = $abbr;
$hash->{READINGS}{"temperature"}{UNIT} = $abbr;
$hash->{ERRCOUNT} = 0;
$hash->{tempf}{offset} = $offset;
$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
# 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($$$$$$) {
my ($hash, $reset, $owx_dev, $command, $numread, $res) = @_;
#Log3 $name, 1,"OWXTHERM_BinValues context = $context";
sub OWXTHERM_BinValues($$$$$$$) {
my ($hash, $context, $reset, $owx_dev, $crcpart, $numread, $res) = @_;
my ($i,$j,$k,@data,$ow_thn,$ow_tln);
my $change = 0;
#Log3 $name, 1,"OWXTHERM: data length from reading device is ".length($res)." bytes";
#-- process results
die "$owx_dev not accessible in 2nd step" unless ( defined $res and $res ne 0 );
my $name = $hash->{NAME};
my $msg;
OWX_WDBG($name,"OWTHERM_BinValues called for device $name with ",$res)
if( $main::owx_debug>2 );
#-- process results
@data=split(//,$res);
die "invalid data length, ".int(@data)." instead of 9 bytes"
if (@data != 9);
die "invalid data"
if (ord($data[7])<=0);
die "invalid CRC"
if (OWX_CRC8(substr($res,0,8),$data[8])==0);
if (@data != 9){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 9 bytes, ";
}elsif(ord($data[7])<=0){
$msg="Error - $name returns invalid data, ";
}elsif(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
# family = 10 => DS1820, DS18S20
@ -967,7 +1015,7 @@ sub OWXTHERM_BinValues($$$$$$) {
$ow_tln = ord($data[3]) > 127 ? 128-ord($data[3]) : ord($data[3]);
} else {
die "OWXTHERM: Unknown device family $hash->{OW_FAMILY}\n";
die "OWTHERM: $name: Unknown device family $hash->{OW_FAMILY}\n";
}
#-- process alarm settings
@ -977,7 +1025,6 @@ sub OWXTHERM_BinValues($$$$$$) {
#-- and now from raw to formatted values
$hash->{PRESENT} = 1;
my $value = OWTHERM_FormatValues($hash);
Log3 $hash->{NAME}, 5, $value;
return undef;
}
@ -1003,34 +1050,50 @@ sub OWXTHERM_GetValues($) {
my $master = $hash->{IODev};
my $name = $hash->{NAME};
my $res;
#-- check, if the conversion has been called before for all sensors
if( defined($attr{$name}{tempConv}) && ( $attr{$name}{tempConv} eq "onkick") ){
$con=0;
}
#-- if the conversion has not been called before
if( $con==1 ){
#-- 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);
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);
#-- 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
#-- issue the match ROM command \x55 and the read scratchpad command \xBE
#-- reading 9 + 1 + 8 data bytes and 1 CRC byte = 19 bytes
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
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 );
return "$owx_dev has returned invalid data"
return "OWTHERM: $name has returned invalid data"
if( length($res)!=19);
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;
#-- 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($$) {
my ($hash, $args) = @_;
my ($i,$j,$k);
my $name = $hash->{NAME};
#-- 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
my $select=sprintf("\x4E%c%c%c",$thp,$tlp,$cfg);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
my $res=OWX_Complex($master,$owx_dev,$select,3);
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;
}
@ -1137,7 +1204,7 @@ sub OWXTHERM_PT_GetValues($) {
$thread->{pt_execute} = OWX_ASYNC_PT_Execute($master,1,$owx_dev,"\xBE",9);
PT_WAIT_THREAD($thread->{pt_execute});
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;
});
}
@ -1299,12 +1366,10 @@ sub OWXTHERM_PT_SetValues($$) {
<ul>
<li><a name="owtherm_stateAL"><code>attr &lt;name&gt; stateAL &lt;string&gt;</code>
</a>
<br />character string for denoting low alarm condition, default is down triangle,
e.g. the code &amp;#x25BE; leading to the sign &#x25BE; </li>
<br />character string for denoting low alarm condition, default is ↓</li>
<li><a name="owtherm_stateAH"><code>attr &lt;name&gt; stateAH &lt;string&gt;</code>
</a>
<br />character string for denoting high alarm condition, default is upward
triangle, e.g. the code &amp;#x25B4; leading to the sign &#x25B4; </li>
<br />character string for denoting high alarm condition, default is ↑</li>
<li><a name="owtherm_tempConv">
<code>attr &lt;name&gt; tempConv onkick|onread</code>
</a>
@ -1315,9 +1380,9 @@ sub OWXTHERM_PT_SetValues($$) {
</a>
<br />temperature offset in °C added to the raw temperature reading. </li>
<li><a name="owtherm_tempUnit"><code>attr &lt;name&gt; tempUnit
Celsius|Kelvin|Fahrenheit</code>
none|Celsius|Kelvin|Fahrenheit</code>
</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">
<code>attr &lt;name&gt; resolution 9|10|11|12</code></a><br /> Temperature
resolution in bit, only relevant for DS18B20 </li>
@ -1336,13 +1401,7 @@ sub OWXTHERM_PT_SetValues($$) {
</a>
<br /> low alarm temperature (on the temperature scale chosen by the attribute
value). </li>
<li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
href="#event-on-update-reading">event-on-update-reading</a>, <a
href="#event-on-change-reading">event-on-change-reading</a>, <a
href="#stateFormat">stateFormat</a>, <a href="#room"
>room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
<a href="#webCmd">webCmd</a></li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
=end html