mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
856ce5a4fa
attribute, which is available from now on for all devices. git-svn-id: https://svn.fhem.de/fhem/trunk@3738 2b470e98-0d58-463d-a4d8-8e2adae1ed80
330 lines
7.3 KiB
Perl
330 lines
7.3 KiB
Perl
##############################################
|
|
# $Id$
|
|
package main;
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Device::SerialPort;
|
|
|
|
my %sets = (
|
|
"cmd" => "",
|
|
"freq" => "",
|
|
);
|
|
|
|
#####################################
|
|
sub
|
|
SCIVT_Initialize($)
|
|
{
|
|
my ($hash) = @_;
|
|
|
|
# Consumer
|
|
$hash->{DefFn} = "SCIVT_Define";
|
|
$hash->{GetFn} = "SCIVT_Get";
|
|
$hash->{SetFn} = "SCIVT_Set";
|
|
$hash->{AttrList}= "model:SCD10,SCD20,SCD30";
|
|
}
|
|
|
|
#####################################
|
|
sub
|
|
SCIVT_Define($$)
|
|
{
|
|
my ($hash, $def) = @_;
|
|
my @a = split("[ \t][ \t]*", $def);
|
|
|
|
return "Define the serial device as a parameter, use none for a fake device"
|
|
if(@a != 3);
|
|
$hash->{STATE} = "Initialized";
|
|
|
|
my $dev = $a[2];
|
|
|
|
Log3 $hash, 1, "SCIVT device is none, commands will be echoed only"
|
|
if($dev eq "none");
|
|
|
|
if($dev ne "none") {
|
|
Log3 $hash, 3, "SCIVT opening device $dev";
|
|
my $po = new Device::SerialPort ($dev);
|
|
return "SCIVT Can't open $dev: $!" if(!$po);
|
|
Log3 $hash, 2, "SCIVT opened device $dev";
|
|
$po->close();
|
|
}
|
|
|
|
$hash->{DeviceName} = $dev;
|
|
$hash->{Timer} = 900; # call every 15 min
|
|
$hash->{Cmd} = 'F'; # get all data, min/max unchanged
|
|
|
|
my $tn = TimeNow();
|
|
$hash->{READINGS}{"freq"}{TIME} = $tn;
|
|
$hash->{READINGS}{"freq"}{VAL} = $hash->{Timer};
|
|
$hash->{READINGS}{"cmd"}{TIME} = $tn;
|
|
$hash->{READINGS}{"cmd"}{VAL} = $hash->{Cmd};
|
|
$hash->{CHANGED}[0] = "freq: $hash->{Timer}";
|
|
$hash->{CHANGED}[1] = "cmd: $hash->{Cmd}";
|
|
|
|
# InternalTimer blocks if init_done is not true
|
|
my $oid = $init_done;
|
|
$init_done = 1;
|
|
SCIVT_GetStatus($hash);
|
|
$init_done = $oid;
|
|
return undef;
|
|
}
|
|
|
|
#####################################
|
|
sub
|
|
SCIVT_Set($@)
|
|
{
|
|
my ($hash, @a) = @_;
|
|
return "\"set SCIVT\" needs at least two parameter" if(@a < 3);
|
|
my $name = $hash->{NAME};
|
|
Log3 $name, 4, "SCIVT Set request $a[1] $a[2], old: Timer:$hash->{Timer} Cmd: $hash->{Cmd}";
|
|
|
|
return "Unknown argument $a[1], choose one of " . join(" ", sort keys %sets)
|
|
if(!defined($sets{$a[1]}));
|
|
|
|
$name = shift @a;
|
|
my $type = shift @a;
|
|
my $arg = join("", @a);
|
|
my $tn = TimeNow();
|
|
|
|
if($type eq "freq")
|
|
{
|
|
if ($arg > 0)
|
|
{
|
|
$hash->{Timer} = $arg * 60;
|
|
$hash->{READINGS}{$type}{TIME} = $tn;
|
|
$hash->{READINGS}{$type}{VAL} = $hash->{Timer};
|
|
$hash->{CHANGED}[0] = "$type: $hash->{Timer}";
|
|
}
|
|
}
|
|
|
|
if($type eq "cmd")
|
|
{
|
|
if ($arg eq "F")
|
|
{
|
|
$hash->{Cmd} = 'F'; # F : get all data
|
|
}
|
|
if ($arg eq "L") # L : get all data and clear min-/max values
|
|
{
|
|
$hash->{Cmd} = 'L';
|
|
}
|
|
$hash->{READINGS}{$type}{TIME} = $tn;
|
|
$hash->{READINGS}{$type}{VAL} = $hash->{Cmd};
|
|
$hash->{CHANGED}[0] = "$type: $hash->{Cmd}";
|
|
}
|
|
|
|
DoTrigger($name, undef) if($init_done);
|
|
|
|
Log3 $name, 3, "SCIVT Set result Timer:$hash->{Timer} sec Cmd:$hash->{Cmd}";
|
|
return "SCIVT => Timer:$hash->{Timer} Cmd:$hash->{Cmd}";
|
|
}
|
|
|
|
#####################################
|
|
sub
|
|
SCIVT_Get($@)
|
|
{
|
|
my ($hash, @a) = @_;
|
|
return "get for an SCIVT device needs exactly one parameter" if(@a != 2);
|
|
my $name = $hash->{NAME};
|
|
|
|
my $v;
|
|
if($a[1] eq "data")
|
|
{
|
|
$v = SCIVT_GetLine($hash->{DeviceName}, $hash->{Cmd});
|
|
if(!defined($v))
|
|
{
|
|
Log3 $name, 2, "SCIVT Get $a[1] error";
|
|
return "$a[0] $a[1] => Error";
|
|
}
|
|
$v =~ s/[\r\n]//g; # Delete the NewLine
|
|
$hash->{READINGS}{$a[1]}{VAL} = $v;
|
|
$hash->{READINGS}{$a[1]}{TIME} = TimeNow();
|
|
}
|
|
else
|
|
{
|
|
if($a[1] eq "param")
|
|
{
|
|
$v = "$hash->{DeviceName} $hash->{Timer} $hash->{Cmd}";
|
|
}
|
|
else
|
|
{
|
|
return "Unknown argument $a[1], must be data or param";
|
|
}
|
|
}
|
|
|
|
Log3 $name, 3, "SCIVT Get $a[1] $v";
|
|
return "$a[0] $a[1] => $v";
|
|
}
|
|
|
|
#####################################
|
|
sub
|
|
SCIVT_GetStatus($)
|
|
{
|
|
my ($hash) = @_;
|
|
my $dnr = $hash->{DEVNR};
|
|
my $name = $hash->{NAME};
|
|
|
|
# Call us in n minutes again.
|
|
InternalTimer(gettimeofday()+ $hash->{Timer}, "SCIVT_GetStatus", $hash,1);
|
|
|
|
my %vals;
|
|
my $result = SCIVT_GetLine($hash->{DeviceName}, $hash->{Cmd});
|
|
|
|
if(!defined($result))
|
|
{
|
|
Log3 $name, 4, "SCIVT read error, retry $hash->{DeviceName}, $hash->{Cmd}";
|
|
$result = SCIVT_GetLine($hash->{DeviceName}, $hash->{Cmd});
|
|
}
|
|
|
|
if(!defined($result))
|
|
{
|
|
Log3 $name, 2, "SCIVT read error, abort $hash->{DeviceName}, $hash->{Cmd}";
|
|
$hash->{STATE} = "timeout";
|
|
return $hash->{STATE};
|
|
}
|
|
if (length($result) < 10)
|
|
{
|
|
Log3 $name, 2, "SCIVT incomplete line ($result)";
|
|
$hash->{STATE} = "incomplete";
|
|
}
|
|
else
|
|
{
|
|
$result =~ s/^.*R://;
|
|
$result =~ s/[\r\n ]//g;
|
|
Log3 $name, 3, "SCIVT $result (raw)";
|
|
$result=~ s/,/./g;
|
|
my @data = split(";", $result);
|
|
|
|
my @names = ("Vs", "Is", "Temp", "minV", "maxV", "minI", "maxI");
|
|
my $tn = TimeNow();
|
|
for(my $i = 0; $i < int(@names); $i++)
|
|
{
|
|
$hash->{CHANGED}[$i] = "$names[$i]: $data[$i]";
|
|
$hash->{READINGS}{$names[$i]}{TIME} = $tn;
|
|
$hash->{READINGS}{$names[$i]}{VAL} = $data[$i];
|
|
}
|
|
|
|
DoTrigger($name, undef) if($init_done);
|
|
|
|
$result =~ s/;/ /g;
|
|
$hash->{STATE} = "$result";
|
|
}
|
|
|
|
return $hash->{STATE};
|
|
}
|
|
|
|
#####################################
|
|
sub
|
|
SCIVT_GetLine($$)
|
|
{
|
|
my $retry = 0;
|
|
my ($dev,$cmd) = @_;
|
|
|
|
return "R:13,66; 0,0;30;13,62;15,09;- 0,2; 2,8;\n"
|
|
if($dev eq "none"); # Fake-mode
|
|
|
|
my $serport = new Device::SerialPort ($dev);
|
|
if(!$serport) {
|
|
Log3 undef, 1, "SCIVT: Can't open $dev: $!";
|
|
return undef;
|
|
}
|
|
$serport->reset_error();
|
|
$serport->baudrate(1200);
|
|
$serport->databits(8);
|
|
$serport->parity('none');
|
|
$serport->stopbits(1);
|
|
$serport->handshake('none');
|
|
|
|
my $rm = "SCIVT timeout reading the answer";
|
|
my $data="";
|
|
|
|
$serport->write($cmd);
|
|
sleep(1);
|
|
|
|
for(;;)
|
|
{
|
|
my ($rout, $rin) = ('', '');
|
|
vec($rin, $serport->FILENO, 1) = 1;
|
|
my $nfound = select($rout=$rin, undef, undef, 3.0);
|
|
|
|
if($nfound < 0) {
|
|
$rm = "SCIVT Select error $nfound / $!";
|
|
goto DONE;
|
|
}
|
|
last if($nfound == 0);
|
|
|
|
my $buf = $serport->input();
|
|
if(!defined($buf) || length($buf) == 0) {
|
|
$rm = "SCIVT EOF on $dev";
|
|
goto DONE;
|
|
}
|
|
|
|
|
|
$data .= $buf;
|
|
if($data =~ m/[\r\n]/) { # Newline received
|
|
$serport->close();
|
|
return $data;
|
|
}
|
|
}
|
|
|
|
DONE:
|
|
$serport->close();
|
|
Log3 undef, 3, "SCIVT $rm";
|
|
return undef;
|
|
}
|
|
|
|
1;
|
|
|
|
=pod
|
|
=begin html
|
|
|
|
<a name="SCIVT"></a>
|
|
<h3>SCIVT</h3>
|
|
<ul>
|
|
<br>
|
|
|
|
<a name="SCIVTdefine"></a>
|
|
<b>Define</b>
|
|
<ul>
|
|
<code>define <name> SCIVT <SCD-device></code>
|
|
<br><br>
|
|
|
|
Define a SCD series solar controler device. Details see <a
|
|
href="http://english.ivt-hirschau.de/content.php?parent_id=CAT_64&doc_id=DOC_118">here</a>.
|
|
You probably need a Serial to USB controller like the PL2303.
|
|
<br>
|
|
Defining an SCIVT device will schedule an internal task, which reads the
|
|
status of the device every 5 minutes, and triggers notify/filelog commands.
|
|
<br>Note: Currently this device does not support a "set" function, only
|
|
a single get function which reads the device status immediately.
|
|
<br><br>
|
|
|
|
Example:
|
|
<ul>
|
|
<code>define scd SCIVT /dev/ttyUSB2</code><br>
|
|
</ul>
|
|
<br>
|
|
</ul>
|
|
|
|
<a name="SVICTset"></a>
|
|
<b>Set</b> <ul>N/A</ul><br>
|
|
|
|
<a name="SVICTget"></a>
|
|
<b>Get</b>
|
|
<ul>
|
|
<code>get SCVIT data</code>
|
|
<br>
|
|
</ul>
|
|
<br>
|
|
|
|
<a name="SVICTattr"></a>
|
|
<b>Attributes</b>
|
|
<ul>
|
|
<li><a href="#model">model</a> (SCD)</li>
|
|
</ul>
|
|
<br>
|
|
|
|
</ul>
|
|
|
|
|
|
=end html
|
|
=cut
|