2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 03:06:37 +00:00

21_OWLCD.pm: Version 7.0 mit Anpassungen für OWX Next Generation

21_OWMULTI.pm: Version 7.0 mit Anpassungen für OWX Next Generation
21_OWSWITCH.pm: Version 7.0 mit Anpassungen für OWX Next Generation

git-svn-id: https://svn.fhem.de/fhem/trunk@14824 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
phenning 2017-07-31 18:13:20 +00:00
parent a3b98833ff
commit 7df0751160
3 changed files with 589 additions and 684 deletions

File diff suppressed because it is too large Load Diff

View File

@ -7,48 +7,7 @@
# Prof. Dr. Peter A. Henning
# Norbert Truchsess
#
# $Id$
#
########################################################################################
#
# define <name> OWMULTI [<model>] <ROM_ID> [interval] or OWMULTI <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
# DS2438
# <FAM_ID> is a 1-Wire family id, currently allowed value is 26
# <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 => OW_FAMILY.ROM_ID.CRC
# get <name> present => 1 if device present, 0 if not
# get <name> interval => query interval
# get <name> reading => measurement value obtained from VFunction
# get <name> temperature => temperature measurement
# get <name> VDD => supply voltage measurement
# get <name> raw => raw measurement voltages
# get <name> version => OWX version number
#
# set <name> interval => set period for measurement
#
# Additional attributes are defined in fhem.cfg
# Note: attributes "tempXXXX" are read during every update operation.
#
# 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 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 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
#
# $Id$
#
########################################################################################
#
@ -73,7 +32,7 @@ package main;
use vars qw{%attr %defs %modules $readingFnAttributes $init_done};
use strict;
use warnings;
#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though...
#add FHEM/lib to @INC if it's not already included. Should rather be in fhem.pl than here though...
BEGIN {
if (!grep(/FHEM\/lib$/,@INC)) {
foreach my $inc (grep(/FHEM$/,@INC)) {
@ -87,14 +46,12 @@ no warnings 'deprecated';
sub Log($$);
my $owx_version="6.1";
my $owx_version="7.0";
#-- flexible channel name
my ($owg_channel,$owg_schannel);
my %gets = (
"id" => "",
"present" => "",
"interval" => "",
"reading" => "",
"temperature" => "",
"VDD" => "",
@ -174,9 +131,9 @@ sub OWMULTI_Attr(@) {
#-- interval modified at runtime
$key eq "interval" and do {
#-- check value
return "OWMULTI: Set with short interval, must be > 1" if(int($value) < 1);
return "OWMULTI: 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}, "OWMULTI_GetValues", $hash, 0);
@ -261,7 +218,6 @@ sub OWMULTI_Define ($$) {
return "OWMULTI: $a[0] ID $a[2] invalid, specify a 12 or 2.12 digit value";
}
#-- determine CRC Code - only if this is a direct interface
$crc = sprintf("%02x",OWX_CRC($fam.".".$id."00"));
@ -269,6 +225,7 @@ sub OWMULTI_Define ($$) {
$hash->{OW_ID} = $id;
$hash->{OW_FAMILY} = $fam;
$hash->{PRESENT} = 0;
$hash->{ERRCOUNT} = 0;
$hash->{ROM_ID} = "$fam.$id.$crc";
$hash->{INTERVAL} = $interval;
@ -530,33 +487,6 @@ sub OWMULTI_Get($@) {
#-- Get other values according to interface type
my $interface= $hash->{IODev}->{TYPE};
#-- get present
if($a[1] eq "present" ) {
#-- OWX interface
if( $interface =~ /^OWX/ ){
#-- asynchronous mode
if( $hash->{ASYNC} ){
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";
} else {
return "OWMULTI: Verification not yet implemented for interface $interface";
}
}
#-- get interval
if($reading eq "interval") {
$value = $hash->{INTERVAL};
return "$name.interval => $value";
}
#-- get version
if( $a[1] eq "version") {
return "$name.version => $owx_version";
@ -572,7 +502,7 @@ sub OWMULTI_Get($@) {
$ret = OWX_ASYNC_RunToCompletion($hash,OWXMULTI_PT_GetValues($hash));
};
$ret = GP_Catch($@) if $@;
#-- OWFS interface not yet implemented
#-- OWFS interface
}elsif( $interface eq "OWServer" ){
$ret = OWFSMULTI_GetValues($hash);
#-- Unknown interface
@ -582,7 +512,8 @@ sub OWMULTI_Get($@) {
#-- process result
if( $master->{ASYNCHRONOUS} ){
return "OWSMULTI: $name getting readings, please wait for completion";
#return "OWSMULTI: $name getting readings, please wait for completion";
return undef;
}else{
if( defined($ret) ){
return "OWMULTI: Could not get values from device $name, reason $ret";
@ -628,20 +559,17 @@ sub OWMULTI_GetValues($) {
OWMULTI_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}, "OWMULTI_GetValues", $hash, 0);
#-- Get values according to interface type
my $interface= $hash->{IODev}->{TYPE};
if( $interface eq "OWX" ){
#-- max 3 tries
for(my $try=0; $try<3; $try++){
$ret = OWXMULTI_GetValues($hash);
#ASYNC: Need to wait for some result
return if( !defined($ret) );
}
$ret = OWXMULTI_GetValues($hash);
}elsif( $interface eq "OWX_ASYNC" ){
eval {
OWX_ASYNC_Schedule( $hash, OWXMULTI_PT_GetValues($hash) );
@ -715,10 +643,10 @@ sub OWMULTI_Set($@) {
#-- set new timer interval
if($key eq "interval") {
# check value
return "OWMULTI: Set with short interval, must be > 1"
if(int($value) < 1);
return "OWMULTI: 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}, "OWMULTI_GetValues", $hash, 0);
return undef;
@ -875,31 +803,33 @@ sub OWXMULTI_BinValues($$$$$$$) {
#-- hash of the busmaster
my $master = $hash->{IODev};
my $name = $hash->{NAME};
my @data=[];
my $error = 0;
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 );
OWX_WDBGL($name,4,"OWXMULTI_BinValues: called for device $name in context $context with data ",$res);
#-- always check for success, unused are reset, numread
return unless ($context =~ /^ds2438.getv[ad]d$/);
#Log 1,"OWXMULTI_BinValues context = $context";
#-- process results
@data=split(//,$res);
#-- not useful here, because data may be filled up with ff
#if (@data != 9) {
# $msg="$name returns invalid data length, ".int(@data)." instead of 9 bytes";
if ((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";
#-- we have to get rid of the first 11 bytes
if( length($res) == 20 ){
$res=substr($res,11);
}
OWX_WDBG($name,"OWXMULTI_BinValues: ".$msg,"")
if( $main::owx_debug>2 );
@data=split(//,$res);
#-- process results
if ((ord($data[0]) & 112)!=0) {
$msg = "$name: conversion not complete or data invalid in context $context ";
$error = 1;
}elsif (OWX_CRC8(substr($res,0,8),$data[8]) eq "\0x00") {
$msg = "$name: invalid CRC ";
$error = 1;
}else{
$msg = "$name: no error, ";
}
OWX_WDBGL($name,5-4*$error,"OWXMULTI_BinValues: ".$msg,$res);
#-- this must be different for the different device types
# family = 26 => DS2438
@ -955,9 +885,14 @@ sub OWXMULTI_BinValues($$$$$$$) {
$hash->{owg_val}->[3] = ($msb*256.+ $lsb)/4096;
#-- and now from raw to formatted values
$hash->{PRESENT} = 1;
my $value = OWMULTI_FormatValues($hash);
};
if( $error ){
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1;
}else{
$hash->{PRESENT} = 1;
OWMULTI_FormatValues($hash);
}
}
return undef;
}
@ -1088,75 +1023,75 @@ sub OWXMULTI_GetValues($) {
#-- 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);
#OWX_Qomplex($master, $hash, "write SP", 0, $owx_dev, "\x4E\x00\x08", 0, 0, 0, undef, undef);
#-- 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, 2, 0, undef, 0.01);
OWX_Qomplex($master, $hash, "write SP", 0, $owx_dev, "\x4E\x00\x09", 0, 2, 0, undef, 0.015);
#-- 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, 1, 0, undef, 0.01);
OWX_Qomplex($master, $hash, "copy SP", 0, $owx_dev, "\x48\x00", 0, 1, 0, undef, 0.015);
#-- 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.02);
OWX_Qomplex($master, $hash, "T conversion", 0, $owx_dev, "\x44", 0, 0, 0, undef, 0.015);
#-- 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.01);
OWX_Qomplex($master, $hash, "V conversion", 0, $owx_dev, "\xB4", 0, 0, 0, undef, 0.015);
#-- 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, 2, 0, undef, 0.02);
OWX_Qomplex($master, $hash, "recall", 0, $owx_dev, "\xB8\x00", 0, 2, 0, undef, 0.015);
#-- 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 operation
OWX_Qomplex($master, $hash, "ds2438.getvdd", 1, $owx_dev, "\xBE\x00\x08", 0, 9, 11, \&OWXMULTI_BinValues, 0.01);
OWX_Qomplex($master, $hash, "ds2438.getvdd", 1, $owx_dev, "\xBE\x00", 0, 20, 0, \&OWXMULTI_BinValues, 0.015);
#-- 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);
#OWX_Qomplex($master, $hash, "write SP", 0, $owx_dev, "\x4E\x00\x00", 0, 0, 0, undef, undef);
#-- 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, 1, 0, undef, 0.01);
OWX_Qomplex($master, $hash, "write SP", 0, $owx_dev, "\x4E\x00\x01", 0, 1, 0, undef, 0.015);
#-- 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, 1, 0, undef, 0.01);
OWX_Qomplex($master, $hash, "copy SP", 0, $owx_dev, "\x48\x00", 0, 1, 0, undef, 0.015);
#-- 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.01);
OWX_Qomplex($master, $hash, "V conversion", 0, $owx_dev, "\xB4", 0, 0, 0, undef, 0.015);
#-- 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, 1, 0, undef, 0.02);
OWX_Qomplex($master, $hash, "recall", 0, $owx_dev, "\xB8\x00", 0, 1, 0, undef, 0.015);
#-- 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 operation
OWX_Qomplex($master, $hash, "ds2438.getvad", 1, $owx_dev, "\xBE\x00", 0, 9, 11, \&OWXMULTI_BinValues, 0.01);
OWX_Qomplex($master, $hash, "ds2438.getvad", 1, $owx_dev, "\xBE\x00", 0, 20, 0, \&OWXMULTI_BinValues, 0.015);
return undef;
}
@ -1444,14 +1379,14 @@ sub OWXMULTI_PT_SetValues($@) {
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>
<a name="OWMULTIset"></a>
<h4>Set</h4>
<ul>
<li><a name="owmulti_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>
<a name="OWMULTIget"></a>
<h4>Get</h4>
@ -1459,13 +1394,6 @@ sub OWXMULTI_PT_SetValues($@) {
<li><a name="owmulti_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="owmulti_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="owmulti_interval2">
<code>get &lt;name&gt; interval</code></a><br />Returns measurement interval in
seconds. </li>
<li><a name="owmulti_reading">
<code>get &lt;name&gt; reading</code></a><br />Obtain all three measurement values. </li>
<li><a name="owmulti_temperature">
@ -1477,7 +1405,9 @@ sub OWXMULTI_PT_SetValues($@) {
</ul>
<a name="OWMULTIattr"></a>
<h4>Attributes</h4>
<ul>
<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 name="owmulti_vname"><code>attr &lt;name&gt; VName
&lt;string&gt;[|&lt;string&gt;]</code></a>
<br />name for the voltage channel [|short name used in state reading]. </li>

View File

@ -11,46 +11,6 @@
#
########################################################################################
#
# define <name> OWSWITCH [<model>] <ROM_ID> [interval] or OWSWITCH <fam>.<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
# 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
# [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> input <channel-name> => state for channel (name A, B or defined channel name)
# note: this value reflects the measured value, not necessarily the one set as
# output state, because the output transistors are open collector switches. A measured
# state of 1 = OFF therefore corresponds to an output state of 1 = OFF, but a measured
# state of 0 = ON can also be due to an external shortening of the output.
# get <name> gpio => values for channels
# get <name> version => OWX version number
#
# set <name> interval => set period for measurement
# set <name> output <channel-name> on|off|on-for-timer <int>|on-for-timer <int>
# => set value for channel (name A, B or defined channel name)
# note: 1 = OFF, 0 = ON in normal usage. See also the note above
# ON-for-timer/OFF-for-timer will set the desired value only for <int> seconds
# and then will return to the opposite value.
# set <name> gpio value => set values for channels (3 = both OFF, 1 = B ON 2 = A ON 0 = both ON)
# set <name> init yes => re-initialize device
#
# Additional attributes are defined in fhem.cfg, in some cases per channel, where <channel>=A,B
# Note: attributes are read only during initialization procedure - later changes are not used.
#
# attr <name> 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
#
########################################################################################
#
# 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
@ -87,15 +47,13 @@ no warnings 'deprecated';
sub Log($$);
my $owx_version="6.11";
my $owx_version="7.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");
my %gets = (
"id" => "",
"present" => "",
"interval" => "",
"input" => "",
"gpio" => "",
"version" => ""
@ -251,6 +209,7 @@ sub OWSWITCH_Define ($$) {
$hash->{OW_ID} = $id;
$hash->{OW_FAMILY} = $fam;
$hash->{PRESENT} = 0;
$hash->{ERRCOUNT} = 0;
$hash->{INTERVAL} = $interval;
#-- Couple to I/O device
@ -326,9 +285,9 @@ sub OWSWITCH_Attr(@) {
#-- interval modified at runtime
$key eq "interval" and do {
#-- check value
return "OWSWITCH: Set with short interval, must be > 1" if(int($value) < 1);
return "OWSWITCH: 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}, "OWSWITCH_GetValues", $hash, 0);
@ -490,28 +449,6 @@ sub OWSWITCH_Get($@) {
#-- hash of the busmaster
my $master = $hash->{IODev};
#-- get present
if($a[1] eq "present") {
#-- asynchronous mode
if( $hash->{ASYNC} ){
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") {
@ -547,15 +484,16 @@ sub OWSWITCH_Get($@) {
};
$ret = GP_Catch($@) if $@;
#-- OWFS interface
}elsif( $interface eq "OWFS" ){
}elsif( $interface eq "OWServer" ){
$ret = OWFSSWITCH_GetState($hash);
#-- Unknown interface
}else{
return "OWSWITCH: Get with wrong IODev type $interface";
}
#-- process result
if( ($master->{ASYNCHRONOUS}) && ($interface ne "OWFS") ){
return "OWSWITCH: $name getting input, please wait for completion";
if( ($master->{ASYNCHRONOUS}) && ($interface ne "OWServer") ){
#return "OWSWITCH: $name getting input, please wait for completion";
return undef;
}else{
return $name.".".$a[2]." => ".$hash->{READINGS}{$owg_channel[$fnd]}{VAL};
}
@ -579,7 +517,8 @@ sub OWSWITCH_Get($@) {
}
#-- process results
if( $master->{ASYNCHRONOUS} ){
return "OWSWITCH: $name getting gpio, please wait for completion";
#return "OWSWITCH: $name getting gpio, please wait for completion";
return undef;
}else{
if( defined($ret) ){
return "OWSWITCH: Could not get values from device $name, reason $ret";
@ -609,8 +548,11 @@ sub OWSWITCH_GetValues($) {
OWSWITCH_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}, "OWSWITCH_GetValues", $hash, 0);
#-- Get readings according to interface type
@ -714,10 +656,10 @@ sub OWSWITCH_Set($@) {
#-- set new timer interval
if($key eq "interval") {
# check value
return "OWSWITCH: Set with short interval, must be > 1"
if(int($value) < 1);
return "OWSWITCH: 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}, "OWSWITCH_GetValues", $hash, 0);
return undef;
@ -1025,7 +967,8 @@ sub OWXSWITCH_BinValues($$$$$$$) {
#-- hash of the busmaster
my $master = $hash->{IODev};
my $name = $hash->{NAME};
my @data=[];
my $error = 0;
my @data = [];
my $value;
my $msg;
my $cmd;
@ -1033,8 +976,7 @@ sub OWXSWITCH_BinValues($$$$$$$) {
my $outfnd;
my $outval;
OWX_WDBG($name,"OWXSWITCH_BinValues called for device $name in context $context with data ",$res)
if( $main::owx_debug>2 );
OWX_WDBGL($name,4,"OWXSWITCH_BinValues: called for device $name in context $context with data ",$res);
#-- note: value 1 corresponds to OFF, 0 to ON normally
# val = input value, vax = output value
@ -1048,13 +990,21 @@ sub OWXSWITCH_BinValues($$$$$$$) {
#-- initial get operation
#-- family = 12 => DS2406 -------------------------------------------------------
if( $chip eq "ds2406" ) {
#-- we have to get rid of the first 12 bytes
if( length($res) == 16 ){
$res=substr($res,12);
}
@data=split(//,$res);
$crcpart = $crcpart.substr($res,0,2);
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, ";
$error = 1;
$msg = "$name: invalid data length in $context, ".int(@data)." instead of 4 bytes, ";
}elsif(OWX_CRC16($crcpart,$data[2],$data[3]) == 0){
$error = 1;
$msg = "$name: invalid CRC in getstate, ";
}else{
$msg="No error, ";
$msg = "$name: no error, ";
$value=ord($data[0]);
$hash->{owg_val}->[0] = ($value>>2) & 1;
$hash->{owg_vax}->[0] = $value & 1;
@ -1064,15 +1014,24 @@ sub OWXSWITCH_BinValues($$$$$$$) {
}
#-- family = 29 => DS2408 -------------------------------------------------------
}elsif( $chip eq "ds2408" ) {
#-- we have to get rid of the first 12 bytes
if( length($res) == 22 ){
$res=substr($res,12);
}
@data=split(//,$res);
if (@data != 10){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 10 bytes, ";
$crcpart = $crcpart.substr($res,0,8);
if (@data < 10){
$error = 1;
$msg = "$name: invalid data length in $context, ".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, ";
$error = 1;
$msg = "$name: invalid data in getstate, ";
}elsif(OWX_CRC16($crcpart,$data[8],$data[9]) == 0){
$error = 1;
$msg = "$name: invalid CRC in getstate, ";
}else{
$msg="No error, ";
$msg = "$name: 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;
@ -1080,27 +1039,33 @@ sub OWXSWITCH_BinValues($$$$$$$) {
}
#-- family = 3A => DS2413 -------------------------------------------------------
}elsif( $chip eq "ds2413" ){
#-- we have to get rid of the first 10 bytes
if( length($res) == 12 ){
$res=substr($res,10);
}
@data=split(//,$res);
if (@data != 2){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 2 bytes, ";
$error = 1;
$msg = "$name: invalid data length in $context, ".int(@data)." instead of 2 bytes, ";
}elsif((15- (ord($data[0])>>4)) != (ord($data[0]) & 15)){
$msg="Error - $name returns invalid data, ";
$error = 1;
$msg = "$name: invalid data in getstate, ";
}else{
$msg="No error, ";
$msg ="$name: 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;
}
#--
}else{
die "OWSWITCH: $name has unknown device family $hash->{OW_FAMILY} in OWXSWITCH_BinValues getstate\n";
};
OWX_WDBG($name,"OWXSWITCH_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
main::OWX_WDBGL($name,5-4*$error,"OWXSWITCH_BinValues $context: ".$msg,$res);
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1
if( $error );
#-- Formatting only after final get
if( $outfnd eq "final"){
if( defined($outfnd) && ($outfnd eq "final") && !$error ){
$hash->{PRESENT} = 1;
$value = OWSWITCH_FormatValues($hash);
return undef;
@ -1128,13 +1093,20 @@ sub OWXSWITCH_BinValues($$$$$$$) {
$value = $2;
#-- family = 12 => DS2406 -------------------------------------------------------
if( $chip eq "ds2406" ) {
#-- we have to get rid of the first 13 bytes
if( length($res) == 15 ){
$res=substr($res,13);
}
@data=split(//,$res);
if (@data != 2){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 2 bytes, ";
$error = 1;
$msg = "$name: invalid data length in setstate, ".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, ";
$error = 1;
$msg = "$name: invalid CRC in setstate, ";
}else{
$msg="No error, ";
$msg = "$name: no error, ";
$hash->{owg_val}->[0] = ($value>>2) & 1;
$hash->{owg_vax}->[0] = $value & 1;
$hash->{owg_val}->[1] = ($value>>3) & 1;
@ -1142,12 +1114,20 @@ sub OWXSWITCH_BinValues($$$$$$$) {
}
#-- family = 29 => DS2408 -------------------------------------------------------
}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, ";
#-- we have to get rid of the first 12 bytes
if( length($res) == 13 ){
$res=substr($res,12);
}
@data=split(//,$res);
if (@data !=1 ){
$error = 1;
$msg = "$name: invalid data length in setstate, ".int(@data)." instead of 1 bytes, ";
}elsif($data[0] ne "\xAA"){
$error = 1;
$msg = "$name: invalid data in setstate, ";
}else{
$msg="No error, ";
$msg = "$name: no error, ";
for(my $i=0;$i<8;$i++){
$outval = ($value >>$i) & 1;
$hash->{owg_vax}->[$i] = $outval;
@ -1157,13 +1137,20 @@ sub OWXSWITCH_BinValues($$$$$$$) {
}
#-- family = 3A => DS2413 -------------------------------------------------------
}elsif( $chip eq "ds2413" ){
#-- we have to get rid of the first 12 bytes
if( length($res) == 14 ){
$res=substr($res,12);
}
@data=split(//,$res);
if (@data != 2){
$msg="Error - $name returns invalid data length, ".int(@data)." instead of 2 bytes, ";
$error = 1;
$msg = "$name: invalid data length in setstate, ".int(@data)." instead of 2 bytes, ";
}elsif( $data[0] ne "\xAA"){
$msg="Error - state could not be set for device $name, ";
$error = 1;
$msg = "$name: invalid data in setstate, ";
}else{
$msg="No error, ";
$msg = "$name: no error, ";
$outval = (ord($data[1])>>1) & 1;
$hash->{owg_vax}->[0] = $outval;
$hash->{owg_val}->[0] = 0
@ -1174,15 +1161,12 @@ sub OWXSWITCH_BinValues($$$$$$$) {
if( $outval ==0);
}
#--
}else{
die "OWSWITCH: $name has unknown device family $hash->{OW_FAMILY} in OWXSWITCH_BinValues setstate\n";
};
OWX_WDBG($name,"OWXSWITCH_BinValues: ".$msg,$res)
if( $main::owx_debug>2 );
}
OWX_WDBGL($name,5-4*$error,"OWXSWITCH_BinValues $context: ".$msg,$res);
$hash->{ERRCOUNT}=$hash->{ERRCOUNT}+1
if( $error );
#-- and finally after setstate follows another getstate
OWXSWITCH_GetModState($hash,"final",undef);
}else{
die "OWSWITCH: unknown context $context in OWXSWITCH_BinValues";
}
return undef;
}
@ -1219,15 +1203,15 @@ sub OWXSWITCH_GetModState($$$) {
if( !defined($outfnd) ){
$context = "getstate";
#-- take your time
$proc = 0;
$proc = 1;
}elsif( $outfnd eq "final"){
$context = "getstate.final";
#-- faster !
$proc = 16;
$proc = 1;
}else{
$context = "modstate.$outfnd.$outval";
#-- faster !
$proc = 16;
$proc = 1;
}
#-- family = 12 => DS2406
@ -1246,14 +1230,13 @@ sub OWXSWITCH_GetModState($$$) {
return "OWSWITCH: $name has returned invalid data"
if( length($res)!=16);
#OWX_Reset($master);
eval {
OWXSWITCH_BinValues($hash,"ds2406.$context",undef,$owx_dev,$select,4,substr($res,12));
};
return $@ ? $@ : undef;
return OWXSWITCH_BinValues($hash,"ds2406.$context",undef,$owx_dev,$select,4,substr($res,12));
#-- 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);
#OWX_Qomplex($master, $hash, "ds2406.$context", $proc, $owx_dev, $select, $select, 4, 12, \&OWXSWITCH_BinValues, 0.05);
OWX_Qomplex($master, $hash, "ds2406.$context", $proc, $owx_dev, $select, $select, 16, 0, \&OWXSWITCH_BinValues, 0.05);
return undef;
}
#-- family = 29 => DS2408
@ -1272,14 +1255,13 @@ sub OWXSWITCH_GetModState($$$) {
return "OWSWITCH: $name has returned invalid data"
if( length($res)!=22);
#OWX_Reset($master);
eval {
OWXSWITCH_BinValues($hash,"ds2408.$context",0,$owx_dev,$select,4,substr($res,12));
};
return $@ ? $@ : undef;
return OWXSWITCH_BinValues($hash,"ds2408.$context",0,$owx_dev,$select,4,substr($res,12));
#-- 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);
#OWX_Qomplex($master, $hash, "ds2408.$context", $proc, $owx_dev, $select, $select,12, 12, \&OWXSWITCH_BinValues, 0.05);
OWX_Qomplex($master, $hash, "ds2408.$context", $proc, $owx_dev, $select, $select, 22, 0, \&OWXSWITCH_BinValues, 0.05);
return undef;
}
#-- family = 3A => DS2413
@ -1297,14 +1279,13 @@ sub OWXSWITCH_GetModState($$$) {
return "OWSWITCH: $name has returned invalid data"
if( length($res)!=12);
#OWX_Reset($master);
eval {
OWXSWITCH_BinValues($hash,"ds2413.$context",0,$owx_dev,substr($res,9,1),2,substr($res,10));
};
return $@ ? $@ : undef;
return OWXSWITCH_BinValues($hash,"ds2413.$context",0,$owx_dev,substr($res,9,1),2,substr($res,10));
#-- NEW OWX interface
}else{
#### master slave context proc owx_dev data crcpart numread startread callback delay
OWX_Qomplex($master, $hash, "ds2413.$context", $proc, $owx_dev, "\xF5", "\xF5", 2, 10, \&OWXSWITCH_BinValues, 0);
#OWX_Qomplex($master, $hash, "ds2413.$context", $proc, $owx_dev, "\xF5", "\xF5", 2, 10, \&OWXSWITCH_BinValues, 0.05);
OWX_Qomplex($master, $hash, "ds2413.$context", $proc, $owx_dev, "\xF5", "\xF5", 12, 0, \&OWXSWITCH_BinValues, 0.05);
return undef;
}
} else {
@ -1353,10 +1334,10 @@ sub OWXSWITCH_SetState($$) {
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
#### 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", 0, $owx_dev, $select, 0, 2, 13, \&OWXSWITCH_BinValues, 0.01);
OWX_Qomplex($master, $hash, "ds2406.setstate.$value", 0, $owx_dev, $select, 0, 2, 2, \&OWXSWITCH_BinValues, 0.01);
#OWX_Qomplex($master, $hash, "ds2406.setstate.$value", 1, $owx_dev, $select, $select, 2, 13, \&OWXSWITCH_BinValues, undef);
OWX_Qomplex($master, $hash, "ds2406.setstate.$value", 1, $owx_dev, $select, $select, 15, 0, \&OWXSWITCH_BinValues, undef);
return undef;
}
#-- family = 29 => DS2408
@ -1378,7 +1359,8 @@ sub OWXSWITCH_SetState($$) {
}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);
#OWX_Qomplex($master, $hash, "ds2408.setstate.$value", 1, $owx_dev, $select, 0, 1, 12, \&OWXSWITCH_BinValues, undef);
OWX_Qomplex($master, $hash, "ds2408.setstate.$value", 1, $owx_dev, $select, 0, 13, 0, \&OWXSWITCH_BinValues, undef);
return undef;
}
#-- family = 3A => DS2413
@ -1390,7 +1372,7 @@ sub OWXSWITCH_SetState($$) {
#-- OLD OWX interface
if( !$master->{ASYNCHRONOUS} ){
OWX_Reset($master);
$res=OWX_Complex($master,$owx_dev,$select,1);
$res=OWX_Complex($master,$owx_dev,$select,2);
if( $res eq 0 ){
return "device $owx_dev not accessible in writing";
}
@ -1400,7 +1382,8 @@ sub OWXSWITCH_SetState($$) {
}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);
#OWX_Qomplex($master, $hash, "ds2413.setstate", 1, $owx_dev, $select, 0, 2, 12, \&OWXSWITCH_BinValues, undef);
OWX_Qomplex($master, $hash, "ds2413.setstate", 1, $owx_dev, $select, 0, 14, 0, \&OWXSWITCH_BinValues, undef);
return undef;
}
} else {
@ -1693,14 +1676,14 @@ sub OWXSWITCH_PT_SetOutput($$$) {
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>
<a name="OWSWITCHset"></a>
<h4>Set</h4>
<ul>
<li><a name="owswitch_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>
<li><a name="owswitch_output">
<code>set &lt;name&gt; output &lt;channel-name&gt; on | off | on-for-timer &lt;time&gt; | off-for-timer &lt;time&gt;</code>
</a><br />Set
@ -1721,13 +1704,6 @@ sub OWXSWITCH_PT_SetOutput($$$) {
<li><a name="owswitch_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="owswitch_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="owswitch_interval2">
<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
channel (A,B, ... or defined channel name) This value reflects the measured value,
@ -1738,8 +1714,12 @@ sub OWXSWITCH_PT_SetOutput($$$) {
<li><a name="owswitch_gpio">
<code>get &lt;name&gt; gpio</code></a><br />Obtain state of all channels</li>
</ul>
<a name="OWSWITCHattr"></a>
<h4>Attributes</h4> For each of the following attributes, the channel identification A,B,...
<a name="OWSWITCHattr"></a>
<h4>Attributes</h4>
<ul><li><a name="owswitch_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,...
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 X, set to "none" for empty).</li>