Wed, 24 Oct 2018 23:15:04 +0200
Update /spiffs via internet. http://update.mbse.eu is now the update server.
0 | 1 | /** |
2 | * @file task_sdcard.c | |
3 | * @brief SD/MMC driver. This driver is for a slot for the user on | |
4 | * the front panel. It will detect an inserted card and then | |
4 | 5 | * mount it. It also detects the removal of the card and then |
6 | * unmounts it. Be carefull, only do this in the main menu. | |
0 | 7 | * Also, brew logging is handled here and finished brewlogs |
8 | * are copied to the SD card if it is mounted. | |
9 | * Recipes to import must go into the /sdcard/recipe folder | |
10 | * and have extension .xml and the contents be a beerxml file. | |
4 | 11 | * Backup and restore is also done to this card. |
0 | 12 | */ |
13 | ||
14 | ||
15 | #include "vfs_fat_internal.h" | |
16 | #include "driver/sdmmc_host.h" | |
17 | #include "driver/sdspi_host.h" | |
18 | #include "sdmmc_cmd.h" | |
19 | #include "diskio.h" | |
20 | ||
21 | #include "config.h" | |
22 | ||
23 | ||
24 | ||
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
25 | SDCARD_State *sdcard_state; ///< SD card status |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
26 | JSON_log *json_log; ///< JSON log array |
0 | 27 | EventGroupHandle_t xEventGroupSDcard; ///< SD card events. |
28 | ||
29 | static const char *TAG = "task_sdcard"; | |
30 | static sdmmc_card_t* s_card = NULL; | |
31 | static uint8_t s_pdrv = 0; | |
32 | static char * s_base_path = NULL; | |
33 | ||
34 | BYTE pdrv = 0xFF; | |
35 | ||
36 | ||
37 | #define SDCARD_HOST_SLOT VSPI_HOST ///< HSPI_HOST is used by the TFT | |
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
38 | #define SDCARD_PIN_NUM_MISO 2 ///< MISO pin |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
39 | #define SDCARD_PIN_NUM_MOSI 15 ///< MOSI pin |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
40 | #define SDCARD_PIN_NUM_CLK 14 ///< CLOCK |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
41 | #define SDCARD_PIN_NUM_CS 13 ///< Chip select pin |
0 | 42 | #define SDCARD_DMA_CHANNEL 2 ///< Channel 1 is used by the TFT |
43 | ||
44 | ||
45 | const int TASK_SDCARD_LOG_CLEAN = BIT0; ///< Clean spiffs logfile directory | |
46 | const int TASK_SDCARD_LOG_CLOSE = BIT1; ///< Close the logfile. | |
47 | ||
48 | extern time_t now; | |
49 | extern struct tm timeinfo; | |
50 | ||
51 | ||
52 | ||
53 | void log_begin(time_t t) | |
54 | { | |
55 | struct tm timeinfo; | |
56 | ||
57 | /* | |
58 | * If there is an open logfile from an crashed brew, open that one. | |
59 | */ | |
60 | if (! strlen(sdcard_state->logfile) && strlen(runtime.Logfile)) { | |
61 | sprintf(sdcard_state->logfile, "%s", runtime.Logfile); | |
62 | ESP_LOGI(TAG, "Resumed %s", sdcard_state->logfile); | |
63 | } else { | |
64 | localtime_r(&t, &timeinfo); | |
65 | if (timeinfo.tm_year > (2016 - 1900)) { | |
66 | // Valid time, construct the filename. | |
67 | strftime(sdcard_state->logfile, sizeof(sdcard_state->logfile), "br%y%m%d%H%M", &timeinfo); | |
68 | } else { | |
69 | sprintf(sdcard_state->logfile, "brewlog"); | |
70 | } | |
71 | ESP_LOGI(TAG, "Create %s", sdcard_state->logfile); | |
72 | sprintf(runtime.Logfile, "%s", sdcard_state->logfile); | |
73 | } | |
74 | } | |
75 | ||
76 | ||
77 | ||
78 | void log_close(void) | |
79 | { | |
80 | xEventGroupSetBits(xEventGroupSDcard, TASK_SDCARD_LOG_CLOSE); | |
81 | } | |
82 | ||
83 | ||
84 | ||
85 | void log_clean(void) | |
86 | { | |
87 | xEventGroupSetBits(xEventGroupSDcard, TASK_SDCARD_LOG_CLEAN); | |
88 | } | |
89 | ||
90 | ||
91 | ||
92 | void log_json(void) | |
93 | { | |
94 | char filename[32], strftime_buf[64]; | |
95 | FILE *f; | |
96 | bool addcomma = true; | |
97 | ||
98 | if (strlen(sdcard_state->logfile)) { | |
99 | sprintf(filename, "/spiffs/log/%s.json", sdcard_state->logfile); | |
100 | f = fopen(filename, "r"); | |
101 | if (f == NULL) { | |
102 | // Create the file and add the header | |
103 | f = fopen(filename, "a"); | |
104 | if (f) { | |
105 | strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); | |
106 | fprintf(f, "{\n"); | |
107 | fprintf(f, " \"brew\": [{\n"); | |
108 | fprintf(f, " \"Recipe\":\"%s\",\n", recipe.Name); | |
109 | fprintf(f, " \"Date\":\"%s\",\n", strftime_buf); | |
110 | fprintf(f, " \"brewdata\":[\n"); | |
111 | addcomma = false; | |
112 | fclose(f); | |
113 | } else { | |
114 | ESP_LOGE(TAG, "Failed to create %s error %d", filename, errno); | |
115 | return; | |
116 | } | |
117 | } else { | |
118 | fclose(f); // Was open for reading. | |
119 | } | |
120 | ||
121 | f = fopen(filename, "a"); | |
122 | if (f) { | |
123 | if (addcomma) { | |
124 | fprintf(f, ",\n"); | |
125 | } | |
126 | addcomma = true; | |
127 | fprintf(f, " {\"MLT_sp\":\"%.3f\",\"MLT_pv\":\"%.3f\",\"MLT_pwm\":\"%d\",\"MLT_tr\":\"%d\",\"Pump\":\"%d\",", | |
128 | json_log->mlt_sp, json_log->mlt_pv, json_log->mlt_power, json_log->mlt_tempreached, json_log->pump_run); | |
129 | if (json_log->hlt_sp > 0.0) { | |
130 | fprintf(f, "\"HLT_sp\":\"%.3f\",\"HLT_pv\":\"%.3f\",\"HLT_pwm\":\"%d\",", json_log->hlt_sp, json_log->hlt_pv, json_log->hlt_power); | |
131 | } | |
132 | fprintf(f, "\"Label\":\"%s\"}", json_log->time); | |
6
e84200edc852
Updated esp-ide. Removed VNC server corre encoding because no clients would use it. Enabled WiFi error logmessages. Write runtime record is now debug logging. Removed recipe.Record number, not usefull and was wrong too. Removed console print of json log data.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
133 | // printf("{\"MLT_sp\":\"%.3f\",\"MLT_pv\":\"%.3f\",\"MLT_pwm\":\"%d\",\"MLT_tr\":\"%d\",\"Pump\":\"%d\",", |
e84200edc852
Updated esp-ide. Removed VNC server corre encoding because no clients would use it. Enabled WiFi error logmessages. Write runtime record is now debug logging. Removed recipe.Record number, not usefull and was wrong too. Removed console print of json log data.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
134 | // json_log->mlt_sp, json_log->mlt_pv, json_log->mlt_power, json_log->mlt_tempreached, json_log->pump_run); |
e84200edc852
Updated esp-ide. Removed VNC server corre encoding because no clients would use it. Enabled WiFi error logmessages. Write runtime record is now debug logging. Removed recipe.Record number, not usefull and was wrong too. Removed console print of json log data.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
135 | // if (json_log->hlt_sp > 0.0) { |
e84200edc852
Updated esp-ide. Removed VNC server corre encoding because no clients would use it. Enabled WiFi error logmessages. Write runtime record is now debug logging. Removed recipe.Record number, not usefull and was wrong too. Removed console print of json log data.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
136 | // printf("\"HLT_sp\":\"%.3f\",\"HLT_pv\":\"%.3f\",\"HLT_pwm\":\"%d\",", json_log->hlt_sp, json_log->hlt_pv, json_log->hlt_power); |
e84200edc852
Updated esp-ide. Removed VNC server corre encoding because no clients would use it. Enabled WiFi error logmessages. Write runtime record is now debug logging. Removed recipe.Record number, not usefull and was wrong too. Removed console print of json log data.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
137 | // } |
e84200edc852
Updated esp-ide. Removed VNC server corre encoding because no clients would use it. Enabled WiFi error logmessages. Write runtime record is now debug logging. Removed recipe.Record number, not usefull and was wrong too. Removed console print of json log data.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
138 | // printf("\"Label\":\"%s\"}\n", json_log->time); |
0 | 139 | fclose(f); |
140 | } | |
141 | } | |
142 | } | |
143 | ||
144 | ||
145 | ||
146 | void log_annotation(int annotation_type, char *label) | |
147 | { | |
148 | char filename[32]; | |
149 | char bordercolor[9], color[9], pos[8]; | |
150 | FILE *f; | |
151 | bool addcomma = true; | |
152 | ||
153 | if (strlen(sdcard_state->logfile)) { | |
154 | sprintf(filename, "/spiffs/log/%s.anno", sdcard_state->logfile); | |
155 | ||
156 | switch (annotation_type) { | |
157 | case ANNOTATION_STAGE: snprintf(bordercolor, 8, "#8942f4"); | |
158 | snprintf(color, 8, "#00215b"); | |
159 | snprintf(pos, 7, "bottom"); | |
160 | break; | |
161 | ||
162 | case ANNOTATION_EVENT: snprintf(bordercolor, 8, "#42f445"); | |
163 | snprintf(color, 8, "#00215b"); | |
164 | snprintf(pos, 7, "top"); | |
165 | break; | |
166 | ||
167 | case ANNOTATION_SYSTEM: snprintf(bordercolor, 8, "black"); | |
168 | snprintf(color, 8, "red"); | |
169 | snprintf(pos, 7, "center"); | |
170 | break; | |
171 | } | |
172 | ||
173 | // Check if the file exists to see if we need to insert a comma. | |
174 | f = fopen(filename, "r"); | |
175 | if (f == NULL) { | |
176 | addcomma = false; | |
177 | } else { | |
178 | fclose(f); | |
179 | } | |
180 | ||
181 | f = fopen(filename, "a"); | |
182 | if (f) { | |
183 | if (addcomma) { | |
184 | fprintf(f, ",\n"); | |
185 | } | |
186 | addcomma = true; | |
187 | fprintf(f, "{\"type\":\"line\",\"mode\":\"vertical\",\"scaleID\":\"x-axis-0\",\"value\":\"%s\",\"borderColor\":\"%s\",\"borderWidth\":2,\"label\":{\"backgroundColor\":\"%s\",\"content\":\"%s\",\"position\":\"%s\",\"enabled\":true}}", json_log->time, bordercolor, color, label, pos); | |
188 | fclose(f); | |
189 | } | |
190 | } | |
191 | } | |
192 | ||
193 | ||
194 | ||
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
195 | /** |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
196 | * @brief This is a local modified version of the esp_vfs_fat_sdmmc_mount() function in |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
197 | * the FreeRTOS components library. It is here so we can better handle errors |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
198 | * for our application. |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
199 | * @param base_path The mount path |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
200 | * @param host_config SPI host configuration |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
201 | * @param slot_config Slot configuration |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
202 | * @return Error condition. |
0 | 203 | */ |
204 | esp_err_t my_vfs_fat_sdmmc_init(const char* base_path, const sdmmc_host_t* host_config, const void* slot_config) | |
205 | { | |
206 | if (s_card != NULL) { | |
207 | return ESP_ERR_INVALID_STATE; | |
208 | } | |
209 | ||
210 | // connect SDMMC driver to FATFS | |
211 | pdrv = 0xFF; | |
212 | if (ff_diskio_get_drive(&pdrv) != ESP_OK || pdrv == 0xFF) { | |
213 | ESP_LOGI(TAG, "the maximum count of volumes is already mounted"); | |
214 | return ESP_ERR_NO_MEM; | |
215 | } | |
216 | ||
217 | s_base_path = strdup(base_path); | |
218 | if (!s_base_path) { | |
219 | ESP_LOGI(TAG, "could not copy base_path"); | |
220 | return ESP_ERR_NO_MEM; | |
221 | } | |
222 | esp_err_t err = ESP_OK; | |
223 | s_card = malloc(sizeof(sdmmc_card_t)); | |
224 | if (s_card == NULL) { | |
225 | err = ESP_ERR_NO_MEM; | |
226 | goto fail; | |
227 | } | |
228 | ||
229 | err = (*host_config->init)(); | |
230 | if (err != ESP_OK) { | |
231 | ESP_LOGI(TAG, "host init returned rc=0x%x", err); | |
232 | goto fail; | |
233 | } | |
234 | ||
235 | // configure SD slot | |
236 | if (host_config->flags == SDMMC_HOST_FLAG_SPI) { | |
237 | err = sdspi_host_init_slot(host_config->slot, (const sdspi_slot_config_t*) slot_config); | |
238 | } else { | |
239 | err = sdmmc_host_init_slot(host_config->slot, (const sdmmc_slot_config_t*) slot_config); | |
240 | } | |
241 | if (err != ESP_OK) { | |
242 | ESP_LOGI(TAG, "slot_config returned rc=0x%x", err); | |
243 | goto fail; | |
244 | } | |
245 | return ESP_OK; | |
246 | ||
247 | fail: | |
248 | host_config->deinit(); | |
249 | free(s_card); | |
250 | s_card = NULL; | |
251 | return err; | |
252 | } | |
253 | ||
254 | ||
255 | ||
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
256 | /** |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
257 | * @brief Mount SD card. |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
258 | * @param base_path The mountpoint |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
259 | * @param host_config SPI host configuration |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
260 | * @param slot_config Slot configuration |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
261 | * @param mount_config Mount configuration |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
262 | * @param[out] out_card Card information |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
263 | * @return Error condition |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
264 | */ |
0 | 265 | esp_err_t my_esp_vfs_fat_sdmmc_mount(const char* base_path, |
266 | const sdmmc_host_t* host_config, | |
267 | const void* slot_config, | |
268 | const esp_vfs_fat_mount_config_t* mount_config, | |
269 | sdmmc_card_t** out_card) | |
270 | { | |
271 | FATFS* fs = NULL; | |
272 | esp_err_t err = ESP_OK; | |
273 | ||
274 | if (s_card == NULL) { | |
275 | return ESP_ERR_INVALID_STATE; | |
276 | } | |
277 | ||
278 | // probe and initialize card | |
279 | err = sdmmc_card_init(host_config, s_card); | |
280 | if (err != ESP_OK) { | |
281 | if (err != ESP_ERR_INVALID_RESPONSE) { // No card present, do not log | |
282 | ESP_LOGI(TAG, "sdmmc_card_init failed 0x(%x)", err); | |
283 | } | |
284 | goto fail; | |
285 | } | |
286 | if (out_card != NULL) { | |
287 | *out_card = s_card; | |
288 | } | |
289 | ||
290 | ff_diskio_register_sdmmc(pdrv, s_card); | |
291 | s_pdrv = pdrv; | |
292 | ESP_LOGD(TAG, "using pdrv=%i", pdrv); | |
293 | char drv[3] = {(char)('0' + pdrv), ':', 0}; | |
294 | ||
295 | // connect FATFS to VFS | |
296 | err = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); | |
297 | if (err == ESP_ERR_INVALID_STATE) { | |
298 | // it's okay, already registered with VFS | |
299 | } else if (err != ESP_OK) { | |
300 | ESP_LOGI(TAG, "esp_vfs_fat_register failed 0x(%x)", err); | |
301 | goto fail; | |
302 | } | |
303 | ||
304 | // Try to mount partition | |
305 | FRESULT res = f_mount(fs, drv, 1); | |
306 | if (res != FR_OK) { | |
307 | err = ESP_FAIL; | |
308 | ESP_LOGD(TAG, "f_mount failed (%d)", res); | |
309 | goto fail; | |
310 | } | |
311 | return ESP_OK; | |
312 | ||
313 | fail: | |
314 | if (fs) { | |
315 | f_mount(NULL, drv, 0); | |
316 | } | |
317 | esp_vfs_fat_unregister_path(base_path); | |
318 | ff_diskio_unregister(pdrv); | |
319 | return err; | |
320 | } | |
321 | ||
322 | ||
323 | ||
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
324 | /** |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
325 | * @brief Unmount a mounted SD card, |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
326 | * @return Error condition |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
327 | */ |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
328 | esp_err_t my_esp_vfs_fat_sdmmc_unmount(void) |
0 | 329 | { |
330 | if (s_card == NULL) { | |
331 | return ESP_ERR_INVALID_STATE; | |
332 | } | |
333 | // unmount | |
334 | char drv[3] = {(char)('0' + s_pdrv), ':', 0}; | |
335 | f_mount(0, drv, 0); | |
336 | return ESP_OK; | |
337 | } | |
338 | ||
339 | ||
340 | ||
341 | int FileCopy(char *ff, char *tf) | |
342 | { | |
343 | FILE *f, *t; | |
344 | uint8_t buf[512]; | |
345 | size_t bytes; | |
346 | ||
347 | f = fopen(ff, "r"); | |
348 | if (f == NULL) { | |
349 | ESP_LOGE(TAG, "FileCopy cannot open %s for read, error %d", ff, errno); | |
350 | return 1; | |
351 | } | |
352 | ||
353 | t = fopen(tf, "w+"); | |
354 | if (t == NULL) { | |
355 | ESP_LOGE(TAG, "FileCopy cannot open %s for create/write, error %d", tf, errno); | |
356 | fclose(f); | |
357 | return 1; | |
358 | } | |
359 | ||
360 | while ((bytes = fread(&buf, 1, 512, f))) { | |
361 | fwrite(&buf, 1, bytes, t); | |
362 | vTaskDelay(10 / portTICK_PERIOD_MS); | |
363 | } | |
364 | ||
365 | fclose(f); | |
366 | fclose(t); | |
367 | return 0; | |
368 | } | |
369 | ||
370 | ||
371 | ||
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
372 | /** |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
373 | * @brief Sync directories. |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
374 | * @param fromdir Source directory |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
375 | * @param todir Destination directory |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
376 | */ |
13
8f01b74bf1dd
Update /spiffs via internet. http://update.mbse.eu is now the update server.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
377 | #if 0 |
0 | 378 | void SyncDirs(char *fromdir, char *todir) |
379 | { | |
380 | char ff[64], tf[64]; | |
381 | struct stat fs, ts; | |
382 | int rc; | |
383 | ||
384 | ESP_LOGI(TAG, "SyncDirs(%s, %s)", fromdir, todir); | |
385 | ||
386 | DIR *dir = opendir(fromdir); | |
387 | struct dirent* de = readdir(dir); | |
388 | while (de) { | |
389 | if (de->d_type == DT_REG) { | |
390 | sprintf(ff, "%s/%s", fromdir, de->d_name); | |
391 | if (stat(ff, &fs) == ESP_OK) { | |
392 | ||
393 | sprintf(tf, "%s/%s", todir, de->d_name); | |
394 | if (stat(tf, &ts) != ESP_OK) { | |
395 | ts.st_size = 0; | |
396 | } | |
397 | ||
398 | if (fs.st_size && (fs.st_size != ts.st_size)) { | |
399 | rc = FileCopy(ff, tf); | |
400 | ESP_LOGI(TAG, "Copy %s to %s, %ld bytes, rc=%d", ff, todir, fs.st_size, rc); | |
401 | } | |
402 | } | |
403 | } | |
404 | de = readdir(dir); | |
405 | vTaskDelay(50 / portTICK_PERIOD_MS); | |
406 | } | |
407 | closedir(dir); | |
408 | ||
409 | /* | |
410 | * Now see if we need to remove files. | |
411 | */ | |
412 | dir = opendir(todir); | |
413 | de = readdir(dir); | |
414 | while (de) { | |
415 | sprintf(tf, "%s/%s", todir, de->d_name); | |
416 | sprintf(ff, "%s/%s", fromdir, de->d_name); | |
417 | ||
418 | if (stat(ff, &fs) != ESP_OK) { | |
419 | if (unlink(tf) == ESP_OK) { | |
420 | ESP_LOGI(TAG, "Removed %s", tf); | |
421 | } | |
422 | } | |
423 | ||
424 | de = readdir(dir); | |
425 | vTaskDelay(50 / portTICK_PERIOD_MS); | |
426 | } | |
427 | closedir(dir); | |
428 | } | |
13
8f01b74bf1dd
Update /spiffs via internet. http://update.mbse.eu is now the update server.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
429 | #endif |
0 | 430 | |
431 | ||
432 | ||
433 | void task_sdcard(void *pvParameter) | |
434 | { | |
435 | sdmmc_card_t* card; | |
436 | esp_err_t ret; | |
437 | EventBits_t uxBits; | |
438 | char filename[64]; | |
439 | ||
440 | sdcard_state = malloc(sizeof(SDCARD_State)); | |
441 | sdcard_state->host_ok = false; | |
442 | sdcard_state->card_present = false; | |
443 | sdcard_state->logfile[0] = '\0'; | |
444 | ||
445 | json_log = malloc(sizeof(JSON_log)); | |
446 | ||
447 | ESP_LOGI(TAG, "Starting SD card"); | |
448 | sdmmc_host_t host = SDSPI_HOST_DEFAULT(); | |
449 | host.slot = SDCARD_HOST_SLOT; // HSPI_HOST is in use by the TFT. | |
450 | sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT(); | |
451 | slot_config.gpio_miso = SDCARD_PIN_NUM_MISO; | |
452 | slot_config.gpio_mosi = SDCARD_PIN_NUM_MOSI; | |
453 | slot_config.gpio_sck = SDCARD_PIN_NUM_CLK; | |
454 | slot_config.gpio_cs = SDCARD_PIN_NUM_CS; | |
455 | slot_config.dma_channel = SDCARD_DMA_CHANNEL; | |
456 | // This initializes the slot without card detect (CD) and write protect (WP) signals. | |
457 | // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. | |
458 | ||
459 | /* | |
460 | * No errors from the sdmmc_cmd driver. | |
461 | */ | |
462 | esp_log_level_set("sdmmc_cmd", ESP_LOG_NONE); | |
463 | ||
464 | /* | |
465 | * Options for mounting the filesystem. | |
466 | * If format_if_mount_failed is set to true, SD card will be partitioned and | |
467 | * formatted in case when mounting fails. | |
468 | */ | |
469 | esp_vfs_fat_sdmmc_mount_config_t mount_config = { | |
470 | .format_if_mount_failed = false, | |
471 | .max_files = 5, | |
472 | .allocation_unit_size = 16 * 1024 | |
473 | }; | |
474 | ||
475 | ret = my_vfs_fat_sdmmc_init("/sdcard", &host, &slot_config); | |
476 | if (ret == ESP_OK) { | |
477 | ESP_LOGI(TAG, "SPI card interface ready"); | |
478 | sdcard_state->host_ok = true; | |
479 | } else { | |
480 | ESP_LOGE(TAG, "SPI card interface failed, abort task"); | |
481 | vTaskDelete(NULL); | |
482 | return; | |
483 | } | |
484 | ||
485 | xEventGroupSDcard = xEventGroupCreate(); | |
486 | ||
487 | /* | |
488 | * Task loop, continues check of the inserted cards. | |
489 | */ | |
490 | while (1) { | |
491 | ||
492 | if (sdcard_state->card_present == false) { | |
493 | /* | |
494 | * If the card is not mounted, try it. | |
495 | */ | |
496 | ret = my_esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); | |
497 | if (ret == ESP_OK) { | |
498 | ESP_LOGI(TAG, "SD card mounted on /sdcard"); | |
499 | sdcard_state->card_present = true; | |
500 | ||
501 | DIR* dir = opendir("/sdcard/w/log"); | |
502 | if (dir == NULL) { | |
503 | ret = mkdir("/sdcard/w/log", 0755); | |
504 | } else { | |
505 | closedir(dir); | |
506 | } | |
507 | ||
508 | ||
13
8f01b74bf1dd
Update /spiffs via internet. http://update.mbse.eu is now the update server.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
509 | // SyncDirs("/sdcard/w", "/spiffs/w"); |
8f01b74bf1dd
Update /spiffs via internet. http://update.mbse.eu is now the update server.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
510 | // SyncDirs("/sdcard/w/js", "/spiffs/w/js"); |
8f01b74bf1dd
Update /spiffs via internet. http://update.mbse.eu is now the update server.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
511 | // SyncDirs("/sdcard/w/css", "/spiffs/w/css"); |
0 | 512 | // SyncDirs("/sdcard/w/js/modl" , "/spiffs/w/js/modl"); // |
513 | // SyncDirs("/sdcard/w/js/utils", "/spiffs/w/js/utils"); | |
514 | // SyncDirs("/sdcard/w/js/zlib", "/spiffs/w/js/zlib"); | |
515 | // SyncDirs("/sdcard/w/core", "/spiffs/w/core"); | |
516 | // SyncDirs("/sdcard/w/core/input", "/spiffs/w/core/input"); | |
517 | // SyncDirs("/sdcard/w/core/util", "/spiffs/w/core/util"); | |
518 | // SyncDirs("/sdcard/w/app", "/spiffs/w/app"); | |
519 | // SyncDirs("/sdcard/w/app/images", "/spiffs/w/app/images"); | |
520 | // SyncDirs("/sdcard/w/app/locale", "/spiffs/w/app/locale"); | |
521 | // SyncDirs("/sdcard/w/app/sounds", "/spiffs/w/app/sounds"); // | |
13
8f01b74bf1dd
Update /spiffs via internet. http://update.mbse.eu is now the update server.
Michiel Broek <mbroek@mbse.eu>
parents:
6
diff
changeset
|
522 | // SyncDirs("/sdcard/w/app/styles", "/spiffs/w/app/styles"); |
0 | 523 | // SyncDirs("/sdcard/fonts", "/spiffs/fonts"); // |
524 | ||
525 | } | |
526 | } else { | |
527 | /* | |
528 | * Check if the mounted card is still in the slot. | |
529 | */ | |
530 | DIR* dir = opendir("/sdcard/w/log"); | |
531 | if (dir == NULL) { | |
532 | ESP_LOGI(TAG, "SD card missing, unmount"); | |
533 | my_esp_vfs_fat_sdmmc_unmount(); | |
534 | sdcard_state->card_present = false; | |
535 | } else { | |
536 | closedir(dir); | |
537 | } | |
538 | } | |
539 | ||
540 | uxBits = xEventGroupWaitBits(xEventGroupSDcard, | |
541 | TASK_SDCARD_LOG_CLEAN | TASK_SDCARD_LOG_CLOSE, pdFALSE, pdFALSE, 1000 / portTICK_PERIOD_MS); | |
542 | ||
543 | if (uxBits & TASK_SDCARD_LOG_CLEAN) { | |
544 | DIR *dir = opendir("/spiffs/log"); | |
545 | char lf[32]; | |
546 | ||
547 | if (dir != NULL) { | |
548 | struct dirent *de = readdir(dir); | |
549 | while (de) { | |
550 | sprintf(lf, "/spiffs/log/%s", de->d_name); | |
551 | if (unlink(lf) == ESP_OK) { | |
552 | ESP_LOGI(TAG, "Removed old %s", lf); | |
553 | } | |
554 | de = readdir(dir); | |
555 | vTaskDelay(2 / portTICK_PERIOD_MS); | |
556 | } | |
557 | closedir(dir); | |
558 | } | |
559 | xEventGroupClearBits(xEventGroupSDcard, TASK_SDCARD_LOG_CLEAN); | |
560 | } | |
561 | ||
562 | if (uxBits & TASK_SDCARD_LOG_CLOSE) { | |
563 | // Close the logfile. | |
564 | if (strlen(sdcard_state->logfile) && (sdcard_state->card_present == true)) { | |
565 | ESP_LOGI(TAG, "Closing logfile"); | |
566 | char destname[64]; | |
567 | sprintf(destname, "/sdcard/w/log"); | |
568 | int rc = mkdir(destname, 0755); | |
569 | if (rc && (errno != EEXIST)) { | |
570 | ESP_LOGE(TAG, "Cannot create %s error %d", destname, errno); | |
571 | } else { | |
572 | sprintf(filename, "/spiffs/log/%s.json", sdcard_state->logfile); | |
573 | // First close the JSON data records | |
574 | FILE *f = fopen(filename, "a+"); | |
575 | if (f) { | |
576 | fprintf(f, " ],\n"); // End of brewdata | |
577 | fprintf(f, " \"annotations\":[\n"); | |
578 | // Insert annotation records | |
579 | sprintf(destname, "/spiffs/log/%s.anno", sdcard_state->logfile); | |
580 | FILE *a = fopen(destname, "r"); | |
581 | char buf[256]; | |
582 | if (a) { | |
583 | while(true) { | |
584 | if (fgets(buf, sizeof(buf), a)) { | |
585 | fprintf(f, "%s", buf); | |
586 | } else { | |
587 | break; | |
588 | } | |
589 | } | |
590 | fclose(a); | |
591 | unlink(destname); | |
592 | } | |
593 | fprintf(f, " ]\n"); // End of annotations | |
594 | fprintf(f, " }]\n"); // End of brew | |
595 | fprintf(f, "}\n"); | |
596 | fclose(f); | |
597 | } | |
598 | sprintf(destname, "/sdcard/w/log/%s.json", sdcard_state->logfile); | |
599 | if (FileCopy(filename, destname) == 0) { | |
600 | ESP_LOGI(TAG, "JSON file copied to %s", destname); | |
601 | unlink(filename); | |
602 | } | |
603 | } | |
604 | } | |
605 | sdcard_state->logfile[0] = '\0'; // Clear logfile name | |
606 | runtime.Logfile[0] = '\0'; | |
607 | xEventGroupClearBits(xEventGroupSDcard, TASK_SDCARD_LOG_CLOSE); | |
608 | } | |
609 | } | |
610 | } | |
611 | ||
612 |