mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-10 03:06:37 +00:00
00_DFPlayerMini: improved requestAck handling
git-svn-id: https://svn.fhem.de/fhem/trunk@14229 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
182a62d8c3
commit
5b54a84c60
@ -1,5 +1,6 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||||
# Do not insert empty lines here, update check depends on it.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- feature: 00_DFPlayerMini: improved requestAck handling
|
||||||
- change: 49_SSCam: new version 2.1.3, change of internal processes, new
|
- change: 49_SSCam: new version 2.1.3, change of internal processes, new
|
||||||
get scanVirgin command
|
get scanVirgin command
|
||||||
- bugfix: 73_ElectricityCalculator: SiPrefix multiplier instead divider
|
- bugfix: 73_ElectricityCalculator: SiPrefix multiplier instead divider
|
||||||
|
@ -287,6 +287,7 @@ DFPlayerMini_Define($$)
|
|||||||
$ret = DevIo_OpenDev($hash, 0, "DFPlayerMini_DoInit", 'DFPlayerMini_Connect');
|
$ret = DevIo_OpenDev($hash, 0, "DFPlayerMini_DoInit", 'DFPlayerMini_Connect');
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
DFPlayerMini_DoInit($hash);
|
||||||
$hash->{DevState} = 'initialized';
|
$hash->{DevState} = 'initialized';
|
||||||
readingsSingleUpdate($hash, "state", "opened", 1);
|
readingsSingleUpdate($hash, "state", "opened", 1);
|
||||||
}
|
}
|
||||||
@ -361,7 +362,7 @@ DFPlayerMini_createCmd($$;$$)
|
|||||||
$par2 = 0 if !defined $par2;
|
$par2 = 0 if !defined $par2;
|
||||||
|
|
||||||
my $requestAck = AttrVal($hash->{NAME}, "requestAck", 0) || $cmd == DFP_C_Acknowledge;
|
my $requestAck = AttrVal($hash->{NAME}, "requestAck", 0) || $cmd == DFP_C_Acknowledge;
|
||||||
|
|
||||||
my $checksum = -(DFP_Version_Byte+DFP_Command_Length+$cmd+$requestAck+$par1+$par2);
|
my $checksum = -(DFP_Version_Byte+DFP_Command_Length+$cmd+$requestAck+$par1+$par2);
|
||||||
return pack('CCCCCCCnC', DFP_Start_Byte,DFP_Version_Byte, DFP_Command_Length, $cmd, $requestAck, $par1, $par2, $checksum, DFP_End_Byte);
|
return pack('CCCCCCCnC', DFP_Start_Byte,DFP_Version_Byte, DFP_Command_Length, $cmd, $requestAck, $par1, $par2, $checksum, DFP_End_Byte);
|
||||||
|
|
||||||
@ -1046,6 +1047,7 @@ DFPlayerMini_DoInit($)
|
|||||||
|
|
||||||
@{$hash->{PLAYQUEUE}} = ();
|
@{$hash->{PLAYQUEUE}} = ();
|
||||||
@{$hash->{TTSQUEUE}} = ();
|
@{$hash->{TTSQUEUE}} = ();
|
||||||
|
$hash->{waitForAck} = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
#return undef;
|
#return undef;
|
||||||
@ -1138,7 +1140,7 @@ sub DFPlayerMini_AddSendQueue($$)
|
|||||||
|
|
||||||
#Log3 $hash, 3,"$name: AddSendQueue: " . $hash->{NAME} . ": $msg";
|
#Log3 $hash, 3,"$name: AddSendQueue: " . $hash->{NAME} . ": $msg";
|
||||||
|
|
||||||
if (gettimeofday() - $hash->{LAST_SEND_TS} > DFP_MIN_WAITTIME) {
|
if (!$hash->{waitForAck} && gettimeofday() - $hash->{LAST_SEND_TS} > DFP_MIN_WAITTIME) {
|
||||||
# minimal wait time before next command exceeded, can write immediately
|
# minimal wait time before next command exceeded, can write immediately
|
||||||
DFPlayerMini_SimpleWrite($hash, $msg);
|
DFPlayerMini_SimpleWrite($hash, $msg);
|
||||||
} else {
|
} else {
|
||||||
@ -1146,32 +1148,16 @@ sub DFPlayerMini_AddSendQueue($$)
|
|||||||
push(@{$hash->{QUEUE}}, $msg);
|
push(@{$hash->{QUEUE}}, $msg);
|
||||||
|
|
||||||
#Log3 $hash , 5, Dumper($hash->{QUEUE});
|
#Log3 $hash , 5, Dumper($hash->{QUEUE});
|
||||||
|
if ($hash->{waitForAck} == 0) {
|
||||||
InternalTimer(gettimeofday() + DFP_MIN_WAITTIME, "DFPlayerMini_HandleWriteQueue", "HandleWriteQueue:$name", 1);
|
# if we don't have to wait for an acknowledge from dfp we have at least to wait 20ms
|
||||||
|
InternalTimer(gettimeofday() + DFP_MIN_WAITTIME, "DFPlayerMini_HandleWriteQueue", "HandleWriteQueue:$name", 1);
|
||||||
|
} else {
|
||||||
|
Log3 $hash, 5, "delayed send, waiting for ack";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub
|
|
||||||
DFPlayerMini_SendFromQueue($$)
|
|
||||||
{
|
|
||||||
my ($hash, $msg) = @_;
|
|
||||||
my $name = $hash->{NAME};
|
|
||||||
|
|
||||||
if($msg ne "") {
|
|
||||||
#DevIo_SimpleWrite($hash, $msg,2);
|
|
||||||
|
|
||||||
DFPlayerMini_SimpleWrite($hash,$msg);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
##############
|
|
||||||
if (AttrVal($name, "requestAck", 0) == 0) {
|
|
||||||
# Write the next buffer not earlier than 20ms, which is the fastest time the DFP can process commands
|
|
||||||
InternalTimer(gettimeofday() + DFP_MIN_WAITTIME, "DFPlayerMini_HandleWriteQueue", "HandleWriteQueue:$name", 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
####################################
|
####################################
|
||||||
sub
|
sub
|
||||||
DFPlayerMini_HandleWriteQueue($)
|
DFPlayerMini_HandleWriteQueue($)
|
||||||
@ -1183,12 +1169,13 @@ DFPlayerMini_HandleWriteQueue($)
|
|||||||
#my @arr = @{$hash->{QUEUE}};
|
#my @arr = @{$hash->{QUEUE}};
|
||||||
|
|
||||||
if(@{$hash->{QUEUE}}) {
|
if(@{$hash->{QUEUE}}) {
|
||||||
my $msg= shift(@{$hash->{QUEUE}});
|
my $msg = shift(@{$hash->{QUEUE}});
|
||||||
|
|
||||||
if($msg eq "") {
|
if($msg eq "") {
|
||||||
DFPlayerMini_HandleWriteQueue("x:$name");
|
DFPlayerMini_HandleWriteQueue("x:$name");
|
||||||
} else {
|
} else {
|
||||||
DFPlayerMini_SendFromQueue($hash, $msg);
|
|
||||||
|
DFPlayerMini_SimpleWrite($hash,$msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log3 $name, 4, "$name/HandleWriteQueue: nothing to send, stopping timer";
|
Log3 $name, 4, "$name/HandleWriteQueue: nothing to send, stopping timer";
|
||||||
@ -1213,11 +1200,11 @@ DFPlayerMini_Read($)
|
|||||||
|
|
||||||
#Log3 $name, 5, "$name: DFPlayerMini_Read ($name) - received data: " . $hash->{PARTIAL};
|
#Log3 $name, 5, "$name: DFPlayerMini_Read ($name) - received data: " . $hash->{PARTIAL};
|
||||||
|
|
||||||
# Daten an den Puffer anhängen
|
# Daten an den Puffer anhängen
|
||||||
$hash->{helper}{BUFFER} .= $buf;
|
$hash->{helper}{BUFFER} .= $buf;
|
||||||
#Log3 $name, 5, "$name: DFPlayerMini_Read ($name) - current buffer content: " . unpack('H*', $hash->{helper}{BUFFER});
|
#Log3 $name, 5, "$name: DFPlayerMini_Read ($name) - current buffer content: " . unpack('H*', $hash->{helper}{BUFFER});
|
||||||
|
|
||||||
# prüfen, ob im Buffer ein vollständiger Frame mit 10 Bytes zur Verarbeitung vorhanden ist.
|
# prufen, ob im Buffer ein vollstä;ndiger Frame mit 10 Bytes zur Verarbeitung vorhanden ist.
|
||||||
while (length($hash->{helper}{BUFFER}) >= DFP_FrameLength)
|
while (length($hash->{helper}{BUFFER}) >= DFP_FrameLength)
|
||||||
{
|
{
|
||||||
if (unpack("C",substr($hash->{helper}{BUFFER},0,1)) == DFP_Start_Byte && unpack("C", substr($hash->{helper}{BUFFER},9,1)) == DFP_End_Byte) {
|
if (unpack("C",substr($hash->{helper}{BUFFER},0,1)) == DFP_Start_Byte && unpack("C", substr($hash->{helper}{BUFFER},9,1)) == DFP_End_Byte) {
|
||||||
@ -1305,10 +1292,9 @@ DFPlayerMini_Parse($$)
|
|||||||
# ToDo: Special case: DFP_C_GetNoTracksFolder will return DFP_E_TrackNotFound if the folder is empty
|
# ToDo: Special case: DFP_C_GetNoTracksFolder will return DFP_E_TrackNotFound if the folder is empty
|
||||||
readingsSingleUpdate($hash, "state", $error, 1);
|
readingsSingleUpdate($hash, "state", $error, 1);
|
||||||
} elsif ($cmd == DFP_C_Acknowledge) {
|
} elsif ($cmd == DFP_C_Acknowledge) {
|
||||||
if (AttrVal($name, "requestAck", 0)) {
|
# send next command if one is in the queue
|
||||||
# send next command
|
$hash->{waitForAck} = 0;
|
||||||
DFPlayerMini_HandleWriteQueue("x:$name");
|
DFPlayerMini_HandleWriteQueue("x:$name");
|
||||||
}
|
|
||||||
} elsif ($cmd == DFP_C_GetStorage) {
|
} elsif ($cmd == DFP_C_GetStorage) {
|
||||||
if ($par2 & 0x01) {
|
if ($par2 & 0x01) {
|
||||||
push @storage, "USB";
|
push @storage, "USB";
|
||||||
@ -1410,6 +1396,7 @@ DFPlayerMini_SimpleWrite(@)
|
|||||||
my $hexMsg = unpack ('H*', $msg);
|
my $hexMsg = unpack ('H*', $msg);
|
||||||
Log3 $name, 5, "$name SW: $hexMsg";
|
Log3 $name, 5, "$name SW: $hexMsg";
|
||||||
|
|
||||||
|
|
||||||
my $sendCmd = AttrVal($name, "sendCmd", undef);
|
my $sendCmd = AttrVal($name, "sendCmd", undef);
|
||||||
if (defined $sendCmd) {
|
if (defined $sendCmd) {
|
||||||
$sendCmd =~ s/\$msg/${hexMsg}/;
|
$sendCmd =~ s/\$msg/${hexMsg}/;
|
||||||
@ -1428,7 +1415,13 @@ DFPlayerMini_SimpleWrite(@)
|
|||||||
|
|
||||||
# remember time the command was sent
|
# remember time the command was sent
|
||||||
$hash->{LAST_SEND_TS} = gettimeofday();
|
$hash->{LAST_SEND_TS} = gettimeofday();
|
||||||
|
# evaluate requestAck byte in command
|
||||||
|
# if it is set an acknowledge must be received before
|
||||||
|
# sending the next command from the queue
|
||||||
|
$hash->{waitForAck} = unpack('C', substr($msg,4,1));
|
||||||
|
Log3 $name, 5, "current cmd waitForAck " . $hash->{waitForAck};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub
|
||||||
@ -1597,7 +1590,8 @@ sub DFPlayerMini_Notify($$)
|
|||||||
</li>
|
</li>
|
||||||
<li>requestAck<br>
|
<li>requestAck<br>
|
||||||
The DFPlayer can send a response to any command sent to it to acknowledge that is has received the command. As this increases the communication
|
The DFPlayer can send a response to any command sent to it to acknowledge that is has received the command. As this increases the communication
|
||||||
overhead it can be switched off if the communication integrity is ensured by other means.
|
overhead it can be switched off if the communication integrity is ensured by other means. If set the next command is only sent if the last one was
|
||||||
|
acknowledged by the DFPlayer. This ensures that no command is lost if the the DFPlayer is busy/sleeping.
|
||||||
</li>
|
</li>
|
||||||
<li>sendCmd<br>
|
<li>sendCmd<br>
|
||||||
A fhem command that is used to send the command data generated by this module to the DFPlayer hardware. If this is set, no other way of communication with the DFP is used.
|
A fhem command that is used to send the command data generated by this module to the DFPlayer hardware. If this is set, no other way of communication with the DFP is used.
|
||||||
@ -1821,7 +1815,8 @@ sub DFPlayerMini_Notify($$)
|
|||||||
</li>
|
</li>
|
||||||
<li>requestAck<br>
|
<li>requestAck<br>
|
||||||
Der DFPlayer kann fü jedes Kommando eine Bestätigung senden. Da das zu erhöhter Kommunikation führt kann es über dieses
|
Der DFPlayer kann fü jedes Kommando eine Bestätigung senden. Da das zu erhöhter Kommunikation führt kann es über dieses
|
||||||
Attribut abgeschaltet werden.
|
Attribut abgeschaltet werden. Wenn es eingeschaltet ist wird das nächste Kommando erst dann zum DFPlayer wenn das vorherige bestätigt wurde.
|
||||||
|
Das stellt sicher, dass kein Kommando verloren geht selbst wenn der DFPlayer ausgelastet oder im Schlafzustand ist.
|
||||||
</li>
|
</li>
|
||||||
<li>sendCmd<br>
|
<li>sendCmd<br>
|
||||||
Ein fhem Kommando das verwendet wird um ein durch diese Modul erzeugtes DFPlayer Kommando an die DFPlayer Hardware zu senden.
|
Ein fhem Kommando das verwendet wird um ein durch diese Modul erzeugtes DFPlayer Kommando an die DFPlayer Hardware zu senden.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user