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