diff --git a/fhem/FHEM/98_ComfoAir.pm b/fhem/FHEM/98_ComfoAir.pm
index b9432a47a..7e3ead7bd 100755
--- a/fhem/FHEM/98_ComfoAir.pm
+++ b/fhem/FHEM/98_ComfoAir.pm
@@ -1,10 +1,9 @@
-##############################################
+##########################################################################
# $Id$
#
# fhem Modul für ComfoAir Lüftungsanlagen von Zehnder mit
# serieller Schnittstelle (RS232) sowie dazu kompatible Anlagen wie
-# Storkair WHR 930, Storkair 950
-# Paul Santos 370 DC, Paul Santos 570 DC
+# Storkair WHR 930, Storkair 950, Paul Santos 370 DC, Paul Santos 570 DC
# Wernig G90-380, Wernig G90-550
#
# Dieses Modul basiert auf der Protokollanalyse von SeeSolutions:
@@ -28,51 +27,88 @@
# along with fhem. If not, see .
#
##############################################################################
-# Changelog:
-#
# 2014-04-18 initial version
-# 2014-05-17 added more protocol commands, changed logging settings
-# 2014-05-25 added hide- attributes
-# 2014-07-07 corrected handling of 0xD2 Message (protocol is different than documented)
-# 2014-07-24 added max queue length checking and attribute
-# 2016-01-25 Reading Namen mit Umlauten korrigiert
-# 2016-04-06 Testmode Protokollbefehle hinzugefügt
-# 2016-11-13 korrektur bei set / get / readanswer. Set liefert bei Erfolg undef statt Text
-# 2017-02-12 Doku ergänzt
-# 2017-05-09 Text-Kodierung für summary korrigiert
-# 2020-05-07 fixed log level of debug massages in get function
-# 2020-05-15 fix uppercase hex strings in %parseInfo, use DevIo
-#
-#
-# Todo / Ideas:
-#
-package main;
+package ComfoAir;
use strict;
-
-use DevIo;
-
use warnings;
-use Time::HiRes qw( time );
+use GPUtils qw(:all);
+use Time::HiRes qw(gettimeofday time);
+use DevIo;
+use FHEM::HTTPMOD::Utils qw(:all);
-sub ComfoAir_Initialize($);
-sub ComfoAir_Define($$);
-sub ComfoAir_Undef($$);
-sub ComfoAir_Set($@);
-sub ComfoAir_Get($@);
-sub ComfoAir_Read($);
-sub ComfoAir_Ready($);
-sub ComfoAir_ReadAnswer($$$);
-sub ComfoAir_GetUpdate($$);
-sub ComfoAir_Send($$$;$$);
-sub ComfoAir_ParseFrames($);
-sub ComfoAir_InterpretFrame($$);
-sub ComfoAir_HandleSendQueue($);
-sub ComfoAir_SendAck($);
-sub ComfoAir_TimeoutSend($);
+use Exporter ('import');
+our @EXPORT_OK = qw();
+our %EXPORT_TAGS = (all => [@EXPORT_OK]);
-my $ComfoAir_Version = '1.52 - 15.5.2020';
+BEGIN {
+ GP_Import( qw(
+ fhem
+ CommandAttr
+ CommandDeleteAttr
+ addToDevAttrList
+ AttrVal
+ ReadingsVal
+ ReadingsTimestamp
+ readingsSingleUpdate
+ readingsBeginUpdate
+ readingsBulkUpdate
+ readingsEndUpdate
+ InternalVal
+ makeReadingName
+ Log3
+ RemoveInternalTimer
+ InternalTimer
+ deviceEvents
+ EvalSpecials
+ AnalyzePerlCommand
+ CheckRegexp
+ IsDisabled
+
+ gettimeofday
+ FmtDateTime
+ GetTimeSpec
+ fhemTimeLocal
+ time_str2num
+ min
+ max
+ minNum
+ maxNum
+ abstime2rel
+ defInfo
+ trim
+ ltrim
+ rtrim
+ UntoggleDirect
+ UntoggleIndirect
+ IsInt
+ fhemNc
+ round
+ sortTopicNum
+ Svn_GetFile
+ WriteFile
+
+ DevIo_OpenDev
+ DevIo_SimpleWrite
+ DevIo_SimpleRead
+ DevIo_CloseDev
+ SetExtensions
+ HttpUtils_NonblockingGet
+
+ featurelevel
+ defs
+ modules
+ attr
+ init_done
+ ));
+
+ GP_Export( qw(
+ Initialize
+ ));
+};
+
+my $Module_Version = '2.01 - 31.3.2021';
# %parseInfo:
# replyCode => msgHashRef
@@ -244,23 +280,21 @@ my %getHash; # helper to reference the msgHash in parseInfo for each name
my %requestHash; # helper to reference each msgHash for each request Set
my %cmdHash; # helper to map from send cmd code to msgHash of Reply
-my %ComfoAir_AddSets = (
+my %AddSets = (
"SendRawData" => ""
);
#####################################
-sub
-ComfoAir_Initialize($)
-{
- my ($hash) = @_;
+sub Initialize {
+ my $hash = shift;
- $hash->{ReadFn} = "ComfoAir_Read";
- $hash->{ReadyFn} = "ComfoAir_Ready";
- $hash->{DefFn} = "ComfoAir_Define";
- $hash->{UndefFn} = "ComfoAir_Undef";
- $hash->{SetFn} = "ComfoAir_Set";
- $hash->{GetFn} = "ComfoAir_Get";
+ $hash->{ReadFn} = \&ComfoAir::ReadFn;
+ $hash->{ReadyFn} = \&ComfoAir::ReadyFn;
+ $hash->{DefFn} = \&ComfoAir::DefineFn;
+ $hash->{UndefFn} = \&ComfoAir::UndefFn;
+ $hash->{SetFn} = \&ComfoAir::SetFn;
+ $hash->{GetFn} = \&ComfoAir::GetFn;
@setList = ();
@getList = ();
@@ -310,7 +344,8 @@ ComfoAir_Initialize($)
my $hl = $readingHashRef->{map}; # create hint list from map
$hl =~ s/([^ ,\$]+):([^ ,\$]+,?) ?/$2/g;
$readingHashRef->{setopt} = $reading . ":$hl";
- } else {
+ }
+ else {
$readingHashRef->{setopt} = $reading; # keine besonderen Optionen, nur den Namen für setopt verwenden.
}
if (defined($readingHashRef->{hint})){ # hints explizit definiert? (überschreibt evt. schon abgeleitete hints)
@@ -328,96 +363,81 @@ ComfoAir_Initialize($)
"queueMax " .
#"minSendDelay " .
join (" ", @pollList) . " " . # Def der zyklisch abzufragenden Nachrichten
- $readingFnAttributes;
+ $main::readingFnAttributes;
+ return;
}
#####################################
-sub
-ComfoAir_Define($$)
-{
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
+sub DefineFn {
+ my $hash = shift; # reference to the Fhem device hash
+ my $def = shift; # definition string
+ my @a = split( /[ \t]+/, $def ); # the above string split at space or tab
my ($name, $ComfoAir, $dev, $interval) = @a;
return "wrong syntax: define ComfoAir [devicename|none] [interval]"
if(@a < 3);
$hash->{BUSY} = 0;
- $hash->{EXPECT} = "";
- $hash->{ModuleVersion} = $ComfoAir_Version;
+ $hash->{EXPECT} = '';
+ $hash->{ModuleVersion} = $Module_Version;
- if (!defined($interval)) {
- $hash->{INTERVAL} = 0;
- Log 1, "$name: interval is 0 or not defined - not sending requests - just listening!";
- } else {
- $hash->{INTERVAL} = $interval;
- }
DevIo_CloseDev($hash);
-
- if($dev eq "none") {
- Log 1, "$name: device is none, commands will be echoed only";
- return undef;
- }
$hash->{DeviceName} = $dev;
- my $ret = DevIo_OpenDev($hash, 0, 0);
-
- InternalTimer(gettimeofday()+1, "ComfoAir_GetUpdate", $hash, 0) # erste Abfrage von Werten nach 1 Sekunde (zumindest in Queue stellen)
- if ($hash->{INTERVAL});
- return $ret;
+ if($dev ne "none") {
+ DevIo_OpenDev($hash, 0, 0);
+ }
+ if (!$interval) {
+ $hash->{INTERVAL} = 0;
+ Log3 $name, 3, "$name: interval is 0 or not specified - not sending requests - just listening!";
+ }
+ else {
+ $hash->{INTERVAL} = $interval;
+ InternalTimer(gettimeofday()+1, "GetUpdate", $hash, 0);
+ }
+ Log3 $name, 3, "$name: Defined with device $dev" . ($interval ? ", interval $interval" : '');
+ return;
}
#####################################
-sub
-ComfoAir_Undef($$)
-{
+sub UndefFn {
my ($hash, $arg) = @_;
my $name = $hash->{NAME};
DevIo_CloseDev($hash);
RemoveInternalTimer ("timeout:".$name);
RemoveInternalTimer ("queue:".$name);
RemoveInternalTimer ($hash);
- return undef;
+ return;
}
#####################################
-sub
-ComfoAir_Get($@)
-{
- my ($hash, @a) = @_;
- return "\"get ComfoAir\" needs at least one argument" if(@a < 2);
+sub GetFn {
+ my @getValArr = @_; # rest is optional values
+ my $hash = shift @getValArr; # reference to device hash
+ my $name = shift @getValArr; # device name
+ my $getName = shift @getValArr; # get option name
+ my $getVal = join(' ', @getValArr); # optional value after get name
- my $name = $hash->{NAME};
- my $getName = $a[1];
-
- if (defined($getHash{$getName})) {
- # get Option für Reading aus parseInfo -> generische Verarbeitung
- my $msgHash = $getHash{$getName}{msgHash}; # Hash für die Nachricht aus parseInfo
- Log3 $name, 5, "$name: Request found in getHash created from parseInfo data";
- if ($msgHash->{request}) {
- ComfoAir_Send($hash, $msgHash->{request}, "", $msgHash->{replyCode}, 1);
- my ($err, $result) = ComfoAir_ReadAnswer($hash, $getName, $msgHash->{replyCode});
- return $err if ($err);
- return $result;
- } else {
- return "Protocol doesn't provide a command to get $getName";
- }
- } else {
- # undefiniertes Get
+ return "\"get ComfoAir\" needs at least one argument" if(!$getName);
+ if (!defined($getHash{$getName})) { # undefined Get
Log3 $name, 5, "$name: Get $getName not found, return list @getList ";
- return "Unknown argument $a[1], choose one of @getList ";
+ return "Unknown argument $getName, choose one of @getList ";
}
-
- return undef;
+ my $msgHash = $getHash{$getName}{msgHash}; # Hash für die Nachricht aus parseInfo
+ Log3 $name, 5, "$name: Request found in getHash created from parseInfo data";
+ if (!$msgHash->{request}) {
+ return "Protocol doesn't provide a command to get $getName";
+ }
+ Send($hash, $msgHash->{request}, '', $msgHash->{replyCode}, 1);
+ my ($err, $result) = ReadAnswer($hash, $getName, $msgHash->{replyCode});
+ return $err if ($err);
+ return $result;
}
-
#####################################
-sub
-ComfoAir_Set($@)
-{
+sub SetFn {
my ($hash, @a) = @_;
return "\"set ComfoAir\" needs at least an argument" if(@a < 2);
@@ -431,7 +451,7 @@ ComfoAir_Set($@)
if (defined($requestHash{$setName})) {
# set Option ist Daten-Abfrage-Request aus parseInfo
Log3 $name, 5, "$name: Request found in requestHash created from parseInfo data";
- ComfoAir_Send($hash, $requestHash{$setName}{request}, "", $requestHash{$setName}{replyCode});
+ Send($hash, $requestHash{$setName}{request}, "", $requestHash{$setName}{replyCode});
return "";
}
if (defined($setHash{$setName})) {
@@ -475,46 +495,44 @@ ComfoAir_Set($@)
# 3. Schritt: Konvertiere mit setexpr falls definiert
if (defined($setHash{$setName}{setexpr})) {
my $val = $rawVal;
- $rawVal = eval($setHash{$setName}{setexpr});
+ $rawVal = eval($setHash{$setName}{setexpr}); ## no critic - expression needs to come from variable
Log3 $name, 5, "$name: converted Value $val to $rawVal using expr $setHash{$setName}{setexpr}";
}
# 4. Schritt: mit sprintf umwandeln und senden.
$data = sprintf($fmt, $rawVal); # in parseInfo angegebenes Format bei set=> - meist Konvert in Hex
- ComfoAir_Send($hash, $cmd, $data, 0);
+ Send($hash, $cmd, $data, 0);
# Nach dem Set gleich den passenden Datenblock nochmals anfordern, damit die Readings de neuen Wert haben
if ($setHash{$setName}{msgHash}{request}) {
- ComfoAir_Send($hash, $setHash{$setName}{msgHash}{request}, "",
+ Send($hash, $setHash{$setName}{msgHash}{request}, "",
$setHash{$setName}{msgHash}{replyCode},1);
# falls ein minDelay bei Send implementiert wäre, müsste ReadAnswer optimiert werden, sonst wird der 2. send ggf nicht vor einem Timeout gesendet ...
- my ($err, $result) = ComfoAir_ReadAnswer($hash, $setName, $setHash{$setName}{msgHash}{replyCode});
+ my ($err, $result) = ReadAnswer($hash, $setName, $setHash{$setName}{msgHash}{replyCode});
#return "$setName -> $result";
return $err if ($err);
}
- return undef;
+ return;
- } elsif (defined($ComfoAir_AddSets{$setName})) {
- # Additional set option not defined in parseInfo but ComfoAir_AddSets
+ } elsif (defined($AddSets{$setName})) {
+ # Additional set option not defined in parseInfo but AddSets
if($setName eq "SendRawData") {
return "please specify data as cmd or cmd -> data in hex"
if (!defined($setVal));
($cmd, $data) = split("->",$setVal); # eingegebener Wert ist HexCmd -> HexData
$data="" if(!defined($data));
}
- ComfoAir_Send($hash, $cmd, $data, 0);
+ Send($hash, $cmd, $data, 0);
} else {
# undefiniertes Set
- Log3 $name, 5, "$name: Set $setName not found, return list @setList " . join (" ", keys %ComfoAir_AddSets);
- return "Unknown argument $a[1], choose one of @setList " . join (" ", keys %ComfoAir_AddSets);
+ Log3 $name, 5, "$name: Set $setName not found, return list @setList " . join (" ", keys %AddSets);
+ return "Unknown argument $a[1], choose one of @setList " . join (" ", keys %AddSets);
}
- return undef;
+ return;
}
#####################################
# Called from the read functions
-sub
-ComfoAir_ParseFrames($)
-{
+sub ParseFrames {
my $hash = shift;
my $name = $hash->{NAME};
my $frame = $hash->{helper}{buffer};
@@ -532,7 +550,9 @@ ComfoAir_ParseFrames($)
Log3 $name, 5, "$name: ParseFrames got frame: $hash->{RAWBUFFER}" .
" data $hash->{LASTFRAMEDATA} Rest " . unpack ('H*', $hash->{helper}{buffer});
return $framedata;
- } elsif ($frame =~ /\x07\xf3(.*)/s) {
+ }
+ # ACK?
+ elsif ($frame =~ /\x07\xf3(.*)/s) {
my $level = ($hash->{INTERVAL} ? 4 : 5);
Log3 $name, $level, "$name: read got Ack";
$hash->{helper}{buffer} = $1; # only keep the rest after the frame
@@ -541,56 +561,48 @@ ComfoAir_ParseFrames($)
# es wird keine weitere Antwort erwartet -> gleich weiter Send Queue abarbeiten und nicht auf alten Timer warten
RemoveInternalTimer ("timeout:".$name);
RemoveInternalTimer ("queue:".$name);
- ComfoAir_HandleSendQueue ("direct:".$name); # don't wait for next regular handle queue slot
+ HandleSendQueue ("direct:".$name); # don't wait for next regular handle queue slot
}
- return undef;
- } else {
- return undef; # continue reading, probably frame not fully received yet
- }
+ }
+ return; # continue reading, probably frame not fully received yet
}
#####################################
# Called from the read functions
-sub
-ComfoAir_InterpretFrame($$)
-{
+sub InterpretFrame {
my $hash = shift;
my $framedata = shift;
my $name = $hash->{NAME};
my ($cmd, $hexcmd, $hexdata, $len, $data, $chk);
if (defined($framedata)) {
- if ($framedata =~ /(.{2})(.)(.*)(.)/s) {
- $cmd = $1;
- $len = $2;
- $data = $3;
- $chk = unpack ('C', $4);
- $hexcmd = unpack ('H*', $cmd);
- $hexdata = unpack ('H*', $data);
- Log3 $name, 5, "$name: read split frame into cmd $hexcmd, len " . unpack ('C', $len) .
- ", data $hexdata chk $chk";
- } else {
+ if ($framedata !~ /(.{2})(.)(.*)(.)/s) {
Log3 $name, 3, "$name: read: error splitting frame into fields: $hash->{LASTFRAMEDATA}";
return;
}
- }
-
+ $cmd = $1;
+ $len = $2;
+ $data = $3;
+ $chk = unpack ('C', $4);
+ $hexcmd = unpack ('H*', $cmd);
+ $hexdata = unpack ('H*', $data);
+ Log3 $name, 5, "$name: read split frame into cmd $hexcmd, len " . unpack ('C', $len) .
+ ", data $hexdata chk $chk";
+ }
# Länge prüfen
if (unpack ('C', $len) != length($data)) {
Log3 $name, 4, "$name: read: wrong length: " . length($data) .
" (calculated) != " . unpack ('C', $len) . " (header)" .
" cmd=$hexcmd, data=$hexdata, chk=$chk";
- #return;
+ return;
}
-
# Checksum prüfen
my $csum = unpack ('%8C*', $cmd . $len . $data . "\xad"); # berechne csum
if($csum != $chk) {
Log3 $name, 4, "$name: read: wrong checksum: $csum (calculated) != $chk (frame) cmd $hexcmd, data $hexdata";
return;
- };
-
+ };
# Parse Data
if ($parseInfo{$hexcmd}) {
if (!AttrVal($name, "hide-$parseInfo{$hexcmd}{name}", 0)) {
@@ -601,9 +613,9 @@ ComfoAir_InterpretFrame($$)
my @fields = unpack($p{"unpack"}, $data);
my $filter = 0;
if ($p{check}) {
- Log3 $name, 5, "$name: cmd $hexcmd check is " . eval($p{check}) .
- ', $fields[5] = ' . $fields[5] if ($fields[5] > 15);
- if (!eval($p{check})) {
+ my $result = eval($p{check}); ## no critic - expression needs to come from variable
+ Log3 $name, 5, "$name: cmd $hexcmd check is " . $result . ', $fields[5] = ' . $fields[5] if ($fields[5] > 15);
+ if (!$result) {
Log3 $name, 5, "$name: filter data for failed check: @fields";
$filter = 1;
}
@@ -617,7 +629,7 @@ ComfoAir_InterpretFrame($$)
# Exp zur Nachbearbeitung der Werte?
if ($p{"readings"}[$i]{"expr"}) {
Log3 $name, 5, "$name: read evaluate $val with expr " . $p{"readings"}[$i]{"expr"};
- $val = eval($p{"readings"}[$i]{"expr"});
+ $val = eval($p{"readings"}[$i]{"expr"}); ## no critic - expr needs tocome from variable
}
# Map zur Nachbereitung der Werte?
if ($p{"readings"}[$i]{"map"}) {
@@ -646,43 +658,53 @@ ComfoAir_InterpretFrame($$)
Log3 $name, 3, "$name: read did not get expected reply (" . $hash->{EXPECT} . ") but $hexcmd";
}
}
- ComfoAir_SendAck($hash) if ($hash->{INTERVAL});
+ SendAck($hash) if ($hash->{INTERVAL});
if (!$hash->{EXPECT}) {
# es wird keine Antwort mehr erwartet -> gleich weiter Send Queue abarbeiten und nicht auf Timer warten
$hash->{BUSY} = 0; # zur Sicherheit falls ein Ack versäumt wurde
RemoveInternalTimer ("timeout:".$name);
RemoveInternalTimer ("queue:".$name);
- ComfoAir_HandleSendQueue ("direct:".$name); # don't wait for next regular handle queue slot
+ HandleSendQueue ("direct:".$name); # don't wait for next regular handle queue slot
}
+ return;
}
#####################################
# Called from the global loop, when the select for hash->{FD} reports data
-sub
-ComfoAir_Read($)
-{
+sub ReadFn {
my $hash = shift;
my $name = $hash->{NAME};
- my $buf = DevIo_SimpleRead($hash);
- return if(!defined($buf));
-
+ my $buf;
+
+ if ($hash->{DeviceName} eq 'none') { # simulate receiving
+ if ($hash->{TestInput}) {
+ $buf = $hash->{TestInput};
+ delete $hash->{TestInput};
+ }
+ }
+ else {
+ $buf = DevIo_SimpleRead($hash);
+ return if(!defined($buf));
+ }
$hash->{helper}{buffer} .= $buf;
+ # todo: does this loop really make sense?
for (my $i = 0;$i < 2;$i++) {
- my $framedata = ComfoAir_ParseFrames($hash);
+ my $framedata = ParseFrames($hash);
return if (!$framedata);
- ComfoAir_InterpretFrame($hash, $framedata);
+ InterpretFrame($hash, $framedata);
}
+ return;
}
#####################################
# Called from get / set to get a direct answer
-sub
-ComfoAir_ReadAnswer($$$)
-{
+# todo: restructure this function (see Modbus)
+# handle BUSY when timeout here!
+sub ReadAnswer {
my ($hash, $arg, $expectReply) = @_;
my $name = $hash->{NAME};
@@ -696,7 +718,17 @@ ComfoAir_ReadAnswer($$$)
Log3 $name, 5, "$name: ReadAnswer called for get $arg";
for(;;) {
- if($^O =~ m/Win/ && $hash->{USBDev}) {
+ if ($hash->{DeviceName} eq 'none') { # simulate receiving
+ if ($hash->{TestInput}) {
+ $buf = $hash->{TestInput};
+ delete $hash->{TestInput};
+ } else {
+ #$hash->{BUSY} = 0;
+ #$hash->{EXPECT} = "";
+ return ("Timeout reading answer for $arg", undef);
+ }
+ }
+ elsif($^O =~ m/Win/ && $hash->{USBDev}) {
$hash->{USBDev}->read_const_time($to*1000); # set timeout (ms)
$buf = $hash->{USBDev}->read(999);
if(length($buf) == 0) {
@@ -716,7 +748,7 @@ ComfoAir_ReadAnswer($$$)
my $err = $!;
DevIo_Disconnected($hash);
Log3 $name, 3, "$name: ReadAnswer $arg: error $err";
- return("ComfoAir_ReadAnswer $arg: $err", undef);
+ return("ReadAnswer $arg: $err", undef);
}
if($nfound == 0) {
Log3 $name, 3, "$name: Timeout2 in ReadAnswer for $arg";
@@ -735,9 +767,9 @@ ComfoAir_ReadAnswer($$$)
Log3 $name, 5, "$name: ReadAnswer got: " . unpack ("H*", $hash->{helper}{buffer});
}
- $framedata = ComfoAir_ParseFrames($hash);
+ $framedata = ParseFrames($hash);
if ($framedata) {
- ComfoAir_InterpretFrame($hash, $framedata);
+ InterpretFrame($hash, $framedata);
$cmd = unpack ('H4x*', $framedata);
if ($cmd eq $expectReply) {
# das war's worauf wir gewartet haben
@@ -745,15 +777,14 @@ ComfoAir_ReadAnswer($$$)
return (undef, ReadingsVal($name, $arg, ""));
}
}
- ComfoAir_HandleSendQueue("direct:".$name);
+ HandleSendQueue("direct:".$name);
}
+ return;
}
#####################################
-sub
-ComfoAir_Ready($)
-{
+sub ReadyFn {
my ($hash) = @_;
return DevIo_OpenDev($hash, 1, undef)
if($hash->{STATE} eq "disconnected");
@@ -767,11 +798,10 @@ ComfoAir_Ready($)
#####################################
-sub
-ComfoAir_GetUpdate($$) {
+sub GetUpdate {
my ($hash) = @_;
my $name = $hash->{NAME};
- InternalTimer(gettimeofday()+$hash->{INTERVAL}, "ComfoAir_GetUpdate", $hash, 0)
+ InternalTimer(gettimeofday()+$hash->{INTERVAL}, "GetUpdate", $hash, 0)
if ($hash->{INTERVAL});
foreach my $msgHashRef (values %parseInfo) {
@@ -779,16 +809,16 @@ ComfoAir_GetUpdate($$) {
my $default = ($msgHashRef->{defaultpoll} ? 1 : 0); # verwende als Defaultwert für Attribut, falls gesetzt in %parseInfo
if (AttrVal($name, "poll-$msgHashRef->{name}", $default)) {
Log3 $name, 5, "$name: GetUpdate requests $msgHashRef->{name}, default is $default";
- ComfoAir_Send($hash, $msgHashRef->{request}, "", $msgHashRef->{replyCode});
+ Send($hash, $msgHashRef->{request}, "", $msgHashRef->{replyCode});
}
}
}
+ return;
}
#####################################
-sub
-ComfoAir_Send($$$;$$){
+sub Send {
my ($hash, $hexcmd, $hexdata, $expectReply, $first) = @_;
my $name = $hash->{NAME};
@@ -826,14 +856,13 @@ ComfoAir_Send($$$;$$){
}
}
}
- ComfoAir_HandleSendQueue("direct:".$name);
+ HandleSendQueue("direct:".$name);
+ return;
}
#######################################
-sub
-ComfoAir_TimeoutSend($)
-{
+sub TimeoutSend {
my $param = shift;
my (undef,$name) = split(':',$param);
my $hash = $defs{$name};
@@ -842,14 +871,13 @@ ComfoAir_TimeoutSend($)
($hash->{EXPECT} ? " expecting " . $hash->{EXPECT} : "") .
" Request was " . $hash->{LASTREQUEST};
$hash->{BUSY} = 0;
- $hash->{EXPECT} = "";
-};
+ $hash->{EXPECT} = "";
+ return;
+}
#######################################
-sub
-ComfoAir_HandleSendQueue($)
-{
+sub HandleSendQueue {
my $param = shift;
my (undef,$name) = split(':',$param);
my $hash = $defs{$name};
@@ -860,13 +888,13 @@ ComfoAir_HandleSendQueue($)
if(defined($arr) && @{$arr} > 0) {
if (!$init_done) { # fhem not initialized, wait with IO
RemoveInternalTimer ("queue:".$name);
- InternalTimer($now+$queueDelay, "ComfoAir_HandleSendQueue", "queue:".$name, 0);
+ InternalTimer($now+$queueDelay, "ComfoAir::HandleSendQueue", "queue:".$name, 0);
Log3 $name, 3, "$name: init not done, delay writing from queue";
return;
}
if ($hash->{BUSY}) { # still waiting for reply to last request
RemoveInternalTimer ("queue:".$name);
- InternalTimer($now+$queueDelay, "ComfoAir_HandleSendQueue", "queue:".$name, 0);
+ InternalTimer($now+$queueDelay, "ComfoAir::HandleSendQueue", "queue:".$name, 0);
Log3 $name, 5, "$name: send busy, delay writing from queue";
return;
}
@@ -885,7 +913,12 @@ ComfoAir_HandleSendQueue($)
($entry->{EXPECT} ? " and wait for " . $entry->{EXPECT} : "") .
", V " . $hash->{ModuleVersion};
- DevIo_SimpleWrite($hash, $bstring, 0);
+ if ($hash->{DeviceName} eq 'none') {
+ Log3 $name, 4, "$name: Simulate sending to none: " . unpack ('H*', $bstring);
+ }
+ else {
+ DevIo_SimpleWrite($hash, $bstring, 0);
+ }
if ($entry->{EXPECT}) {
# we expect a reply
@@ -893,27 +926,27 @@ ComfoAir_HandleSendQueue($)
}
my $to = AttrVal($name, "timeout", 2); # default is 2 seconds timeout
RemoveInternalTimer ("timeout:".$name);
- InternalTimer($now+$to, "ComfoAir_TimeoutSend", "timeout:".$name, 0);
+ InternalTimer($now+$to, "ComfoAir::TimeoutSend", "timeout:".$name, 0);
}
shift(@{$arr});
if(@{$arr} == 0) { # last item was sent -> delete queue
delete($hash->{QUEUE});
} else { # more items in queue -> schedule next handle invocation
RemoveInternalTimer ("queue:".$name);
- InternalTimer($now+$queueDelay, "ComfoAir_HandleSendQueue", "queue:".$name, 0);
+ InternalTimer($now+$queueDelay, "ComfoAir::HandleSendQueue", "queue:".$name, 0);
}
}
+ return;
}
#######################################
-sub
-ComfoAir_SendAck($)
-{
+sub SendAck {
my $hash = shift;
my $name = $hash->{NAME};
Log3 $name, 4, "$name: sending Ack";
DevIo_SimpleWrite($hash, "\x07\xf3", 0);
+ return;
}