2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-18 12:06:04 +00:00

CUL_MAX: Enqueue messages for ShutterContact until its button is pressed

git-svn-id: https://svn.fhem.de/fhem/trunk@4111 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
mgehre 2013-10-25 10:47:03 +00:00
parent 60511648a0
commit 4bca443027

View File

@ -15,7 +15,7 @@ sub CUL_MAX_Set($@);
sub CUL_MAX_SendTimeInformation(@);
sub CUL_MAX_GetTimeInformationPayload();
sub CUL_MAX_Send(@);
sub CUL_MAX_SendQueueHandler($);
sub CUL_MAX_SendQueueHandler($$);
my $pairmodeDuration = 60; #seconds
@ -276,13 +276,18 @@ CUL_MAX_Parse($$)
return $shash->{NAME} if(!@{$shash->{sendQueue}}); #we are not waiting for any Ack
my $packet = $shash->{sendQueue}[0];
if($packet->{src} eq $dst and $packet->{dst} eq $src and $packet->{cnt} == hex($msgcnt)) {
Log $ll5, "Got matching ack";
my $isnak = unpack("C",pack("H*",$payload)) & 0x80;
$packet->{sent} = $isnak ? 3 : 2;
return $shash->{NAME};
for my $i (0 .. $#{$shash->{sendQueue}}) {
my $packet = $shash->{sendQueue}[$i];
if($packet->{src} eq $dst and $packet->{dst} eq $src and $packet->{cnt} == hex($msgcnt)) {
Log $ll5, "Got matching ack";
my $isnak = unpack("C",pack("H*",$payload)) & 0x80;
$packet->{sent} = $isnak ? 3 : 2;
}
}
#Handle outgoing messages to that ShutterContact. It is only awake shortly
#after sending an Ack to a PairPong
CUL_MAX_SendQueueHandler($shash, $src) if($modules{MAX}{defptr}{$src}{type} eq "ShutterContact");
return $shash->{NAME};
} elsif($msgType eq "TimeInformation") {
if($isToMe) {
@ -386,7 +391,7 @@ CUL_MAX_Send(@)
#Call CUL_MAX_SendQueueHandler if we just enqueued the only packet
#otherwise it is already in the InternalTimer list
CUL_MAX_SendQueueHandler($hash) if(@{$hash->{sendQueue}} == 1);
CUL_MAX_SendQueueHandler($hash,undef) if(@{$hash->{sendQueue}} == 1);
return undef;
}
@ -399,12 +404,17 @@ CUL_MAX_DeviceHash($)
#This can be called for two reasons:
#1. @sendQueue was empty, CUL_MAX_Send added a packet and then called us
#2. We sent a packet from @sendQueue and know the ackTimeout is over.
#2. We sent a packet from @sendQueue and now the ackTimeout is over.
# The packet my still be in @sendQueue (timed out) or removed when the Ack was received.
# Arguments are hash and responseToShutterContact.
# If SendQueueHandler was called after receiving a message from a shutter contact, responseToShutterContact
# holds the address of the respective shutter contact. Otherwise, it is empty.
sub
CUL_MAX_SendQueueHandler($)
CUL_MAX_SendQueueHandler($$)
{
my $hash = shift;
my $responseToShutterContact = shift;
Log GetLogLevel($hash->{NAME}, 5), "CUL_MAX_SendQueueHandler: " . @{$hash->{sendQueue}} . " items in queue";
return if(!@{$hash->{sendQueue}}); #nothing to do
@ -423,13 +433,34 @@ CUL_MAX_SendQueueHandler($)
return undef;
}
my $packet = $hash->{sendQueue}[0];
my ($packet, $pktIdx, $packetForShutterContactInQueue);
for($pktIdx = 0; $pktIdx < @{$hash->{sendQueue}}; $pktIdx += 1) {
$packet = $hash->{sendQueue}[$pktIdx];
if(defined($responseToShutterContact)) {
#Find a packet to the ShutterContact in $responseToShutterContact
last if($packet->{dst} eq $responseToShutterContact);
} else {
#We cannot sent packets to a ShutterContact directly, everything else is possible
last if($packet->{cmd} eq "PairPong"
|| $packet->{sent} != 0
|| $modules{MAX}{defptr}{$packet->{dst}}{type} ne "ShutterContact");
$packetForShutterContactInQueue = $modules{MAX}{defptr}{$packet->{dst}}{NAME};
}
}
if($pktIdx == @{$hash->{sendQueue}} && !defined($responseToShutterContact)) {
Log 2, "There is a packet for ShutterContact $packetForShutterContactInQueue in queue. Please push the button on the respective ShutterContact so the packet can be send.";
$timeout += 3;
InternalTimer($timeout, "CUL_MAX_SendQueueHandler", $hash, 0);
return undef;
}
if( $packet->{sent} == 0 ) { #Need to send it first
#We can use fast sending without preamble on culfw 1.53 and higher when the devices has been woken up
my $needPreamble = ((CUL_MAX_Check($hash) < 153)
|| !defined($modules{MAX}{defptr}{$packet->{dst}}{wakeUpUntil})
|| $modules{MAX}{defptr}{$packet->{dst}}{wakeUpUntil} < gettimeofday()) ? 1 : 0;
|| (!defined($responseToShutterContact) &&
(!defined($modules{MAX}{defptr}{$packet->{dst}}{wakeUpUntil})
|| $modules{MAX}{defptr}{$packet->{dst}}{wakeUpUntil} < gettimeofday()))) ? 1 : 0;
#Send to CUL
my ($credit10ms) = (CommandGet("","$hash->{IODev}{NAME} credit10ms") =~ /[^ ]* [^ ]* => (.*)/);
@ -465,7 +496,7 @@ CUL_MAX_SendQueueHandler($)
if( $packet->{sentTime} + $ackTimeout < gettimeofday() ) {
# ackTimeout exceeded
Log 2, "CUL_MAX_SendQueueHandler: Missing ack from $packet->{dst} for $packet->{packet}";
splice @{$hash->{sendQueue}}, 0, 1; #Remove from array
splice @{$hash->{sendQueue}}, $pktIdx, 1; #Remove from array
readingsSingleUpdate($hash, "packetsLost", ReadingsVal($hash->{NAME}, "packetsLost", 0) + 1, 1);
} else {
# Recheck for Ack
@ -476,13 +507,14 @@ CUL_MAX_SendQueueHandler($)
if(defined($packet->{callbackParam})) {
Dispatch($hash, "MAX,1,Ack$packet->{cmd},$packet->{dst},$packet->{callbackParam}", {RAWMSG => ""});
}
splice @{$hash->{sendQueue}}, 0, 1; #Remove from array
splice @{$hash->{sendQueue}}, $pktIdx, 1; #Remove from array
} elsif( $packet->{sent} == 3 ) { #Got nack
splice @{$hash->{sendQueue}}, 0, 1; #Remove from array
splice @{$hash->{sendQueue}}, $pktIdx, 1; #Remove from array
}
return if(!@{$hash->{sendQueue}}); #everything done
return if(defined($responseToShutterContact)); #this was not called from InternalTimer
InternalTimer($timeout, "CUL_MAX_SendQueueHandler", $hash, 0);
}