ESPHome  2025.2.0
dfplayer.cpp
Go to the documentation of this file.
1 #include "dfplayer.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace dfplayer {
6 
7 static const char *const TAG = "dfplayer";
8 
9 void DFPlayer::next() {
10  this->ack_set_is_playing_ = true;
11  ESP_LOGD(TAG, "Playing next track");
12  this->send_cmd_(0x01);
13 }
14 
16  this->ack_set_is_playing_ = true;
17  ESP_LOGD(TAG, "Playing previous track");
18  this->send_cmd_(0x02);
19 }
20 void DFPlayer::play_mp3(uint16_t file) {
21  this->ack_set_is_playing_ = true;
22  ESP_LOGD(TAG, "Playing file %d in mp3 folder", file);
23  this->send_cmd_(0x12, file);
24 }
25 
26 void DFPlayer::play_file(uint16_t file) {
27  this->ack_set_is_playing_ = true;
28  ESP_LOGD(TAG, "Playing file %d", file);
29  this->send_cmd_(0x03, file);
30 }
31 
32 void DFPlayer::play_file_loop(uint16_t file) {
33  this->ack_set_is_playing_ = true;
34  ESP_LOGD(TAG, "Playing file %d in loop", file);
35  this->send_cmd_(0x08, file);
36 }
37 
38 void DFPlayer::play_folder_loop(uint16_t folder) {
39  this->ack_set_is_playing_ = true;
40  ESP_LOGD(TAG, "Playing folder %d in loop", folder);
41  this->send_cmd_(0x17, folder);
42 }
43 
45  ESP_LOGD(TAG, "Increasing volume");
46  this->send_cmd_(0x04);
47 }
48 
50  ESP_LOGD(TAG, "Decreasing volume");
51  this->send_cmd_(0x05);
52 }
53 
55  ESP_LOGD(TAG, "Setting device to %d", device);
56  this->send_cmd_(0x09, device);
57 }
58 
59 void DFPlayer::set_volume(uint8_t volume) {
60  ESP_LOGD(TAG, "Setting volume to %d", volume);
61  this->send_cmd_(0x06, volume);
62 }
63 
65  ESP_LOGD(TAG, "Setting EQ to %d", preset);
66  this->send_cmd_(0x07, preset);
67 }
68 
70  this->ack_reset_is_playing_ = true;
71  ESP_LOGD(TAG, "Putting DFPlayer to sleep");
72  this->send_cmd_(0x0A);
73 }
74 
76  this->ack_reset_is_playing_ = true;
77  ESP_LOGD(TAG, "Resetting DFPlayer");
78  this->send_cmd_(0x0C);
79 }
80 
82  this->ack_set_is_playing_ = true;
83  ESP_LOGD(TAG, "Starting playback");
84  this->send_cmd_(0x0D);
85 }
86 
88  this->ack_reset_is_playing_ = true;
89  ESP_LOGD(TAG, "Pausing playback");
90  this->send_cmd_(0x0E);
91 }
92 
94  this->ack_reset_is_playing_ = true;
95  ESP_LOGD(TAG, "Stopping playback");
96  this->send_cmd_(0x16);
97 }
98 
100  this->ack_set_is_playing_ = true;
101  ESP_LOGD(TAG, "Playing random file");
102  this->send_cmd_(0x18);
103 }
104 
105 void DFPlayer::play_folder(uint16_t folder, uint16_t file) {
106  ESP_LOGD(TAG, "Playing file %d in folder %d", file, folder);
107  if (folder < 100 && file < 256) {
108  this->ack_set_is_playing_ = true;
109  this->send_cmd_(0x0F, (uint8_t) folder, (uint8_t) file);
110  } else if (folder <= 15 && file <= 3000) {
111  this->ack_set_is_playing_ = true;
112  this->send_cmd_(0x14, (((uint16_t) folder) << 12) | file);
113  } else {
114  ESP_LOGE(TAG, "Cannot play folder %d file %d.", folder, file);
115  }
116 }
117 
118 void DFPlayer::send_cmd_(uint8_t cmd, uint16_t argument) {
119  uint8_t buffer[10]{0x7e, 0xff, 0x06, cmd, 0x01, (uint8_t) (argument >> 8), (uint8_t) argument, 0x00, 0x00, 0xef};
120  uint16_t checksum = 0;
121  for (uint8_t i = 1; i < 7; i++)
122  checksum += buffer[i];
123  checksum = -checksum;
124  buffer[7] = checksum >> 8;
125  buffer[8] = (uint8_t) checksum;
126 
127  this->sent_cmd_ = cmd;
128 
129  ESP_LOGV(TAG, "Send Command %#02x arg %#04x", cmd, argument);
130  this->write_array(buffer, 10);
131 }
132 
134  // Read message
135  while (this->available()) {
136  uint8_t byte;
137  this->read_byte(&byte);
138 
140  this->read_pos_ = 0;
141 
142  switch (this->read_pos_) {
143  case 0: // Start mark
144  if (byte != 0x7E)
145  continue;
146  break;
147  case 1: // Version
148  if (byte != 0xFF) {
149  ESP_LOGW(TAG, "Expected Version 0xFF, got %#02x", byte);
150  this->read_pos_ = 0;
151  continue;
152  }
153  break;
154  case 2: // Buffer length
155  if (byte != 0x06) {
156  ESP_LOGW(TAG, "Expected Buffer length 0x06, got %#02x", byte);
157  this->read_pos_ = 0;
158  continue;
159  }
160  break;
161  case 9: // End byte
162 #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
163  char byte_sequence[100];
164  byte_sequence[0] = '\0';
165  for (size_t i = 0; i < this->read_pos_ + 1; ++i) {
166  snprintf(byte_sequence + strlen(byte_sequence), sizeof(byte_sequence) - strlen(byte_sequence), "%02X ",
167  this->read_buffer_[i]);
168  }
169  ESP_LOGVV(TAG, "Received byte sequence: %s", byte_sequence);
170 #endif
171  if (byte != 0xEF) {
172  ESP_LOGW(TAG, "Expected end byte 0xEF, got %#02x", byte);
173  this->read_pos_ = 0;
174  continue;
175  }
176  // Parse valid received command
177  uint8_t cmd = this->read_buffer_[3];
178  uint16_t argument = (this->read_buffer_[5] << 8) | this->read_buffer_[6];
179 
180  ESP_LOGV(TAG, "Received message cmd: %#02x arg %#04x", cmd, argument);
181 
182  switch (cmd) {
183  case 0x3A:
184  if (argument == 1) {
185  ESP_LOGI(TAG, "USB loaded");
186  } else if (argument == 2) {
187  ESP_LOGI(TAG, "TF Card loaded");
188  }
189  break;
190  case 0x3B:
191  if (argument == 1) {
192  ESP_LOGI(TAG, "USB unloaded");
193  } else if (argument == 2) {
194  ESP_LOGI(TAG, "TF Card unloaded");
195  }
196  break;
197  case 0x3F:
198  if (argument == 1) {
199  ESP_LOGI(TAG, "USB available");
200  } else if (argument == 2) {
201  ESP_LOGI(TAG, "TF Card available");
202  } else if (argument == 3) {
203  ESP_LOGI(TAG, "USB, TF Card available");
204  }
205  break;
206  case 0x40:
207  ESP_LOGV(TAG, "Nack");
208  this->ack_set_is_playing_ = false;
209  this->ack_reset_is_playing_ = false;
210  switch (argument) {
211  case 0x01:
212  ESP_LOGE(TAG, "Module is busy or uninitialized");
213  break;
214  case 0x02:
215  ESP_LOGE(TAG, "Module is in sleep mode");
216  break;
217  case 0x03:
218  ESP_LOGE(TAG, "Serial receive error");
219  break;
220  case 0x04:
221  ESP_LOGE(TAG, "Checksum incorrect");
222  break;
223  case 0x05:
224  ESP_LOGE(TAG, "Specified track is out of current track scope");
225  this->is_playing_ = false;
226  break;
227  case 0x06:
228  ESP_LOGE(TAG, "Specified track is not found");
229  this->is_playing_ = false;
230  break;
231  case 0x07:
232  ESP_LOGE(TAG, "Insertion error (an inserting operation only can be done when a track is being played)");
233  break;
234  case 0x08:
235  ESP_LOGE(TAG, "SD card reading failed (SD card pulled out or damaged)");
236  break;
237  case 0x09:
238  ESP_LOGE(TAG, "Entered into sleep mode");
239  this->is_playing_ = false;
240  break;
241  }
242  break;
243  case 0x41:
244  ESP_LOGV(TAG, "Ack ok");
245  this->is_playing_ |= this->ack_set_is_playing_;
246  this->is_playing_ &= !this->ack_reset_is_playing_;
247  this->ack_set_is_playing_ = false;
248  this->ack_reset_is_playing_ = false;
249  break;
250  case 0x3C:
251  ESP_LOGV(TAG, "Playback finished (USB drive)");
252  this->is_playing_ = false;
253  this->on_finished_playback_callback_.call();
254  case 0x3D:
255  ESP_LOGV(TAG, "Playback finished (SD card)");
256  this->is_playing_ = false;
257  this->on_finished_playback_callback_.call();
258  break;
259  default:
260  ESP_LOGE(TAG, "Received unknown cmd %#02x arg %#04x", cmd, argument);
261  }
262  this->sent_cmd_ = 0;
263  this->read_pos_ = 0;
264  continue;
265  }
266  this->read_buffer_[this->read_pos_] = byte;
267  this->read_pos_++;
268  }
269 }
271  ESP_LOGCONFIG(TAG, "DFPlayer:");
272  this->check_uart_settings(9600);
273 }
274 
275 } // namespace dfplayer
276 } // namespace esphome
void send_cmd_(uint8_t cmd, uint16_t argument=0)
Definition: dfplayer.cpp:118
void dump_config() override
Definition: dfplayer.cpp:270
CallbackManager< void()> on_finished_playback_callback_
Definition: dfplayer.h:72
void write_array(const uint8_t *data, size_t len)
Definition: uart.h:21
void play_file_loop(uint16_t file)
Definition: dfplayer.cpp:32
uint8_t checksum
Definition: bl0906.h:210
void set_device(Device device)
Definition: dfplayer.cpp:54
void play_file(uint16_t file)
Definition: dfplayer.cpp:26
void play_folder_loop(uint16_t folder)
Definition: dfplayer.cpp:38
void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits=1, UARTParityOptions parity=UART_CONFIG_PARITY_NONE, uint8_t data_bits=8)
Check that the configuration of the UART bus matches the provided values and otherwise print a warnin...
Definition: uart.cpp:13
bool read_byte(uint8_t *data)
Definition: uart.h:29
const size_t DFPLAYER_READ_BUFFER_LENGTH
Definition: dfplayer.h:7
void play_folder(uint16_t folder, uint16_t file)
Definition: dfplayer.cpp:105
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void set_eq(EqPreset preset)
Definition: dfplayer.cpp:64
void set_volume(uint8_t volume)
Definition: dfplayer.cpp:59
char read_buffer_[DFPLAYER_READ_BUFFER_LENGTH]
Definition: dfplayer.h:65
void play_mp3(uint16_t file)
Definition: dfplayer.cpp:20
ClimatePreset preset
Definition: climate.h:578
stm32_cmd_t * cmd
Definition: stm32flash.h:96