diff --git a/fhem/CHANGED b/fhem/CHANGED index ed1ea5c30..e14740360 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # 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. + - feature: 00_DFPlayerMini: improved requestAck handling - change: 49_SSCam: new version 2.1.3, change of internal processes, new get scanVirgin command - bugfix: 73_ElectricityCalculator: SiPrefix multiplier instead divider diff --git a/fhem/FHEM/00_DFPlayerMini.pm b/fhem/FHEM/00_DFPlayerMini.pm index c60d5a38c..c218a80c7 100644 --- a/fhem/FHEM/00_DFPlayerMini.pm +++ b/fhem/FHEM/00_DFPlayerMini.pm @@ -287,6 +287,7 @@ DFPlayerMini_Define($$) $ret = DevIo_OpenDev($hash, 0, "DFPlayerMini_DoInit", 'DFPlayerMini_Connect'); } else { + DFPlayerMini_DoInit($hash); $hash->{DevState} = 'initialized'; readingsSingleUpdate($hash, "state", "opened", 1); } @@ -361,7 +362,7 @@ DFPlayerMini_createCmd($$;$$) $par2 = 0 if !defined $par2; my $requestAck = AttrVal($hash->{NAME}, "requestAck", 0) || $cmd == DFP_C_Acknowledge; - + 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); @@ -1046,6 +1047,7 @@ DFPlayerMini_DoInit($) @{$hash->{PLAYQUEUE}} = (); @{$hash->{TTSQUEUE}} = (); + $hash->{waitForAck} = 0; return; #return undef; @@ -1138,7 +1140,7 @@ sub DFPlayerMini_AddSendQueue($$) #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 DFPlayerMini_SimpleWrite($hash, $msg); } else { @@ -1146,32 +1148,16 @@ sub DFPlayerMini_AddSendQueue($$) push(@{$hash->{QUEUE}}, $msg); #Log3 $hash , 5, Dumper($hash->{QUEUE}); - - InternalTimer(gettimeofday() + DFP_MIN_WAITTIME, "DFPlayerMini_HandleWriteQueue", "HandleWriteQueue:$name", 1); + if ($hash->{waitForAck} == 0) { + # 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 DFPlayerMini_HandleWriteQueue($) @@ -1183,12 +1169,13 @@ DFPlayerMini_HandleWriteQueue($) #my @arr = @{$hash->{QUEUE}}; if(@{$hash->{QUEUE}}) { - my $msg= shift(@{$hash->{QUEUE}}); + my $msg = shift(@{$hash->{QUEUE}}); if($msg eq "") { DFPlayerMini_HandleWriteQueue("x:$name"); } else { - DFPlayerMini_SendFromQueue($hash, $msg); + + DFPlayerMini_SimpleWrite($hash,$msg); } } else { 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}; - # Daten an den Puffer anhängen + # Daten an den Puffer anhängen $hash->{helper}{BUFFER} .= $buf; #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) { 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 readingsSingleUpdate($hash, "state", $error, 1); } elsif ($cmd == DFP_C_Acknowledge) { - if (AttrVal($name, "requestAck", 0)) { - # send next command - DFPlayerMini_HandleWriteQueue("x:$name"); - } + # send next command if one is in the queue + $hash->{waitForAck} = 0; + DFPlayerMini_HandleWriteQueue("x:$name"); } elsif ($cmd == DFP_C_GetStorage) { if ($par2 & 0x01) { push @storage, "USB"; @@ -1410,6 +1396,7 @@ DFPlayerMini_SimpleWrite(@) my $hexMsg = unpack ('H*', $msg); Log3 $name, 5, "$name SW: $hexMsg"; + my $sendCmd = AttrVal($name, "sendCmd", undef); if (defined $sendCmd) { $sendCmd =~ s/\$msg/${hexMsg}/; @@ -1428,7 +1415,13 @@ DFPlayerMini_SimpleWrite(@) # remember time the command was sent $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 @@ -1597,7 +1590,8 @@ sub DFPlayerMini_Notify($$)