2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-08 13:24:56 +00:00

21_OWAD.pm: Neue Version, angepasst an OWX Next Generation

21_OWCOUNT.pm: Neue Version, angepasst an OWX Next Generation

git-svn-id: https://svn.fhem.de/fhem/trunk@14719 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
phenning 2017-07-15 03:27:23 +00:00
parent 6c5ab80311
commit cb831673b8
2 changed files with 256 additions and 395 deletions

View File

@ -10,44 +10,6 @@
# $Id$
#
########################################################################################
#
# define <name> OWAD [<model>] <ROM_ID> [interval] or or OWAD <FAM_ID>.<ROM_ID> [interval]
#
# where <name> may be replaced by any name string
#
# <model> is a 1-Wire device type. If omitted, we assume this to be an
# DS2450 A/D converter
# <FAM_ID> is a 1-Wire family id, currently allowed value is 20
# <ROM_ID> is a 12 character (6 byte) 1-Wire ROM ID
# without Family ID, e.g. A2D90D000800
# [interval] is an optional query interval in seconds
#
# get <name> id => FAM_ID.ROM_ID.CRC
# get <name> present => 1 if device present, 0 if not
# get <name> interval => query interval
# get <name> reading => measurement for all channels
# get <name> alarm => alarm measurement settings for all channels
# get <name> status => alarm and i/o status for all channels
# get <name> version => OWX version number
#
# set <name> interval => set period for measurement
#
# Additional attributes are defined in fhem.cfg, in some cases per channel, where <channel>=A,B,C,D
#
# 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 ↓
# 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> = 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 function) for low alarm
# attr <name> <channel>High <float> = measurement value (on the scale determined by function) for high alarm
#
########################################################################################
#
# This programm is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -86,7 +48,7 @@ use ProtoThreads;
no warnings 'deprecated';
sub Log3($$$);
my $owx_version="6.1";
my $owx_version="7.0";
#-- fixed raw channel name, flexible channel name
my @owg_fixed = ("A","B","C","D");
my @owg_channel = ("A","B","C","D");
@ -99,8 +61,6 @@ my @owg_range;
my %gets = (
"id" => "",
"present" => "",
"interval" => "",
"reading" => "",
"alarm" => "",
"status" => "",
@ -332,9 +292,9 @@ sub OWAD_Attr(@) {
#-- interval modified at runtime
$key eq "interval" and do {
#-- check value
return "OWAD: Set with short interval, must be > 1" if(int($value) < 1);
return "OWAD: set $name interval, must be >= 0" if(int($value) < 0);
#-- update timer
$hash->{INTERVAL} = $value;
$hash->{INTERVAL} = int($value);
if ($init_done) {
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 0);
@ -436,7 +396,6 @@ sub OWAD_FormatValues($) {
my $galarm = 0;
my $achange = 0;
my $schange = 0;
$hash->{ALARM} = 0;
#-- alarm signatures
my $stateal1 = defined($attr{$name}{stateAL1}) ? $attr{$name}{stateAL1} : "↓";
@ -541,8 +500,10 @@ sub OWAD_FormatValues($) {
#-- STATE
readingsBulkUpdate($hash,"state",$svalue);
readingsEndUpdate($hash,1);
$hash->{ALARM} = 1
if( $galarm == 1);
if( $galarm != $hash->{ALARM} ){
$hash->{ALARM} = $galarm;
main::OWX_Alarms($hash->{IODev});
}
return $svalue;
}
@ -582,35 +543,11 @@ sub OWAD_Get($@) {
return "$name.id => $value";
}
#-- get present
if($a[1] eq "present") {
#-- asynchronous mode
if( $hash->{ASYNC} ){
my ($task,$task_state);
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
if($a[1] eq "interval") {
$value = $hash->{INTERVAL};
return "$name.interval => $value";
}
#-- get version
if( $a[1] eq "version") {
return "$name.version => $owx_version";
}
#-- get reading according to interface type
if($a[1] eq "reading") {
#-- OWX interface
@ -631,18 +568,16 @@ sub OWAD_Get($@) {
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWAD: $name getting reading, please wait for completion";
return undef;
}else{
if( defined($ret) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){
$hash->{INTERVAL} = 9999;
}
return "OWAD: Could not get values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
return "OWAD: Could not get reading from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
}
return "OWAD: $name.reading => ".$hash->{READINGS}{"state"}{VAL};
}
}
#-- get alarm values according to interface type
if($a[1] eq "alarm") {
#-- OWX interface
@ -663,14 +598,11 @@ sub OWAD_Get($@) {
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWAD: $name getting alarm values, please wait for completion";
return undef;
}else{
if( defined($ret) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){
$hash->{INTERVAL} = 9999;
}
return "OWAD: Could not get values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
return "OWAD: Could not get alarm values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
}
#-- assemble ouput string
@ -704,13 +636,11 @@ sub OWAD_Get($@) {
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWAD: $name getting status, please wait for completion";
#return "OWAD: $name getting status, please wait for completion";
return undef;
}else{
if( defined($ret) ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
if( $hash->{ERRCOUNT} > 5 ){
$hash->{INTERVAL} = 9999;
}
return "OWAD: Could not get values from device $name for ".$hash->{ERRCOUNT}." times, reason $ret";
}
@ -772,18 +702,18 @@ sub OWAD_GetValues($) {
my $warn = "none";
$hash->{ALARM} = "0";
#-- restart timer for updates
RemoveInternalTimer($hash);
RemoveInternalTimer($hash);
#-- auto-update for device disabled;
return undef
if( $hash->{INTERVAL} == 0 );
#-- restart timer for updates
InternalTimer(time()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 0);
#-- Get readings, alarms and stati according to interface type
#-- Get readings, alarms and status according to interface type
if( $interface eq "OWX" ){
#-- max 3 tries
#for(my $try=0; $try<3; $try++){
$ret1 = OWXAD_GetPage($hash,"reading",0);
$ret2 = OWXAD_GetPage($hash,"alarm",0);
$ret3 = OWXAD_GetPage($hash,"status",1);
#}
$ret1 = OWXAD_GetPage($hash,"reading",0);
$ret2 = OWXAD_GetPage($hash,"alarm",0);
$ret3 = OWXAD_GetPage($hash,"status",1);
}elsif( $interface eq "OWX_ASYNC" ){
eval {
OWX_ASYNC_Schedule( $hash, OWXAD_PT_GetPage($hash,"reading",0));
@ -807,7 +737,7 @@ sub OWAD_GetValues($) {
$ret .= $ret3
if( defined($ret3) );
if( $ret ne "" ){
return "OWAD: Could not get values from device $name, reason $ret";
return "OWAD: Could not get reading, alarm and status values from device $name, reason $ret";
}
return undef;
@ -944,17 +874,17 @@ sub OWAD_Set($@) {
#-- re-intialize
if($key eq "initialize") {
OWAD_Initialize($hash);
OWAD_InitializeDevice($hash);
return undef;
}
#-- set new timer interval
if($key eq "interval") {
# check value
return "OWAD: Set with short interval, must be > 1"
if(int($value) < 1);
return "OWAD: set $name interval must be >= 0"
if(int($value) < 0);
# update timer
$hash->{INTERVAL} = $value;
$hash->{INTERVAL} = int($value);
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWAD_GetValues", $hash, 0);
return undef;
@ -1239,7 +1169,7 @@ sub OWFSAD_GetPage($$$) {
}
#-- and now from raw to formatted values
$hash->{PRESENT} = 1;
if( $final==1){
if( $final==1 ){
my $value = OWAD_FormatValues($hash);
Log 5, $value;
}
@ -1335,26 +1265,36 @@ sub OWXAD_BinValues($$$$$$$) {
#-- hash of the busmaster
my $master = $hash->{IODev};
my $name = $hash->{NAME};
my @data=[];
my $error = 0;
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 );
OWX_WDBGL($name,4,"OWXAD_BinValues: called for device $name in context $context with data ",$res);
my $final = ($context =~ /\.final$/ );
my ($ow_thn,$ow_tln);
#-- process results
@data=split(//,$res);
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 ";
#-- we have to get rid of the first 12 bytes
if( length($res) == 22 ){
$res=substr($res,12);
}
OWX_WDBG($name,"OWXAD_BinValues: ".$msg,$crcpart)
if( $main::owx_debug>2 );
@data=split(//,$res);
$crcpart = $crcpart.substr($res,0,8);
#-- process results
if (int(@data) != 10){
$msg = "$name: invalid data length, ".int(@data)." instead of 10 bytes ";
$error = 1;
}elsif (OWX_CRC16($crcpart,$data[8],$data[9])==0){
$msg ="$name: invalid CRC ";
$error = 1;
}else{
$msg = "$name: no error ";
}
OWX_WDBGL($name,5-4*$error,"OWXAD_BinValues: context $context ".$msg,$res);
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1
if( $error );
#=============== get the voltage reading ===============================
if( $context =~ /^ds2450.getreading/ ){
@ -1424,7 +1364,7 @@ sub OWXAD_BinValues($$$$$$$) {
}
#-- and now from raw to formatted values
$hash->{PRESENT} = 1;
if( $final ){
if( ($final) && (!$error) ){
my $value = OWAD_FormatValues($hash);
}
return undef
@ -1458,14 +1398,21 @@ sub OWXAD_GetPage($$$@) {
#=============== get the voltage reading ===============================
if( $page eq "reading") {
#-- issue the match ROM command \x55 and the start conversion command
OWX_Reset($master);
$res= OWX_Complex($master,$owx_dev,"\x3C\x0F\x00\xFF\xFF",0);
if( $res eq 0 ){
return "not accessible for conversion";
}
#-- conversion needs some 5 ms per channel
select(undef,undef,undef,0.02);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
$res= OWX_Complex($master,$owx_dev,"\x3C\x0F\x00\xFF\xFF",0);
if( $res eq 0 ){
return "not accessible for conversion";
}
#-- conversion needs some 5 ms per channel
select(undef,undef,undef,0.02);
#-- 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, "convert", 4, $owx_dev, "\x3C\x0F\x00\xFF\xFF", 0, 0, undef, undef, 0.02);
}
#-- issue the match ROM command \x55 and the read conversion page command
# \xAA\x00\x00
$select="\xAA\x00\x00";
@ -1484,6 +1431,7 @@ sub OWXAD_GetPage($$$@) {
return "wrong memory page requested from $owx_dev";
}
my $context = "ds2450.get".$page.($final ? ".final" : "");
my $proc = ($final ? 1 : 0);
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
#-- reset the bus
@ -1495,12 +1443,13 @@ 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,substr($res,12,10));
return OWXAD_BinValues($hash,$context,$proc,$owx_dev,$select,10,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);
OWX_Qomplex($master, $hash, $context, 0, $owx_dev, $select, $select, 22, 0, \&OWXAD_BinValues, 0.01);
return undef;
}
}
@ -1536,8 +1485,6 @@ sub OWXAD_SetPage($$) {
$select .= sprintf "%c\xFF\xFF\xFF",int($hash->{owg_vhigh}->[$i]*256000/$owg_range[$i]);
}
#++Use of uninitialized value within @owg_vlow in multiplication at
#++/usr/share/fhem/FHEM/21_OWAD.pm line 1362.
#=============== set the status ===============================
} elsif ( $page eq "status" ) {
my ($sb1,$sb2)=(0,0);
@ -1579,8 +1526,8 @@ sub OWXAD_SetPage($$) {
}
#-- 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);
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "ds2450.set", 0, $owx_dev, $select, 0, 0, 0, undef, undef);
}
return undef;
}
@ -1786,7 +1733,7 @@ sub OWXAD_PT_SetPage($$) {
code </li>
<li>
<code>&lt;interval&gt;</code>
<br />Measurement interval in seconds. The default is 300 seconds. </li>
<br />Measurement interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update. </li>
</ul>
<br />
<a name="OWADset"></a>
@ -1794,7 +1741,7 @@ sub OWXAD_PT_SetPage($$) {
<ul>
<li><a name="owad_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds. </li>
interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update.</li>
</ul>
<br />
<a name="OWADget"></a>
@ -1803,13 +1750,6 @@ sub OWXAD_PT_SetPage($$) {
<li><a name="owad_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owad_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owad_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval in
seconds. </li>
<li><a name="owad_reading">
<code>get &lt;name&gt; reading</code></a><br />Obtain the measuement values. </li>
<li><a name="owad_alarm">
@ -1830,6 +1770,9 @@ sub OWXAD_PT_SetPage($$) {
<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 ↑</li>
<li><a name="owad_interval2">
<code>attr &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update.</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>

View File

@ -11,58 +11,6 @@
#
########################################################################################
#
# define <name> OWCOUNT [<model>] <ROM_ID> [interval] or OWCOUNT <FAM_ID>.<ROM_ID> [interval]
#
# where <name> may be replaced by any name string
#
# <model> is a 1-Wire device type DS2423,DS2423ene,wDS2423eold. If omitted, we assume this to be an
# DS2423 Counter/RAM
# <FAM_ID> is a 1-Wire family id, currently allowed value is 1D
# <ROM_ID> is a 12 character (6 byte) 1-Wire ROM ID
# without Family ID, e.g. A2D90D000800
# [interval] is an optional query interval in seconds
#
# get <name> id => FAM_ID.ROM_ID.CRC
# get <name> present => 1 if device present, 0 if not
# get <name> interval => query interval
# get <name> memory <page> => 32 byte string from page 0..13
# get <name> midnight <channel> => todays starting value (formatted) for counter
# get <name> month => summary and average for month
# get <name> year => summary and average for year
# get <name> raw <channel> => raw value for counter
# get <name> counters => formatted values for both counters
# get <name> version => OWX version number
#
# set <name> interval => set query interval for measurement
# set <name> memory <page> => 32 byte string into page 0..13
# set <name> midnight <channel> => todays starting value for counter
# set <name> counter <channel> => correct midnight value such that
# counter shows this value
#
# Additional attributes are defined in fhem.cfg, in some cases per channel, where <channel>=A,B
#
# 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 [|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
# attr <name> <channel>Period <string> = period for rate calculation = hour (default), minute or second
#
# In normal counting mode each returned counting value will be factor*(reading+offset)
# In daily counting mode each returned counting value will be factor*(reading+offset)-midnight
# where midnight is stored as string in the 32 byte memory associated with the counter
#
# Log Lines
# after each interval <date> <name> <channel>: <value> <unit> <value> / <unit>/<period> <channel>: <value> <unit> / <value> <unit>/<period>
# example: 2012-07-30_00:07:55 OWX_C Taste: 17.03 p 28.1 p/h B: 7.0 cts 0.0 cts/min
# after midnight <new date> <name> <old day> <old date> <channel>: <value> <unit> <channel>: <value> <unit>
# example: 2012-07-30_00:00:57 OWX_C D29: 2012-7-29_23:59:59 Taste: 110.0 p, B: 7.0 cts
########################################################################################
#
# This programm is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@ -99,7 +47,7 @@ no warnings 'deprecated';
sub Log3($$$);
my $owx_version="6.11";
my $owx_version="7.0";
#-- fixed raw channel name, flexible channel name
my @owg_fixed = ("A","B");
my @owg_channel = ("A","B");
@ -111,9 +59,7 @@ my $owgauto = 0;
my %gets = (
"id" => "",
"present" => "",
"interval" => "",
"mcache" => "",
"mcache" => "",
"memory" => "",
"midnight" => "",
"raw" => "",
@ -197,7 +143,7 @@ sub OWCOUNT_Define ($$) {
$interval = 300;
$scale = "";
$ret = "";
#-- check syntax
return "OWCOUNT: Wrong syntax, must be define <name> OWCOUNT [<model>] <id> [interval] or OWCOUNT <fam>.<id> [interval]"
if(int(@a) < 2 || int(@a) > 5);
@ -266,6 +212,7 @@ sub OWCOUNT_Define ($$) {
$hash->{ROM_ID} = "$fam.$id.$crc";
$hash->{OW_ID} = $id;
$hash->{OW_FAMILY} = $fam;
$hash->{ERRCOUNT} = 0;
$hash->{PRESENT} = 0;
$hash->{INTERVAL} = $interval;
@ -358,7 +305,7 @@ sub OWCOUNT_InitializeDevice($) {
$hash->{owg_midnight}->[$i] = "";
$hash->{owg_str}->[$i] = "";
}
$hash->{memory} = "";
$hash->{DATA}{memory} = "";
#-- Set state to initialized
readingsSingleUpdate($hash,"state","initialized",1);
@ -373,7 +320,7 @@ sub OWCOUNT_InitializeDevice($) {
# Parameter hash = hash of device addressed
# a = argument array
#
########################################################################################
#######################################################################################
sub OWCOUNT_Attr(@) {
my ($do,$name,$key,$value) = @_;
@ -386,9 +333,9 @@ sub OWCOUNT_Attr(@) {
#-- interval modified at runtime
$key eq "interval" and do {
#-- check value
return "OWCOUNT: Set with short interval, must be > 1" if(int($value) < 1);
return "OWCOUNT: set $name interval must be >= 0" if(int($value) < 0);
#-- update timer
$hash->{INTERVAL} = $value;
$hash->{INTERVAL} = int($value);
if ($init_done) {
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWCOUNT_GetValues", $hash, 0);
@ -513,7 +460,7 @@ sub OWCOUNT_FormatValues($) {
OWCOUNT_ChannelNames($hash);
#-- Check, whether we have a new day at the next reading
$deltim = $hour*60.0+$min+$sec/60.0 - (1440 - $hash->{INTERVAL}/60.0);
$deltim = $hour*60.0+$min+$sec/60.0 + $hash->{INTERVAL}/60.0 - 1440;
#$deltim = $min+$sec/60.0 - 55;
if( $deltim>=0 ){
$daybreak = 1;
@ -530,6 +477,7 @@ sub OWCOUNT_FormatValues($) {
readingsBeginUpdate($hash);
#-- Check memory string only if model is defined automatically
# TODO: REMOVE THIS TAKES TOO MUCH TIME IN FORMAT
if( $owgauto ){
my $msg = "OWCOUNT: In device $name, ";
if( $owg_memory[2]==1 ){
@ -620,9 +568,13 @@ sub OWCOUNT_FormatValues($) {
#--midnight extrapolation only possible if previous measurement
if( $daybreak==1 ){
#-- linear extrapolation
$dt = -$delf/$delt;
$dval = int(($vval+($vval-$oldval)*$dt)*10000+0.5)/10000;
if( $delt > 0.0 ){
$dt = -$delf/$delt;
$dval = int(($vval+($vval-$oldval)*$dt)*10000+0.5)/10000;
Log3 $name,5,"OWCOUNT: midnight exploration $name channel ".$owg_channel[$i]." with time delta $delt, dt $dt and dval=$dval";
}else{
Log3 $name,5,"OWCOUNT: midnight exploration $name channel ".$owg_channel[$i]." fails because of zero time delta. dval=$dval";
}
if( $daily == 1 ){
$dval2 = $dval+$hash->{owg_midnight}->[$i];
} else {
@ -630,10 +582,10 @@ sub OWCOUNT_FormatValues($) {
}
#-- in any mode store the interpolated value in the midnight store
my $msg = sprintf("%4d-%02d-%02d midnight %7.2f",
my $msg = sprintf("%4d-%02d-%02d midnight %7.2f ",
$year+1900,$month+1,$day,$dval2);
Log3 $name,5,"OWCOUNT: measured $name value $vval (midnight ".$hash->{owg_midnight}->[$i].") => extrapolated midnight $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);
@ -669,11 +621,11 @@ sub OWCOUNT_FormatValues($) {
$dvalue = sprintf($dvalue,$total0,$total1);
readingsBulkUpdate($hash,"day",$dvalue);
}else{
Log3 $name,3,"OWCOUNT: No monthly summary possible, ".$monthv[0]." for device $name";
Log3 $name,5,"OWCOUNT: No monthly summary possible, ".$monthv[0]." for device $name";
$total0 = 0;
$total1 = 0;
};
}
if( int(@yearv) == 2 ){
$total2 = $yearv[0]->[1];
$total3 = ($month==0)?$total2: $yearv[1]->[1];
@ -683,13 +635,13 @@ sub OWCOUNT_FormatValues($) {
readingsBulkUpdate($hash,"month",$mvalue);
}
}else{
Log3 $name,3,"OWCOUNT: No yearly summary possible, ".$yearv[0]." for device $name";
Log3 $name,5,"OWCOUNT: No yearly summary possible, ".$yearv[0]." for device $name";
$total2 = 0;
$total3 = 0;
};
}
}
#--- memory most recently read
readingsBulkUpdate($hash,"memory",$hash->{memory});
readingsBulkUpdate($hash,"memory",$hash->{DATA}{memory});
#-- STATE
readingsBulkUpdate($hash,"state",$svalue);
@ -720,11 +672,11 @@ sub OWCOUNT_Get($@) {
my ($ret1,$ret2);
#-- check syntax
return "OWCOUNT: Get argument is missing @a"
return "OWCOUNT: get $name argument is missing @a"
if(int(@a) < 2);
#-- check argument
return "OWCOUNT: Get with unknown argument $a[1], choose one of ".join(" ", sort keys %gets)
return "OWCOUNT: get $name with unknown argument $a[1], choose one of ".join(" ", sort keys %gets)
if(!defined($gets{$a[1]}));
#-- get id
@ -733,32 +685,6 @@ sub OWCOUNT_Get($@) {
return "$name.id => $value";
}
#-- get present
if($a[1] eq "present") {
#-- hash of the busmaster
my $master = $hash->{IODev};
#-- 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");
}
}
#-- get interval
if($a[1] eq "interval") {
$value = $hash->{INTERVAL};
return "$name.interval => $value";
}
#-- get version
if( $a[1] eq "version") {
return "$name.version => $owx_version";
@ -829,23 +755,24 @@ sub OWCOUNT_Get($@) {
#-- check syntax for getting memory page 0..13 or midnight A/B
my $nomemory = defined($attr{$name}{"nomemory"}) ? $attr{$name}{"nomemory"} : 0;
if( ($reading eq "memory") || ($reading eq "mcache") ){
return "OWCOUNT: Memory usage disabled"
return "OWCOUNT: Memory usage disabled in $name"
if( $nomemory==1 );
return "OWCOUNT: Get needs parameter when reading memory/mcache: <page>"
return "OWCOUNT: get $name memory/mcache: needs parameter <page>"
if( int(@a)<2 );
$page=int($a[2]);
if( ($page<0) || ($page>13) ){
return "OWCOUNT: Wrong memory/mcache page requested";
return "OWCOUNT: get $name memory/mcache requested wrong page $page";
}
if( $reading eq "memory" ){
$ret = OWCOUNT_GetPage($hash,$page,1,1);
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWCOUNT: $name getting memory $page, please wait for completion";
#return "OWCOUNT: $name getting memory $page, please wait for completion";
return undef;
}else{
#-- when we have a return code, we have an error
if( $ret ){
return "OWCOUNT: Could not get values from device $name, reason: ".$ret;
return "OWCOUNT: get $name failed, reason: ".$ret;
}else{
return "OWCOUNT: $name.$reading [$page] =>".$hash->{owg_str}->[$page];
}
@ -856,7 +783,7 @@ sub OWCOUNT_Get($@) {
}
#-- get midnight value
if( $reading eq "midnight" ){
return "OWCOUNT: get needs parameter when reading midnight: <channel>"
return "OWCOUNT: get $name midnight needs parameter <channel>"
if( int(@a)<3 );
#-- find out which channel we have
if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){
@ -864,16 +791,16 @@ sub OWCOUNT_Get($@) {
}elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){
$page=15;
} else {
return "OWCOUNT: Invalid midnight counter address, must be A, B or defined channel name"
return "OWCOUNT: get $name midnight has 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 midnight value $page and counter, please wait for completion";
return undef;
}else{
#-- when we have a return code, we have an error
if( $ret ){
return "OWCOUNT: Could not get values from device $name, reason: ".$ret;
return "OWCOUNT: get $name midnight failed, reason: ".$ret;
}else{
return "OWCOUNT: $name.$reading [$page] =>".$hash->{owg_midnight}->[$page-14];
}
@ -882,7 +809,7 @@ sub OWCOUNT_Get($@) {
#-- check syntax for getting counter
if( $reading eq "raw" ){
return "OWCOUNT: Get needs parameter when reading raw counter: <channel>"
return "OWCOUNT: get $name raw needs parameter <channel>"
if( int(@a)<2 );
#-- find out which channel we have
if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){
@ -890,36 +817,36 @@ sub OWCOUNT_Get($@) {
}elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){
$page=15;
} else {
return "OWCOUNT: Invalid counter address, must be A, B or defined channel name"
return "OWCOUNT: get $name raw has 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";
return undef;
}else{
#-- when we have a return code, we have an error
if( $ret ){
return "OWCOUNT: Could not get values from device $name, reason: ".$ret;
return "OWCOUNT: get $name raw failed, 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"
return "OWCOUNT: get $name counters needs no parameter"
if( int(@a)==1 );
$ret1 = OWCOUNT_GetPage($hash,14,0,1);
$ret2 = OWCOUNT_GetPage($hash,15,1,1);
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWCOUNT: $name getting counters, please wait for completion";
return undef;
}else{
$ret .= $ret1
if( defined($ret1) );
$ret .= $ret2
if( defined($ret2) );
if( defined($ret1) || defined($ret2) ){
return "OWCOUNT: Could not get values from device $name, reason: ".$ret;
return "OWCOUNT: get $name counters failed, reason: ".$ret;
}
#-- both counters will be returned
return "OWCOUNT: $name.counters => ".$hash->{READINGS}{"state"}{VAL};
@ -1201,8 +1128,11 @@ sub OWCOUNT_GetValues($) {
OWCOUNT_InitializeDevice($hash)
if( $hash->{READINGS}{"state"}{VAL} eq "defined");
#-- restart timer for updates
RemoveInternalTimer($hash);
RemoveInternalTimer($hash);
#-- auto-update for device disabled;
return undef
if( $hash->{INTERVAL} == 0 );
#-- restart timer for updates
InternalTimer(time()+$hash->{INTERVAL}, "OWCOUNT_GetValues", $hash, 0);
#-- Get readings
@ -1232,6 +1162,8 @@ sub OWCOUNT_GetValues($) {
sub OWCOUNT_ParseMidnight($$$) {
my ($hash,$strval,$page) = @_;
my $name = $hash->{NAME};
#-- midnight value
#-- new format
@ -1247,6 +1179,7 @@ sub OWCOUNT_ParseMidnight($$$) {
} else {
$strval = 0.0;
}
#Log 1,"============> Parsed $name midnight value $strval";
$hash->{owg_midnight}->[$page-14] = $strval;
}
@ -1262,8 +1195,14 @@ sub OWCOUNT_ParseMidnight($$$) {
sub OWCOUNT_Set($@) {
my ($hash, @a) = @_;
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my $ret = undef;
my $page;
my $data;
my $key = $a[1];
my $value = $a[2];
my ($cname,@cnama,@channel);
#-- for the selector: which values are possible
if (@a == 2){
@ -1272,28 +1211,20 @@ sub OWCOUNT_Set($@) {
}
#-- check syntax
return "OWCOUNT: Set needs at least one parameter"
return "OWCOUNT: set $name needs at least one parameter"
if( int(@a)<3 );
#-- check argument
if( !defined($sets{$a[1]}) ){
return "OWCOUNT: Set with unknown argument $a[1]";
return "OWCOUNT: set $name with unknown argument $a[1]";
}
#-- define vars
my $ret = undef;
my $page;
my $data;
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my ($cname,@cnama,@channel);
#-- set new timer interval
if($key eq "interval") {
# check value
return "OWCOUNT: Set with short interval, must be > 1"
if(int($value) < 1);
return "OWCOUNT: set $name interval must be >= 0"
if(int($value) < 0);
# update timer
$hash->{INTERVAL} = $value;
$hash->{INTERVAL} = int($value);
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWCOUNT_GetValues", $hash, 0);
return undef;
@ -1308,32 +1239,24 @@ sub OWCOUNT_Set($@) {
#-- check syntax for setting memory page 0..13
my $nomemory = defined($attr{$name}{"nomemory"}) ? $attr{$name}{"nomemory"} : 0;
if( $key eq "memory" ){
return "OWCOUNT: Memory usage disabled"
return "OWCOUNT: set $name memory usage disabled"
if( $nomemory==1 );
return "OWCOUNT: Set needs parameter when writing memory: <page>"
return "OWCOUNT: set $name memory needs parameter <page>"
if( int(@a)<2 );
$page=int($a[2]);
if( ($page<0) || ($page>13) ){
return "OWXCOUNT: Wrong memory page write attempted";
return "OWXCOUNT: set $name memory with wrong page $page attempted";
}
$data=$a[3];
for( my $i=4;$i<int(@a);$i++){
$data.=" ".$a[$i];
}
if( length($data) > 32 ){
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++){
$data.=" ";
}
}
$ret = OWCOUNT_SetPage($hash,$page,$data);
}
#-- other commands are per channel
if( ($key eq "midnight") || ($key eq "counter" )){
return "OWCOUNT: Set $key needs parameter: <channel>"
return "OWCOUNT: set $name $key needs parameter: <channel>"
if( int(@a)<2 );
#-- find out which channel we have
if( ($a[2] eq $owg_channel[0]) || ($a[2] eq "A") ){
@ -1341,7 +1264,7 @@ sub OWCOUNT_Set($@) {
}elsif( ($a[2] eq $owg_channel[1]) || ($a[2] eq "B") ){
$page=15;
} else {
return "OWCOUNT: Invalid counter address, must be A, B or defined channel name"
return "OWCOUNT: set $name $key has invalid counter address, must be A, B or defined channel name"
}
#-- mode normal or daily
my $daily = 0;
@ -1350,13 +1273,13 @@ sub OWCOUNT_Set($@) {
$daily = 1;
}
}
return "OWCOUNT: Set $key for channel $a[2] not possible, is not in daily mode"
return "OWCOUNT: set $name $key for channel $a[2] not possible, is not in daily mode"
if( $daily==0 );
my ($sec, $min, $hour, $day, $month, $year, $wday,$yday,$isdst) = localtime(time);
if( $key eq "midnight" ){
$data = sprintf("%4d-%02d-%02d midnight %7.2f",
$data = sprintf("%4d-%02d-%02d midnight %7.2f ",
$year+1900,$month+1,$day,$a[3]);
$ret = OWCOUNT_SetPage($hash,$page,$data);
}
@ -1364,19 +1287,19 @@ sub OWCOUNT_Set($@) {
if( $key eq "counter" ){
my $midnew=($hash->{owg_val}->[$page-14] + $hash->{READINGS}{$owg_channel[$page-14]}{OFFSET})*
$hash->{READINGS}{$owg_channel[$page-14]}{FACTOR} - $a[3];
$data = sprintf("%4d-%02d-%02d midnight %7.2f",
$data = sprintf("%4d-%02d-%02d midnight %7.2f ",
$year+1900,$month+1,$day,$midnew);
Log3 $name,5,"OWCOUNT: old midnight vakue ".$hash->{owg_midnight}->[$page-14].", replaced by $midnew";
Log3 $name,1,"OWCOUNT: old midnight value for device $name ".$hash->{owg_midnight}->[$page-14].", replaced by $midnew";
$ret = OWCOUNT_SetPage($hash,$page,$data);
}
}
#-- process results - we have to reread the device
if( defined($ret) && ($ret ne "") ){
return "OWCOUNT: Could not set device $name, reason: ".$ret;
return "OWCOUNT: set $name $key failed, reason: ".$ret;
}
OWCOUNT_GetValues($hash);
Log3 $name,5, "OWCOUNT: Set $hash->{NAME} $key $value";
#-- Took this out, not possible in asynchronoues mode
#OWCOUNT_GetValues($hash);
Log3 $name,5, "OWCOUNT: set $name $key $value";
}
#######################################################################################
@ -1399,7 +1322,11 @@ sub OWCOUNT_SetPage ($$$) {
#-- check if memory usage has been disabled
my $nomemory = defined($attr{$name}{"nomemory"}) ? $attr{$name}{"nomemory"} : 0;
#Log 1,"=========> device $name set page $page with nomemory=$nomemory and data of length ".length($data)." has data >$data< ";
$data=sprintf("%-32s",$data);
if( $nomemory==0 ){
#-- OWX interface
if( $interface eq "OWX" ){
@ -1414,12 +1341,12 @@ sub OWCOUNT_SetPage ($$$) {
$ret = OWFSCOUNT_SetPage($hash,$page,$data);
#-- Unknown interface
}else{
return "OWCOUNT: SetPage with wrong IODev type $interface";
return "OWCOUNT: SetPage $name with wrong IODev type $interface";
}
#-- process results
if( defined($ret) && ($ret ne "") ){
return "OWCOUNT: Could not set device $name, reason: ".$ret;
return "OWCOUNT: SetPage $name failed, reason: ".$ret;
}
}else{
if( $page==14 ){
@ -1449,11 +1376,12 @@ sub OWCOUNT_store($$$) {
if( $ret) {
print OWXFILE $data;
Log3 $name,1, "OWCOUNT_store: $name $data";
close(OWXFILE);
close(OWXFILE);
return undef;
} else {
Log3 $name,1,"OWCOUNT_store: Cannot open $filename for writing!";
}
return $ret;
return $ret;
}
}
########################################################################################
@ -1644,105 +1572,114 @@ sub OWXCOUNT_BinValues($$$$$$$) {
#-- hash of the busmaster
my $master = $hash->{IODev};
my $name = $hash->{NAME};
my @data=[];
my $error = 0;
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 );
OWX_WDBGL($name,4,"OWXCOUNT_BinValues called for device $name in context $context with data ",$res);
return undef unless (defined $context and $context =~ /^(get|set|check)page\.([\d]+)(\.final|)$/);
my $cmd = $1;
my $page = $2;
my $final = $3;
#=============== get memory + counter ===============================
if ($cmd eq "get") {
my (@data,$strval,$value);
my $change = 0;
#-- we have to get rid of the first 12 bytes
if( length($res) == 54 ){
$res=substr($res,12);
}
@data=split(//,$res);
$crcpart = $crcpart.substr($res,0,40);
#-- process results
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";
if( int(@data) != 42){
$error = 1;
$msg = "$name: invalid data length, ".int(@data)." instead of 42 bytes ";
}elsif (OWX_CRC16($crcpart,$data[40],$data[41]) == 0){
$error = 1;
$msg = "$name: invalid CRC, ".ord($data[40])." ".ord($data[41])." ";
}else{
if( $page > 13 ){
$owg_memory[1]=1;
}else{
$owg_memory[0]=1;
}
$owg_memory[2]=1;
$msg = "$name: no error ";
}
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 );
OWX_WDBGL($name,5-$error*4,"=====================> OWXCOUNT_BinValues getpage: ".$msg,$res);
#--
my $nomemory = defined($attr{$name}{"nomemory"}) ? $attr{$name}{"nomemory"} : 0;
my $nomemory = defined($attr{$name}{"nomemory"}) ? $attr{$name}{"nomemory"} : 0;
if( $nomemory==0 ){
#-- memory part, treated as string
$strval=substr($res,0,32);
#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 : "";
$hash->{memory} = defined $strval ? $strval : "";
$hash->{DATA}{memory} = 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" ){
my $msg = "device $name returns invalid data ".ord($data[4])." ".ord($data[5])." ".ord($data[6])." ".ord($data[7]);
OWX_WDBG($name,"OWXCOUNT_BinValues: ".$msg,"")
#-- does not work with old emulator devices
#if ( ($data[4] | $data[5] | $data[6] | $data[7]) ne "\x00" ){
# $error = 1;
# my $msg = "$name: invalid data in counter page ".ord($data[4])." ".ord($data[5])." ".ord($data[6])." ".ord($data[7]);
# OWX_WDBGL($name,1,"=====================> OWXCOUNT_BinValues getpage counter: ".$msg,"")
#}
if( !$error ){
#-- 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
OWCOUNT_ParseMidnight($hash,$strval,$page);
}
#-- 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,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);
if( $error ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
}else{
$hash->{PRESENT} = 1;
#-- and now from raw to formatted values
OWCOUNT_FormatValues($hash)
if( $final );
}
#=============== 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);
if( length($res) != 45){
$error = 1;
$msg = "$name: invalid data length, ".length($res)." instead of 45 bytes ";
}else{
$msg = "$name: no error ";
}
OWX_WDBGL($name,5-$error*4,"=====================> OWXCOUNT_BinValues: setpage ".$msg,$res);
#-- process results
my $select="\x5A".substr($res,10,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);
OWX_Qomplex($master, $hash, "setpage.$page.final", 16, $owx_dev, $select, 0, 16, 0, \&OWXCOUNT_BinValues, undef);
#-- 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;
}
#-- we have to get rid of the first 10 bytes
if( length($res) == 16 ){
$res=substr($res,10);
}
#-- change applied
$owg_memory[2]=1;
#-- process results
if( substr($res,4,1) ne "\xAA"){
$error = 1;
$msg = "$name: copy scratchpad to memory not successful ";
}else{
$msg = "$name: no error ";
}
OWX_WDBGL($name,5-$error*4,"=====================> OWXCOUNT_BinValues: setpage.$page.final ".$msg,$res);
}
return undef;
}
@ -1771,7 +1708,7 @@ sub OWXCOUNT_GetPage($$$) {
#=============== wrong value requested ===============================
if( ($page<0) || ($page>15) ){
return "wrong memory page requested";
return "wrong memory page requested from $owx_dev";
}
#=============== get memory + counter ===============================
#-- issue the match ROM command \x55 and the read memory + counter command
@ -1788,16 +1725,14 @@ sub OWXCOUNT_GetPage($$$) {
#-- reading 9 + 3 + 40 data bytes (32 byte memory, 4 byte counter + 4 byte zeroes) and 2 CRC bytes = 54 bytes
$res=OWX_Complex($master,$owx_dev,$select,42);
if( $res eq 0 ){
return "device $owx_dev not accessible in reading page $page";
return "$owx_dev not accessible in reading page $page";
}
#-- process results
if( length($res) < 54 ) {
#Log 1, "OWXCOUNT: warning, have received ".length($res)." bytes in first step";
#-- read the data in a second step
$res.=OWX_Complex($master,"","",0);
#-- process results
if( length($res) < 54 ) {
#Log 1, "OWXCOUNT: warning, have received ".length($res)." bytes in second step";
#-- read the data in a third step
$res.=OWX_Complex($master,"","",0);
}
@ -1807,17 +1742,15 @@ sub OWXCOUNT_GetPage($$$) {
#-- for processing we need 45 bytes
return "$owx_dev not accessible in reading"
if( $res eq 0 );
return "$owx_dev has returned invalid data"
return "$owx_dev has returned invalid data of length ".length($res)
if( length($res)!=54);
eval {
OWXCOUNT_BinValues($hash,$context,0,$owx_dev,$select,44,substr($res,12));
};
return $@ ? $@ : undef;
return OWXCOUNT_BinValues($hash,$context,0,$owx_dev,$select,44,substr($res,12));
#-- 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, 44, 12, \&OWXCOUNT_BinValues, 0.01);
OWX_Qomplex($master, $hash, $context, 0, $owx_dev, $select, $select, 54, 0, \&OWXCOUNT_BinValues, undef);
return undef;
}
}
@ -1833,7 +1766,6 @@ sub OWXCOUNT_GetPage($$$) {
########################################################################################
sub OWXCOUNT_SetPage($$$) {
my ($hash,$page,$data) = @_;
my ($select, $res, $res2, $res3);
@ -1844,7 +1776,7 @@ sub OWXCOUNT_SetPage($$$) {
#=============== wrong page requested ===============================
if( ($page<0) || ($page>15) ){
return "wrong memory page write attempt";
return "OWCOUNT: device $owx_dev wrong memory page write attempt";
}
#=============== midnight value =====================================
if( ($page==14) || ($page==15) ){
@ -1885,29 +1817,15 @@ sub OWXCOUNT_SetPage($$$) {
if( $res eq 0 ){
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, "setscratch", 8, $owx_dev, $select, $select, 35, 10, undef, 0);
OWX_Qomplex($master, $hash, "setscratch", 8, $owx_dev, $select, 0, 40, 0, undef, 0.05);
#-- 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, 35, 10, \&OWXCOUNT_BinValues, 0.01);
OWX_Qomplex($master, $hash, "setpage.".$page, 0, $owx_dev, "\xAA", 0, 45, 0, \&OWXCOUNT_BinValues, undef);
}
return undef;
}
@ -2138,7 +2056,7 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
code </li>
<li>
<code>&lt;interval&gt;</code>
<br />Measurement interval in seconds. The default is 300 seconds. </li>
<br />Measurement interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update. </li>
</ul>
<br />
<a name="OWCOUNTset"></a>
@ -2146,7 +2064,11 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
<ul>
<li><a name="owcount_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br /> Measurement
interval in seconds. The default is 300 seconds. </li>
interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update.
Log line after each interval &lt;date&gt; &lt;name&gt; &lt;channel&gt;: &lt;value&gt; &lt;unit&gt; &lt;value&gt; /
&lt;unit&gt;/&lt;period&gt; &lt;channel&gt;: &lt;value&gt; &lt;unit&gt; / &lt;value&gt; &lt;unit&gt;/&lt;period&gt; <br />
example: 2012-07-30_00:07:55 OWX_C Taste: 17.03 p 28.1 p/h B: 7.0 cts 0.0 cts/min
</li>
<li><a name="owcount_memory">
<code>set &lt;name&gt; memory &lt;page&gt; &lt;string&gt;</code></a><br />Write 32 bytes to
memory page 0..13 </li>
@ -2166,13 +2088,6 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
<li><a name="owcount_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owcount_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
<li><a name="owcount_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval in
seconds. </li>
<li><a name="owcount_memory2">
<code>get &lt;name&gt; memory &lt;page&gt;</code></a><br />Obtain 32 bytes from
memory page 0..13 and store in cache <i>$hash->{owg_str}->[page]</i> as well as in reading "memory"</li>
@ -2200,14 +2115,17 @@ sub OWXCOUNT_PT_InitializeDevicePage($$$) {
<ul>
<li><a name="owcount_logm"><code>attr &lt;name&gt; LogM
&lt;string&gt;</code></a>
<br />device name (not file name) of monthly log file.</li>
<br />device name (not file name) of monthly log file.
Log line after midnight &lt;new date&gt; &lt;name&gt; &lt;old day&gt; &lt;old date&gt; &lt;channel&gt;: &lt;value&gt; &lt;unit&gt; &lt;channel&gt;: &lt;value&gt; &lt;unit&gt;
<br /> example: 2012-07-30_00:00:57 OWX_C D29: 2012-7-29_23:59:59 Taste: 110.0 p, B: 7.0 cts
</li>
<li><a name="owcount_logy"><code>attr &lt;name&gt; LogY
&lt;string&gt;</code></a>
<br />device name (not file name) of yearly log file.</li>
<li><a name="owcount_interval2">
<code>attr &lt;name&gt; interval &lt;int&gt;</code></a>
<br /> Measurement
interval in seconds. The default is 300 seconds. </li>
interval in seconds. The default is 300 seconds, a value of 0 disables the automatic update. </li>
<li><a name="owcount_nomemory"><code>attr &lt;name&gt; nomemory
0|1</code></a>
<br />when set to 1, midnight values will be stored in files instead of the internal memory.</li>