ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
dfplayer.cpp
Go to the documentation of this file.
1#include "dfplayer.h"
3#include "esphome/core/log.h"
4
6
7ESPHOME_LOG_TAG(TAG, "dfplayer");
8
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}
20void 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
26void 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
32void 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
38void 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
59void 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
106 uint16_t arg = enable ? 0x00 : 0x01;
107 ESP_LOGD(TAG, "Setting current track repeat to %s",
108 enable ? LOG_STR_LITERAL("enabled") : LOG_STR_LITERAL("disabled"));
109 this->send_cmd_(0x19, arg);
110}
111
112void DFPlayer::play_folder(uint16_t folder, uint16_t file) {
113 ESP_LOGD(TAG, "Playing file %d in folder %d", file, folder);
114 if (folder < 100 && file < 256) {
115 this->ack_set_is_playing_ = true;
116 this->send_cmd_(0x0F, (uint8_t) folder, (uint8_t) file);
117 } else if (folder <= 15 && file <= 3000) {
118 this->ack_set_is_playing_ = true;
119 this->send_cmd_(0x14, (((uint16_t) folder) << 12) | file);
120 } else {
121 ESP_LOGE(TAG, "Cannot play folder %d file %d.", folder, file);
122 }
123}
124
125void DFPlayer::send_cmd_(uint8_t cmd, uint16_t argument) {
126 uint8_t buffer[10]{0x7e, 0xff, 0x06, cmd, 0x01, (uint8_t) (argument >> 8), (uint8_t) argument, 0x00, 0x00, 0xef};
127 const uint16_t checksum = static_cast<uint16_t>(-sum16_bytes(buffer + 1, 6));
128 buffer[7] = checksum >> 8;
129 buffer[8] = (uint8_t) checksum;
130
131 this->sent_cmd_ = cmd;
132
133 ESP_LOGV(TAG, "Send Command %#02x arg %#04x", cmd, argument);
134 this->write_array(buffer, 10);
135}
136
138 // Read all available bytes in batches to reduce UART call overhead.
139 size_t avail = this->available();
140 uint8_t buf[64];
141 while (avail > 0) {
142 size_t to_read = std::min(avail, sizeof(buf));
143 if (!this->read_array(buf, to_read)) {
144 break;
145 }
146 avail -= to_read;
147 for (size_t bi = 0; bi < to_read; bi++) {
148 uint8_t byte = buf[bi];
149
151 this->read_pos_ = 0;
152
153 switch (this->read_pos_) {
154 case 0: // Start mark
155 if (byte != 0x7E)
156 continue;
157 break;
158 case 1: // Version
159 if (byte != 0xFF) {
160 ESP_LOGW(TAG, "Expected Version 0xFF, got %#02x", byte);
161 this->read_pos_ = 0;
162 continue;
163 }
164 break;
165 case 2: // Buffer length
166 if (byte != 0x06) {
167 ESP_LOGW(TAG, "Expected Buffer length 0x06, got %#02x", byte);
168 this->read_pos_ = 0;
169 continue;
170 }
171 break;
172 case 9: // End byte
173#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
174 char byte_sequence[100];
175 byte_sequence[0] = '\0';
176 for (size_t i = 0; i < this->read_pos_ + 1; ++i) {
177 snprintf(byte_sequence + strlen(byte_sequence), sizeof(byte_sequence) - strlen(byte_sequence), "%02X ",
178 this->read_buffer_[i]);
179 }
180 ESP_LOGVV(TAG, "Received byte sequence: %s", byte_sequence);
181#endif
182 if (byte != 0xEF) {
183 ESP_LOGW(TAG, "Expected end byte 0xEF, got %#02x", byte);
184 this->read_pos_ = 0;
185 continue;
186 }
187 // Parse valid received command
188 uint8_t cmd = this->read_buffer_[3];
189 uint16_t argument = (this->read_buffer_[5] << 8) | this->read_buffer_[6];
190
191 ESP_LOGV(TAG, "Received message cmd: %#02x arg %#04x", cmd, argument);
192
193 switch (cmd) {
194 case 0x3A:
195 if (argument == 1) {
196 ESP_LOGI(TAG, "USB loaded");
197 } else if (argument == 2) {
198 ESP_LOGI(TAG, "TF Card loaded");
199 }
200 break;
201 case 0x3B:
202 if (argument == 1) {
203 ESP_LOGI(TAG, "USB unloaded");
204 } else if (argument == 2) {
205 ESP_LOGI(TAG, "TF Card unloaded");
206 }
207 break;
208 case 0x3F:
209 if (argument == 1) {
210 ESP_LOGI(TAG, "USB available");
211 } else if (argument == 2) {
212 ESP_LOGI(TAG, "TF Card available");
213 } else if (argument == 3) {
214 ESP_LOGI(TAG, "USB, TF Card available");
215 }
216 break;
217 case 0x40:
218 ESP_LOGV(TAG, "Nack");
219 this->ack_set_is_playing_ = false;
220 this->ack_reset_is_playing_ = false;
221 switch (argument) {
222 case 0x01:
223 ESP_LOGE(TAG, "Module is busy or uninitialized");
224 break;
225 case 0x02:
226 ESP_LOGE(TAG, "Module is in sleep mode");
227 break;
228 case 0x03:
229 ESP_LOGE(TAG, "Serial receive error");
230 break;
231 case 0x04:
232 ESP_LOGE(TAG, "Checksum incorrect");
233 break;
234 case 0x05:
235 ESP_LOGE(TAG, "Specified track is out of current track scope");
236 this->is_playing_ = false;
237 break;
238 case 0x06:
239 ESP_LOGE(TAG, "Specified track is not found");
240 this->is_playing_ = false;
241 break;
242 case 0x07:
243 ESP_LOGE(TAG,
244 "Insertion error (an inserting operation only can be done when a track is being played)");
245 break;
246 case 0x08:
247 ESP_LOGE(TAG, "SD card reading failed (SD card pulled out or damaged)");
248 break;
249 case 0x09:
250 ESP_LOGE(TAG, "Entered into sleep mode");
251 this->is_playing_ = false;
252 break;
253 default:
254 break;
255 }
256 break;
257 case 0x41:
258 ESP_LOGV(TAG, "Ack ok");
259 this->is_playing_ |= this->ack_set_is_playing_;
260 this->is_playing_ &= !this->ack_reset_is_playing_;
261 this->ack_set_is_playing_ = false;
262 this->ack_reset_is_playing_ = false;
263 break;
264 case 0x3C:
265 ESP_LOGV(TAG, "Playback finished (USB drive)");
266 this->is_playing_ = false;
268 break;
269 case 0x3D:
270 ESP_LOGV(TAG, "Playback finished (SD card)");
271 this->is_playing_ = false;
273 break;
274 default:
275 ESP_LOGE(TAG, "Received unknown cmd %#02x arg %#04x", cmd, argument);
276 }
277 this->sent_cmd_ = 0;
278 this->read_pos_ = 0;
279 continue;
280 }
281 this->read_buffer_[this->read_pos_] = byte;
282 this->read_pos_++;
283 }
284 }
285}
286void DFPlayer::dump_config() { ESP_LOGCONFIG(TAG, "DFPlayer:"); }
287
288} // namespace esphome::dfplayer
uint8_t checksum
Definition bl0906.h:3
void dump_config() override
Definition dfplayer.cpp:286
CallbackManager< void()> on_finished_playback_callback_
Definition dfplayer.h:77
void send_cmd_(uint8_t cmd, uint16_t argument=0)
Definition dfplayer.cpp:125
void set_volume(uint8_t volume)
Definition dfplayer.cpp:59
void play_folder(uint16_t folder, uint16_t file)
Definition dfplayer.cpp:112
void play_file_loop(uint16_t file)
Definition dfplayer.cpp:32
void set_device(Device device)
Definition dfplayer.cpp:54
void play_file(uint16_t file)
Definition dfplayer.cpp:26
void set_current_track_repeat(bool enable)
Definition dfplayer.cpp:105
void set_eq(EqPreset preset)
Definition dfplayer.cpp:64
char read_buffer_[DFPLAYER_READ_BUFFER_LENGTH]
Definition dfplayer.h:70
void play_folder_loop(uint16_t folder)
Definition dfplayer.cpp:38
void play_mp3(uint16_t file)
Definition dfplayer.cpp:20
optional< std::array< uint8_t, N > > read_array()
Definition uart.h:43
void write_array(const uint8_t *data, size_t len)
Definition uart.h:30
ClimatePreset preset
Definition climate.h:8
const size_t DFPLAYER_READ_BUFFER_LENGTH
Definition dfplayer.h:7
uint32_t buffer
Definition gif.cpp:50
ESPHOME_LOG_TAG(TAG, "dfplayer")
constexpr uint16_t sum16_bytes(const uint8_t *data, size_t len, uint16_t sum=0)
Add up the bytes of data with size len, truncated to 16 bits.
Definition helpers.h:899