fhem-mirror/FHEM/21_OWID.pm
phenning e3607a76a9 00_OWX.pm: Neue Version, kleinere Fixes
11_OWX_CCC: Neue Version, kleinere Fixes
11_OWX_FRM: Neue Version, kleinere Fixes
11_OWX_SER: Neue Version, kleinere Fixes
11_OWX_TCP: Neue Version, kleinere Fixes
21_OWAD.pm: Neue Version, Support für OWX_ASYNC entfernt, kleinere Fixes
21_OWCOUNT.pm: Neue Version, Support für OWX_ASYNC entfernt, kleinere Fixes
21_OWID.pm: Neue Version, Support für OWX_ASYNC entfernt, kleinere Fixes
21_OWLCD.pm: Neue Version, Support für OWX_ASYNC entfernt, kleinere Fixes
21_OWMULTI.pm: Neue Version, Support für OWX_ASYNC entfernt, kleinere Fixes
21_OWSWITCH.pm: Neue Version, Support für OWX_ASYNC entfernt, kleinere Fixes
21_OWTHERM.pm: Neue Version, Support für OWX_ASYNC entfernt, kleinere Fixes
21_OWVAR.pm: Neue Version, Support für OWX_ASYNC entfernt, kleinere Fixes

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@23553 2b470e98-0d58-463d-a4d8-8e2adae1ed80
2021-01-19 13:51:06 +00:00

509 lines
15 KiB
Perl

########################################################################################
#
# OWID.pm
#
# FHEM module to commmunicate with general 1-Wire ID-ROMS
#
# Prof. Dr. Peter A. Henning
#
# $Id$
#
########################################################################################
#
# 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
# (at your option) any later version.
#
# The GNU General Public License can be found at
# http://www.gnu.org/copyleft/gpl.html.
# A copy is found in the textfile GPL.txt and important notices to the license
# from the author is found in LICENSE.txt distributed with these scripts.
#
# This script is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
########################################################################################
package main;
use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
use Time::HiRes qw(gettimeofday);
use strict;
use warnings;
my $owx_version="7.23";
#-- declare variables
my %gets = (
"present" => ":noArg",
"id" => ":noArg",
"version" => ":noArg"
);
my %sets = (
"interval" => ""
);
my %updates = (
"present" => ""
);
########################################################################################
#
# The following subroutines are independent of the bus interface
#
# Prefix = OWID
#
########################################################################################
#
# OWID_Initialize
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWID_Initialize ($) {
my ($hash) = @_;
$hash->{DefFn} = "OWID_Define";
$hash->{UndefFn} = "OWID_Undef";
$hash->{GetFn} = "OWID_Get";
$hash->{SetFn} = "OWID_Set";
$hash->{AttrFn} = "OWID_Attr";
$hash->{NotifyFn} = "OWID_Notify";
$hash->{InitFn} = "OWID_Init";
$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
main::LoadModule("OWX");
}
#########################################################################################
#
# OWID_Define - Implements DefFn function
#
# Parameter hash = hash of device addressed, def = definition string
#
#########################################################################################
sub OWID_Define ($$) {
my ($hash, $def) = @_;
#-- define <name> OWID <FAM_ID> <ROM_ID>
my @a = split("[ \t][ \t]*", $def);
my ($name,$interval,$model,$fam,$id,$crc,$ret);
#-- default
$name = $a[0];
$interval = 300;
$ret = "";
#-- check syntax
return "OWID: Wrong syntax, must be define <name> OWID [<model>] <id> [interval] or OWAD <fam>.<id> [interval]"
if(int(@a) < 2 || int(@a) > 5);
#-- different types of definition allowed
my $a2 = $a[2];
my $a3 = defined($a[3]) ? $a[3] : "";
#-- no model, 2+12 characters
if( $a2 =~ m/^[0-9|a-f|A-F]{2}\.[0-9|a-f|A-F]{12}$/ ) {
$fam = substr($a[2],0,2);
$id = substr($a[2],3);
if(int(@a)>=4) { $interval = $a[3]; }
if( $fam eq "01" ){
$model = "DS2401";
CommandAttr (undef,"$name model DS2401");
}elsif( $fam eq "09" ){
$model = "DS2502";
CommandAttr (undef,"$name model DS2502");
}else{
$model = "unknown";
CommandAttr (undef,"$name model unknown");
}
#-- model or family id, 12 characters
} elsif( $a3 =~ m/^[0-9|a-f|A-F]{12}$/ ) {
$id = $a[3];
if(int(@a)>=5) { $interval = $a[4]; }
#-- family id, 2 characters
if( $a2 =~ m/^[0-9|a-f|A-F]{2}$/ ) {
$fam = $a[2];
if( $fam eq "01" ){
$model = "DS2401";
CommandAttr (undef,"$name model DS2401");
}elsif( $fam eq "09" ){
$model = "DS2502";
CommandAttr (undef,"$name model DS2502");
}else{
$model = "unknown";
CommandAttr (undef,"$name model unknown");
}
}else{
$model = $a[2];
if( $model eq "DS2401" ){
$fam = "01";
CommandAttr (undef,"$name model DS2401");
}elsif( $model eq "DS2502" ){
$fam = "09";
CommandAttr (undef,"$name model DS2502");
}else{
return "OWID: Unknown 1-Wire device model $model";
}
}
} else {
return "OWID: $a[0] ID $a[2] invalid, specify a 12 or 2.12 digit value";
}
#-- determine CRC Code
$crc = sprintf("%02X",OWX_CRC($fam.".".$id."00"));
#-- Define device internals
$hash->{ROM_ID} = "$fam.$id.$crc";
$hash->{OW_ID} = $id;
$hash->{OW_FAMILY} = $fam;
$hash->{PRESENT} = 0;
$hash->{INTERVAL} = $interval;
#-- Couple to I/O device
AssignIoPort($hash);
if( !defined($hash->{IODev}) or !defined($hash->{IODev}->{NAME}) ){
return "OWID: Warning, no 1-Wire I/O device found for $name.";
}
$modules{OWID}{defptr}{$id} = $hash;
#--
readingsSingleUpdate($hash,"state","Defined",1);
Log3 $name,1, "OWID: Device $name defined.";
$hash->{NOTIFYDEV} = "global";
return OWID_Init($hash);
}
#########################################################################################
#
# OWID_Notify - Implements NotifyFn function
#
# Parameter hash = hash of device addressed, dev = device name
#
#########################################################################################
sub OWID_Notify ($$) {
my ($hash,$dev) = @_;
if( grep(m/^(INITIALIZED|REREADCFG)$/, @{$dev->{CHANGED}}) ) {
OWID_Init($hash);
} elsif( grep(m/^SAVE$/, @{$dev->{CHANGED}}) ) {
}
}
#########################################################################################
#
# OWID_Init - Implements InitFn function
#
# Parameter hash = hash of device addressed
#
#########################################################################################
sub OWID_Init ($) {
my ($hash)=@_;
#-- Start timer for updates
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+30, "OWID_GetValues", $hash, 0);
#--
readingsSingleUpdate($hash,"state","Initialized",1);
if (! (defined AttrVal($hash->{NAME},"stateFormat",undef))) {
$main::attr{$hash->{NAME}}{"stateFormat"} = "{ReadingsVal(\$name,\"present\",0) ? \"present\" : \"not present\"}";
}
return undef;
}
#######################################################################################
#
# OWID_Attr - Set one attribute value for device
#
# Parameter hash = hash of device addressed
# a = argument array
#
########################################################################################
sub OWID_Attr(@) {
my ($do,$name,$key,$value) = @_;
my $hash = $defs{$name};
my $ret;
if ( $do eq "set") {
ARGUMENT_HANDLER: {
#-- interval modified at runtime
$key eq "interval" and do {
#-- check value
return "OWID: set $name interval must be >= 0" if(int($value) < 0);
#-- update timer
$hash->{INTERVAL} = int($value);
if ($init_done) {
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0);
}
last;
};
$key eq "IODev" and do {
AssignIoPort($hash,$value);
if( defined($hash->{IODev}) ) {
$hash->{ASYNC} = $hash->{IODev}->{TYPE} eq "OWX_ASYNC" ? 1 : 0;
if ($init_done) {
OWID_Init($hash);
}
}
last;
}
}
}
return $ret;
}
########################################################################################
#
# OWID_Get - Implements GetFn function
#
# Parameter hash = hash of device addressed, a = argument array
#
########################################################################################
sub OWID_Get($@) {
my ($hash, @a) = @_;
my $reading = $a[1];
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my $value = undef;
my $ret = "";
my $offset;
my $factor;
#-- check syntax
return "OWID: Get argument is missing @a"
if(int(@a) != 2);
#-- check argument
my $msg = "OWID: Get with unknown argument $a[1], choose one of ";
$msg .= "$_$gets{$_} " foreach (keys%gets);
return $msg
if(!defined($gets{$a[1]}));
#-- get id
if($a[1] eq "id") {
$value = $hash->{ROM_ID};
return "$name.id => $value";
}
#-- get present
if($a[1] eq "present") {
#-- hash of the busmaster
my $master = $hash->{IODev};
my $interface = $master->{TYPE};
#-- OWX interface
if( $interface eq "OWX" ){
$value = OWX_Verify($master,$name,$hash->{ROM_ID},0);
#-- Unknown interface
} else {
return "OWID: Verification not yet implemented for interface $interface";
}
#-- process results
if( $master->{ASYNCHRONOUS} ){
return undef;
}else{
#-- generate an event only if presence has changed
if( $value == 0 ){
readingsSingleUpdate($hash,"present",0,$hash->{PRESENT});
} else {
readingsSingleUpdate($hash,"present",1,!$hash->{PRESENT});
}
$hash->{PRESENT} = $value;
return "$name.present => $value";
}
}
#-- get version
if( $a[1] eq "version") {
return "$name.version => $owx_version";
}
}
########################################################################################
#
# OWID_GetValues - Updates the reading from one device
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWID_GetValues($) {
my $hash = shift;
my $name = $hash->{NAME};
my $value = 0;
my $ret = "";
my $offset;
my $factor;
RemoveInternalTimer($hash);
#-- auto-update for device disabled;
return undef
if( $hash->{INTERVAL} == 0 );
#-- restart timer for updates
InternalTimer(time()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0);
#-- hash of the busmaster
my $master = $hash->{IODev};
my $interface = $master->{TYPE};
$value = OWX_Verify($master,$name,$hash->{ROM_ID},0);
#-- process results
if( $master->{ASYNCHRONOUS} ){
return undef;
}else{
#-- generate an event only if presence has changed
if( $value == 0 ){
readingsSingleUpdate($hash,"present",0,$hash->{PRESENT});
} else {
readingsSingleUpdate($hash,"present",1,!$hash->{PRESENT});
}
$hash->{PRESENT} = $value;
return "$name.present => $value";
}
}
#######################################################################################
#
# OWID_Set - Set one value for device
#
# Parameter hash = hash of device addressed
# a = argument array
#
########################################################################################
sub OWID_Set($@) {
my ($hash, @a) = @_;
my $key = $a[1];
my $value = $a[2];
#-- for the selector: which values are possible
if (@a == 2){
my $newkeys = join(" ", keys %sets);
return $newkeys ;
}
#-- check syntax
return "OWID: Set needs at least one parameter"
if( int(@a)<3 );
#-- check argument
if( !defined($sets{$a[1]}) ){
return "OWID: Set with unknown argument $a[1]";
}
my $name = $hash->{NAME};
#-- set new timer interval
if($key eq "interval") {
# check value
return "OWID: Set $name interval must be >= 0"
if(int($value) < 0);
# update timer
$hash->{INTERVAL} = int($value);
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWID_GetValues", $hash, 0);
return undef;
}
}
########################################################################################
#
# OWID_Undef - Implements UndefFn function
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWID_Undef ($) {
my ($hash) = @_;
delete($modules{OWID}{defptr}{$hash->{OW_ID}});
RemoveInternalTimer($hash);
return undef;
}
1;
=pod
=item device
=item summary to control 1-Wire devices having only a serial number
=begin html
<a name="OWID"></a>
<h3>OWID</h3>
<ul>
<p>FHEM module for 1-Wire devices that know only their unique ROM ID<br />
<br />This 1-Wire module works with the OWX interface module or with the OWServer interface module
Please define an <a href="#OWX">OWX</a> device or <a href="#OWServer">OWServer</a> device first. <br /></p>
<br /><h4>Example</h4><br />
<p>
<code>define ROM1 OWX_ID OWCOUNT 09.CE780F000000 10</code>
<br />
</p><br />
<a name="OWIDdefine"></a>
<h4>Define</h4>
<p>
<code>define &lt;name&gt; OWID &lt;fam&gt; &lt;id&gt; [&lt;interval&gt;]</code> or <br/>
<code>define &lt;name&gt; OWID &lt;fam&gt;.&lt;id&gt; [&lt;interval&gt;]</code>
<br /><br /> Define a 1-Wire device.<br /><br />
</p>
<ul>
<li>
<code>&lt;fam&gt;</code>
<br />2-character unique family id, see above
</li>
<li>
<code>&lt;id&gt;</code>
<br />12-character unique ROM id of the converter device without family id and CRC
code
</li>
<li>
<code>&lt;interval&gt;</code>
<br />Interval in seconds for checking the presence of the device. The default is 300 seconds. </li>
</ul>
<br />
<a name="OWIDset"></a>
<h4>Set</h4>
<ul>
<li><a name="owid_interval">
<code>set &lt;name&gt; interval &lt;int&gt;</code></a><br />
Interval in seconds for checking the presence of the device. The default is 300 seconds. </li>
</ul>
<br />
<a name="OWIDget"></a>
<h4>Get</h4>
<ul>
<li><a name="owid_id">
<code>get &lt;name&gt; id</code></a>
<br /> Returns the full 1-Wire device id OW_FAMILY.ROM_ID.CRC </li>
<li><a name="owid_present">
<code>get &lt;name&gt; present</code>
</a>
<br /> Returns 1 if this 1-Wire device is present, otherwise 0. </li>
</ul>
<h4>Attributes</h4>
<ul><li><a name="owtherm_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>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
</ul>
=end html
=cut