|
|
|
/**
|
|
|
|
* The default upload handler implementation.
|
|
|
|
* @file AutoConnectUploadImpl.h
|
|
|
|
* @author hieromon@gmail.com
|
|
|
|
* @version 0.9.9
|
|
|
|
* @date 2019-05-25
|
|
|
|
* @copyright MIT license.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _AUTOCONNECTUPLOADIMPL_H_
|
|
|
|
#define _AUTOCONNECTUPLOADIMPL_H_
|
|
|
|
|
|
|
|
#if defined(ARDUINO_ARCH_ESP8266)
|
|
|
|
#include <core_version.h>
|
|
|
|
#include <ESP8266WiFi.h>
|
|
|
|
#elif defined(ARDUINO_ARCH_ESP32)
|
|
|
|
#include <WiFi.h>
|
|
|
|
#include <SPIFFS.h>
|
|
|
|
#endif
|
|
|
|
#include <SPI.h>
|
|
|
|
#include <SD.h>
|
|
|
|
#define FS_NO_GLOBALS
|
|
|
|
#include <FS.h>
|
|
|
|
|
|
|
|
// Types branching to be code commonly for the file system classes with
|
|
|
|
// ESP8266 and ESP32.
|
|
|
|
#if defined(ARDUINO_ARCH_ESP8266)
|
|
|
|
typedef fs::FS SPIFFST; // SPIFFS:File system class
|
|
|
|
typedef fs::File SPIFileT; // SPIFFS:File class
|
|
|
|
typedef SDClass SDClassT; // SD:File system class
|
|
|
|
typedef File SDFileT; // SD:File class
|
|
|
|
#elif defined(ARDUINO_ARCH_ESP32)
|
|
|
|
typedef fs::SPIFFSFS SPIFFST;
|
|
|
|
typedef fs::File SPIFileT;
|
|
|
|
typedef fs::SDFS SDClassT;
|
|
|
|
typedef SDFile SDFileT;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "AutoConnectDefs.h"
|
|
|
|
#include "AutoConnectUpload.h"
|
|
|
|
|
|
|
|
namespace AutoConnectUtil {
|
|
|
|
AC_HAS_FUNC(end);
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
typename std::enable_if<AutoConnectUtil::has_func_end<T>::value, void>::type end(T* media) {
|
|
|
|
media->end();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
typename std::enable_if<!AutoConnectUtil::has_func_end<T>::value, void>::type end(T* media) {
|
|
|
|
(void)(media);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles the default upload process depending on the upload status.
|
|
|
|
* This handler function supports the status of UPLOAD_FILE_START,
|
|
|
|
* UPLOAD_FILE_WRITE, UPLOAD_FILE_END and calls open, write and
|
|
|
|
* close processing respectively.
|
|
|
|
* @param requestUri A reference to the upload request uri.
|
|
|
|
* @param upload A reference of HTTPUpload entity.
|
|
|
|
*/
|
|
|
|
void AutoConnectUploadHandler::upload(const String& requestUri, const HTTPUpload& upload) {
|
|
|
|
AC_UNUSED(requestUri);
|
|
|
|
switch (upload.status) {
|
|
|
|
case UPLOAD_FILE_START: {
|
|
|
|
String absFilename = "/" + upload.filename;
|
|
|
|
(void)_open(absFilename.c_str(), "w");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case UPLOAD_FILE_WRITE:
|
|
|
|
(void)_write(upload.buf, (const size_t)upload.currentSize);
|
|
|
|
break;
|
|
|
|
case UPLOAD_FILE_ABORTED:
|
|
|
|
case UPLOAD_FILE_END:
|
|
|
|
_close();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Default handler for uploading to the standard SPIFFS class embedded in the core.
|
|
|
|
class AutoConnectUploadFS : public AutoConnectUploadHandler {
|
|
|
|
public:
|
|
|
|
explicit AutoConnectUploadFS(SPIFFST& media) : _media(&media) {}
|
|
|
|
~AutoConnectUploadFS() { _close(); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool _open(const char* filename, const char* mode) override {
|
|
|
|
#if defined(ARDUINO_ARCH_ESP8266)
|
|
|
|
if (_media->begin()) {
|
|
|
|
#elif defined(ARDUINO_ARCH_ESP32)
|
|
|
|
if (_media->begin(true)) {
|
|
|
|
#endif
|
|
|
|
_file = _media->open(filename, mode);
|
|
|
|
return _file != false;
|
|
|
|
}
|
|
|
|
AC_DBG("SPIFFS mount failed\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t _write(const uint8_t* buf, const size_t size) override {
|
|
|
|
if (_file)
|
|
|
|
return _file.write(buf, size);
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _close(void) override {
|
|
|
|
if (_file)
|
|
|
|
_file.close();
|
|
|
|
_media->end();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SPIFFST* _media;
|
|
|
|
SPIFileT _file;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Fix to be compatibility with backward for ESP8266 core 2.5.1 or later
|
|
|
|
// SD pin assignment for AutoConnectFile
|
|
|
|
#ifndef AUTOCONNECT_SD_CS
|
|
|
|
#if defined(ARDUINO_ARCH_ESP8266)
|
|
|
|
#ifndef SD_CHIP_SELECT_PIN
|
|
|
|
#define SD_CHIP_SELECT_PIN SS
|
|
|
|
#endif
|
|
|
|
#define AUTOCONNECT_SD_CS SD_CHIP_SELECT_PIN
|
|
|
|
#elif defined(ARDUINO_ARCH_ESP32)
|
|
|
|
#define AUTOCONNECT_SD_CS SS
|
|
|
|
#endif
|
|
|
|
#endif // !AUTOCONNECT_SD_CS
|
|
|
|
// Derivation of SCK frequency and ensuring SD.begin compatibility
|
|
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
|
|
#if defined(SD_SCK_HZ)
|
|
|
|
#define AC_SD_SPEED(s) SD_SCK_HZ(s)
|
|
|
|
#else
|
|
|
|
#define AC_SD_SPEED(s) s
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Default handler for uploading to the standard SD class embedded in the core.
|
|
|
|
class AutoConnectUploadSD : public AutoConnectUploadHandler {
|
|
|
|
public:
|
|
|
|
explicit AutoConnectUploadSD(SDClassT& media, const uint8_t cs = AUTOCONNECT_SD_CS, const uint32_t speed = AUTOCONNECT_SD_SPEED) : _media(&media), _cs(cs), _speed(speed) {}
|
|
|
|
~AutoConnectUploadSD() { _close(); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
bool _open(const char* filename, const char* mode) override {
|
|
|
|
const char* sdVerify;
|
|
|
|
#if defined(ARDUINO_ARCH_ESP8266)
|
|
|
|
if (_media->begin(_cs, AC_SD_SPEED(_speed))) {
|
|
|
|
uint8_t oflag = *mode == 'w' ? FILE_WRITE : FILE_READ;
|
|
|
|
uint8_t sdType = _media->type();
|
|
|
|
switch (sdType) {
|
|
|
|
case 1: // SD_CARD_TYPE_SD1
|
|
|
|
sdVerify = (const char*)"MMC";
|
|
|
|
break;
|
|
|
|
case 2: // SD_CARD_TYPE_SD2
|
|
|
|
sdVerify = (const char*)"SDSC";
|
|
|
|
break;
|
|
|
|
case 3: // SD_CARD_TYPE_SDHC
|
|
|
|
sdVerify = (const char*)"SDHC";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sdVerify = (const char*)"UNKNOWN";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#elif defined(ARDUINO_ARCH_ESP32)
|
|
|
|
if (_media->begin(_cs, SPI, _speed)) {
|
|
|
|
const char* oflag = mode;
|
|
|
|
uint8_t sdType = _media->cardType();
|
|
|
|
switch (sdType) {
|
|
|
|
case CARD_NONE:
|
|
|
|
sdVerify = (const char*)"No card";
|
|
|
|
break;
|
|
|
|
case CARD_MMC:
|
|
|
|
sdVerify = (const char*)"MMC";
|
|
|
|
break;
|
|
|
|
case CARD_SD:
|
|
|
|
sdVerify = (const char*)"SDSC";
|
|
|
|
break;
|
|
|
|
case CARD_SDHC:
|
|
|
|
sdVerify = (const char*)"SDHC";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sdVerify = (const char*)"UNKNOWN";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
AC_DBG("%s mounted\n", sdVerify);
|
|
|
|
_file = _media->open(filename, oflag);
|
|
|
|
return _file != false;
|
|
|
|
}
|
|
|
|
AC_DBG("SD mount failed\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t _write(const uint8_t* buf, const size_t size) override {
|
|
|
|
if (_file)
|
|
|
|
return _file.write(buf, size);
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _close(void) override {
|
|
|
|
if (_file)
|
|
|
|
_file.close();
|
|
|
|
AutoConnectUtil::end<SDClassT>(_media);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SDClassT* _media;
|
|
|
|
SDFileT _file;
|
|
|
|
uint8_t _cs;
|
|
|
|
uint32_t _speed;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // !_AUTOCONNECTUPLOADIMPL_H_
|