diff --git a/lib/basic/Dtypes.h b/lib/basic/Dtypes.h index 577af81..3fd8b21 100644 --- a/lib/basic/Dtypes.h +++ b/lib/basic/Dtypes.h @@ -17,4 +17,4 @@ inline String toString(const T & t) { return String(t); } -#define assert(EXPRESSION, MSG) ((EXPRESSION) ? (void)0 : _assert(#EXPRESSION, #MSG, __FILE__, __LINE__)) \ No newline at end of file +#define assert_msg(EXPRESSION, MSG) ((EXPRESSION) ? (void)0 : _assert(#EXPRESSION, #MSG, __FILE__, __LINE__)) diff --git a/lib/basic/FilesystemAbstraction.h b/lib/basic/FilesystemAbstraction.h new file mode 100644 index 0000000..e89b898 --- /dev/null +++ b/lib/basic/FilesystemAbstraction.h @@ -0,0 +1,181 @@ +#pragma once + +#ifdef PLATFORM_ESP32 +#include "SPIFFS.h" + +namespace portablefs +{ + using File = ::File; + + class Dir + { + public: + Dir() {} + Dir(const String &path) + : root_(SPIFFS.open(path)) + { + //next(); + } + + bool next() + { + file_ = root_.openNextFile(); + return file_; + } + + bool isFile() + { + return !file_.isDirectory(); + } + + bool isDirectory() + { + return file_.isDirectory(); + } + + String fileName() const + { + return file_.name(); + } + + size_t fileSize() const + { + return file_.size(); + } + + private: + File root_; + File file_; + }; + + inline Dir openDir(const String &path) + { + return Dir(path); + } + + inline File open(const char *name, const char *mode) + { + return SPIFFS.open(name, mode); + } + + inline bool exists(const char *name) + { + return SPIFFS.exists(name); + } + + inline bool remove(const char *name) + { + return SPIFFS.remove(name); + } + + inline bool mkdir(const char *name) + { + return SPIFFS.mkdir(name); + } + +} // namespace portablefs + +#endif + +#ifdef PLATFORM_ESP8266 + +#include + +namespace portablefs +{ + using Dir; +} // namespace portablefs + +#endif + +#ifdef PLATFORM_NATIVE + +#include +#include +#include +#include "MockDtypes.h" + +namespace fs = std::filesystem; + + +namespace portablefs +{ + const std::string basePath = "./base"; + + class Dir + { + public: + Dir() {} + Dir(const String &path) + : it_(fs::directory_iterator(path).begin()), + end_(fs::directory_iterator(path).end()), + firstIncremented_(false) + { + } + + bool next() + { + if (!firstIncremented_) + firstIncremented_ = true; + else + ++it_; + + return it_ != end_; + } + + bool isFile() + { + return file.is_regular_file(); + } + + bool isDirectory() + { + return it_.is_directory(); + } + + String fileName() const + { + return it_.path().filename().string(); + } + + size_t fileSize() const + { + return it_.file_size(); + } + + private: + fs::directory_iterator it_; + fs::directory_iterator end_; + bool firstIncremented_; + }; + + inline Dir openDir(const String &path) + { + return Dir(path); + } + + inline File open(const char *name, const char *mode) + { + if(mode == "r") + return fopen() + return SPIFFS.open(name, mode); + } + + inline bool exists(const char *name) + { + return SPIFFS.exists(name); + } + + inline bool remove(const char *name) + { + return SPIFFS.remove(name); + } + + inline bool mkdir(const char *name) + { + return SPIFFS.mkdir(name); + } + +} // namespace portablefs + +#endif \ No newline at end of file diff --git a/lib/basic/MockDtypes.h b/lib/basic/MockDtypes.h index 5596886..857d1e1 100644 --- a/lib/basic/MockDtypes.h +++ b/lib/basic/MockDtypes.h @@ -7,6 +7,7 @@ #include #include #include +#include typedef uint32_t uint_t; @@ -39,4 +40,7 @@ inline std::string toString(const T & t) { return stream.str(); } +class String : public std::string +{}; + #define assert(EXPRESSION, MSG) ((EXPRESSION) ? (void)0 : _assert(#EXPRESSION, #MSG, __FILE__, __LINE__)) \ No newline at end of file diff --git a/lib/scale/MockScale.h b/lib/scale/MockScale.h index a07a549..c9714c1 100644 --- a/lib/scale/MockScale.h +++ b/lib/scale/MockScale.h @@ -4,14 +4,16 @@ class MockScale { public: - MockScale( uint16_t valueMin=0, uint16_t valueMax=50) + MockScale( uint16_t valueMin=0, uint16_t valueMax=10) : valueMin_(valueMin), valueMax_(valueMax), currentValue_(valueMin), direction(1) {} bool measure(uint16_t & measurementOut) { currentValue_ += direction; - if ( currentValue_ >= valueMax_) + if ( currentValue_ >= valueMax_) { direction = -1; + valueMax_ += 2; + } else if ( currentValue_ <= valueMin_ ) direction = +1; diff --git a/lib/scale/Scale.h b/lib/scale/Scale.h index 47a7f7c..109723e 100644 --- a/lib/scale/Scale.h +++ b/lib/scale/Scale.h @@ -1,4 +1,5 @@ #include "HX711.h" +#include "ConfigHardware.h" #include @@ -9,8 +10,11 @@ public: bool measure(uint16_t & measurementOut) { if (hx711_.is_ready()) { - uint32_t value = hx711_.get_value(MEASUREMENT_AVG_COUNT); - measurementOut = (int16_t)(value / DIVIDER); + long value = hx711_.read_average(CONFIG_MEASUREMENT_AVG_COUNT) - offset_; + if(value > 0) + measurementOut = (int16_t)(value / DIVIDER); + else + measurementOut = 0; return true; } else @@ -22,9 +26,10 @@ public: }; void tare(uint32_t numMeasurementsToAverage=50) { - hx711_.tare(numMeasurementsToAverage); + offset_ = hx711_.read_average(numMeasurementsToAverage); } private: HX711 hx711_; + long offset_ = 0; }; diff --git a/lib/session/MeasurementSession.h b/lib/session/MeasurementSession.h index 0cc15fa..ef99e1b 100644 --- a/lib/session/MeasurementSession.h +++ b/lib/session/MeasurementSession.h @@ -23,7 +23,7 @@ public: Serial.println("Starting session rotate"); rotate(); const bool secondInsertSuccess = currentChunk->addPoint(measurement); - assert(secondInsertSuccess, "Session: insertion after rotation failed"); + assert_msg(secondInsertSuccess, "Session: insertion after rotation failed"); // TODO check that there is place for file - remove old files } return true; @@ -52,7 +52,7 @@ public: encoder.template sendArrayHeader(lastIdx - startIdx); while(startIdx < lastIdx) startIdx = serializeChunk(encoder, startIdx); - assert(startIdx == lastIdx, "Not all data was sent"); + assert_msg(startIdx == lastIdx, "Not all data was sent"); } uint32_t getStartTime() const { @@ -88,18 +88,18 @@ private: template< typename Encoder_T> uint32_t serializeChunk(Encoder_T & encoder, uint32_t startIdx) const { - assert( startIdx < currentChunk->getStartIndex() + currentChunk->numMeasurements(), - "serializeChunk: invalid startIdx" ); + assert_msg( startIdx < currentChunk->getStartIndex() + currentChunk->numMeasurements(), + "serializeChunk: invalid startIdx" ); if( startIdx >= currentChunk->getStartIndex() ) { const auto localStartIdx = startIdx - currentChunk->getStartIndex(); const auto numElements = currentChunk->numMeasurements() - localStartIdx; - assert(numElements <= currentChunk->numMeasurements(), "Internal problem in serializeChunk"); + assert_msg(numElements <= currentChunk->numMeasurements(), "Internal problem in serializeChunk"); encoder.sendArrayPartialContents( currentChunk->getDataPointer() + localStartIdx, numElements ); return currentChunk->getStartIndex() + currentChunk->numMeasurements(); } else if( startIdx >= otherChunk->getStartIndex() && otherChunkFilled() ) { encoder.sendArrayPartialContents( otherChunk->getDataPointer(), otherChunk->numMeasurements() ); - assert( otherChunk->numMeasurements(), CHUNK_SIZE ); + assert_msg( otherChunk->numMeasurements(), CHUNK_SIZE ); return otherChunk->getStartIndex() + otherChunk->numMeasurements(); } else { if( encoder.getSizeCountMode() ) { diff --git a/lib/session/SpiffsStorage.h b/lib/session/SpiffsStorage.h index 33ebf01..0053c96 100644 --- a/lib/session/SpiffsStorage.h +++ b/lib/session/SpiffsStorage.h @@ -1,7 +1,43 @@ #pragma once #include "StreamingMsgPackEncoder.h" -#include +#include "FilesystemAbstraction.h" +#ifdef USE_ESP32 + +struct WriterAdaptor +{ + File * f; + void write(const char * ptr, size_t size) { + f->write(reinterpret_cast(ptr), size); + } +}; + +class SpiffsStorageWriter { +public: + SpiffsStorageWriter(const String &fileName) : + f_(SPIFFS.open(fileName, "w")), + adaptor_{&f_}, + encoder_(&adaptor_), + fileName_(fileName) + { + bool success = f_; + Serial.println(success); + } + ~SpiffsStorageWriter() { + f_.close(); + Serial.println(fileName_); + Serial.println(SPIFFS.exists(fileName_)); + } + StreamingMsgPackEncoder &encoder() { return encoder_; } + +private: + File f_; + WriterAdaptor adaptor_; + StreamingMsgPackEncoder encoder_; + String fileName_; +}; + +#else class SpiffsStorageWriter { public: @@ -26,6 +62,11 @@ private: String fileName_; }; +#endif + + + + class SpiffsStorageReader { diff --git a/lib/session/StreamingMsgPackEncoder.h b/lib/session/StreamingMsgPackEncoder.h index b92ba0a..2ea08b4 100644 --- a/lib/session/StreamingMsgPackEncoder.h +++ b/lib/session/StreamingMsgPackEncoder.h @@ -19,6 +19,7 @@ struct DummyWriter { void write(const void*, uint32_t) {} }; + class CopyWriter { public: CopyWriter(uint8_t * bufferToWrite) @@ -193,8 +194,8 @@ public: uint32_t elementsToSkip = 0; if( sentBytes_ < offsetToStart_ ) { elementsToSkip = (offsetToStart_ - sentBytes_) / sizeof(T); - assert((offsetToStart_ - sentBytes_) % sizeof(T) == 0, - "Looks like previous sent operation send fraction of an element."); + assert_msg((offsetToStart_ - sentBytes_) % sizeof(T) == 0, + "Looks like previous sent operation send fraction of an element."); } if( elementsToSkip >= length) { sentBytes_ += sizeof(T) * length; @@ -241,7 +242,7 @@ private: if( sentBytes_ < offsetToStart_ ) { // already sent sentBytes_ += sizeRequired; - assert( sentBytes_ <= offsetToStart_, "Partial sending not supported by this function" ); + assert_msg( sentBytes_ <= offsetToStart_, "Partial sending not supported by this function" ); return; } diff --git a/lib/userdb/UserDB.cpp b/lib/userdb/UserDB.cpp new file mode 100644 index 0000000..f34c3b8 --- /dev/null +++ b/lib/userdb/UserDB.cpp @@ -0,0 +1,192 @@ +#include "UserDB.h" +#include "FilesystemAbstraction.h" + +const String userDir = "/u/"; + +template +ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T &val) +{ + ForwardIterator it; + iterator_traits::difference_type count, step; + count = distance(first, last); + while (count > 0) + { + it = first; + step = count / 2; + advance(it, step); + if (*it < val) + { + first = ++it; + count -= step + 1; + } + else + count = step; + } + return first; +} + +static String userFileName(const String &userName) +{ + return userDir + userName; +} + +bool User::load(const String &name) +{ + name_ = name; + assert(name_.length() > 0); + const auto fileName = userFileName(name_); + if (!portablefs::exists(fileName.c_str())) + return false; + + auto file = portablefs::open(fileName.c_str(), "r"); + + size_t sessionsInFile; + file.read((uint8_t *)&sessionsInFile, sizeof(numSessions_)); + + init(name, sessionsInFile * 2); + + size_t expectedSize = sizeof(SessionIdType) * numSessions_; + auto bytesRead = file.read((uint8_t *)sessionIds_, expectedSize); + numSessions_ = sessionsInFile; + + assert(expectedSize == bytesRead); +} + +void User::init(const String &name, size_t sessionAllocateSize) +{ + if (sessionIds_ != nullptr) + { + free(sessionIds_); + sessionIds_ = nullptr; + } + name_ = name; + numSessionsAllocated_ = sessionAllocateSize; + sessionIds_ = (SessionIdType *)ps_malloc(sizeof(SessionIdType) * numSessionsAllocated_); + numSessions_ = 0; +} + +void User::save() +{ + if (!portablefs::exists(userDir.c_str())) + portablefs::mkdir(userDir.c_str()); + + auto file = portablefs::open(userFileName(name_).c_str(), "w"); + file.write((uint8_t *)&numSessions_, sizeof(numSessions_)); + file.write((uint8_t *)sessionIds_, sizeof(SessionIdType) * numSessions_); +} + +void User::freeResources() +{ + if (sessionIds_ != nullptr) + { + free(sessionIds_); + sessionIds_ = nullptr; + } +} + +void User::remove() +{ + portablefs::remove(userFileName(name_).c_str()); + freeResources(); + name_ = ""; + numSessions_ = 0; + numSessionsAllocated_ = 0; +} + +void User::growSessionArrayIfNecessary() +{ + assert(numSessions_ <= numSessionsAllocated_); + + if (numSessions_ < numSessionsAllocated_) + return; + + numSessionsAllocated_ *= 2; + sessionIds_ = (SessionIdType *)ps_realloc(sessionIds_, numSessionsAllocated_); + + assert(numSessions_ < numSessionsAllocated_); +} + +void User::insertSession(SessionIdType newSessionId) +{ + growSessionArrayIfNecessary(); + assert(numSessionsAllocated_ > numSessions_); + SessionIdType *insertPos = lower_bound(sessionIds_, sessionIds_ + numSessions_, newSessionId); + const size_t moveStartIdx = sessionIds_ + numSessions_ - insertPos; + for (size_t i = numSessions_ - 1; i >= moveStartIdx; --i) + sessionIds_[i + 1] = sessionIds_[i]; + sessionIds_[moveStartIdx] = newSessionId; + numSessions_ += 1; +} + +bool User::removeSession(SessionIdType sessionIdToRemove) +{ + SessionIdType *removePos = lower_bound(sessionIds_, sessionIds_ + numSessions_, sessionIdToRemove); + const size_t removeIdx = sessionIds_ + numSessions_ - removePos; + if (sessionIds_[removeIdx] != sessionIdToRemove) + return false; + + for (size_t i = removeIdx; i < numSessions_ - 1; ++i) + sessionIds_[i] = sessionIds_[i + 1]; + + numSessions_ -= 1; + return true; +} + +// -------------------------------------------------------------------------------------------------------------------- + +User *UserStorage::getUserInfo(const String &userName) +{ + // index 0 is the unassigned user + for (size_t i = 1; i < numUsers_; ++i) + if (users_[i].name() == userName) + return &users_[i]; + return nullptr; +} + +User *UserStorage::getUnassignedUser() +{ + return &users_[0]; +} + +User *UserStorage::addNewUser(const String &userName) +{ + if (numUsers_ >= MAX_USERS) + return nullptr; + + auto userIdx = numUsers_; + numUsers_++; + assert(numUsers_ < MAX_USERS); + users_[userIdx].init(userName); +} + +bool UserStorage::deleteUser(const String &userName) +{ + User *userPtr = getUserInfo(userName); + + if (userPtr == nullptr) + return false; + size_t userIdx = userPtr - users_; + userPtr->remove(); + assert(numUsers_ > 0); + if (userIdx != numUsers_ - 1) + users_[userIdx] = users_[numUsers_ - 1]; +} + +void UserStorage::fillFromFileSystem() +{ + for (size_t i = 0; i < numUsers_; ++i) + users_[i].freeResources(); + + numUsers_ = 1; + + users_[0].load("_unassigned"); + portablefs::Dir d(userDir); + while (d.next()) + { + if (d.isFile() && d.fileName()[0] != '_') + { + users_[numUsers_].load(d.fileName()); + ++numUsers_; + } + } +} \ No newline at end of file diff --git a/lib/userdb/UserDB.h b/lib/userdb/UserDB.h new file mode 100644 index 0000000..cd866d9 --- /dev/null +++ b/lib/userdb/UserDB.h @@ -0,0 +1,73 @@ +#pragma once + +#ifndef PLATFORM_NATIVE +#include +#endif + + +using SessionIdType = uint32_t; +constexpr size_t MAX_USERS = 64; +constexpr size_t INITIAL_SESSIONS_PER_USER = 128; + +struct User +{ +public: + User() : numSessions_(0), numSessionsAllocated_(0), sessionIds_(nullptr) {} + + void init(const String &name, size_t sessionAllocateSize = INITIAL_SESSIONS_PER_USER); + void freeResources(); + + bool load(const String &name); + void save(); + void remove(); + bool valid() const { return sessionIds_ != nullptr; } + + void insertSession(SessionIdType sessionId); + bool removeSession(SessionIdType sessionId); + + bool hasSession(SessionIdType sessionId) const; + + const String &name() const { return name_; } + + // session access + SessionIdType *sessionBegin() { return sessionIds_; } + SessionIdType *sessionEnd() { return sessionIds_ + numSessions_; } + + const SessionIdType *sessionBegin() const { return sessionIds_; } + const SessionIdType *sessionEnd() const { return sessionIds_ + numSessions_; } + +private: + void growSessionArrayIfNecessary(); + + String name_; + size_t numSessions_; + size_t numSessionsAllocated_; + SessionIdType *sessionIds_; +}; + +class UserStorage +{ +public: + UserStorage() + : numUsers_(0) + { + fillFromFileSystem(); + } + User *getUserInfo(const String &userName); + User *getUnassignedUser(); + + User *addNewUser(const String &userName); + bool deleteUser(const String &userName); + + User *begin() { return &users_[0]; } + User *end() { return &users_[numUsers_]; } + + const User *begin() const { return &users_[0]; } + const User *end() const { return &users_[numUsers_]; } + +private: + void fillFromFileSystem(); + + User users_[MAX_USERS]; + size_t numUsers_; +}; \ No newline at end of file diff --git a/lib/webdav/AsyncWebDav.h b/lib/webdav/AsyncWebDav.h index 7d973ac..e2a9e5a 100644 --- a/lib/webdav/AsyncWebDav.h +++ b/lib/webdav/AsyncWebDav.h @@ -1,5 +1,6 @@ #include -#include +#include "FilesystemAbstraction.h" + #define FLASH_TEXT(name) const char *name @@ -35,7 +36,7 @@ public: WebdavFileListCallback(const String &path) : path_(path), headerWritten_(false), finished_(false) { - dir_ = SPIFFS.openDir(path); + dir_ = portablefs::openDir(path); } size_t operator()(uint8_t *buffer, size_t maxLen, size_t index) @@ -104,11 +105,11 @@ public: } size_t bytesWritten = buffer - bufferStart; - assert(bytesWritten < maxLen, "Written too much!"); - Serial.print("Bytes written "); - Serial.println(bytesWritten); - Serial.print("Max bytes "); - Serial.println(maxLen); + assert_msg(bytesWritten < maxLen, "Written too much!"); + //Serial.print("Bytes written "); + //Serial.println(bytesWritten); + //Serial.print("Max bytes "); + //Serial.println(maxLen); return bytesWritten; } @@ -122,7 +123,7 @@ private: { size_t size = 0; auto fileBase = fileZero.substring(0, fileZero.indexOf('_')); - auto newDirInstance = SPIFFS.openDir(path_); + auto newDirInstance = portablefs::openDir(path_); while (newDirInstance.next()) if (newDirInstance.isFile() && newDirInstance.fileName().startsWith(fileBase)) size += newDirInstance.fileSize(); @@ -136,7 +137,7 @@ private: buffer += len; } - Dir dir_; + portablefs::Dir dir_; const String path_; bool headerWritten_; bool finished_; @@ -147,7 +148,7 @@ bool deleteMeasurementFiles(const String &stName, const String &folder) String baseName = folder + "/" + stName.substring(0, stName.indexOf(".")); int counter = 0; { - auto d = SPIFFS.openDir(folder); + auto d = portablefs::openDir(folder); while (d.next()) if (d.isFile() && d.fileName().startsWith(baseName)) ++counter; diff --git a/src/ConfigHardware.h b/src/ConfigHardware.h index 696c71f..ff6978f 100644 --- a/src/ConfigHardware.h +++ b/src/ConfigHardware.h @@ -1,11 +1,29 @@ +#pragma once + #include + +//#define _HW_V_20 + // HX711 load cell +#ifdef USE_ESP32 + +#ifdef _HW_V_20 +const int CONFIG_SCALE_DOUT_PIN = 23; +const int CONFIG_SCALE_SCK_PIN = 22; +#else +const int CONFIG_SCALE_DOUT_PIN = 22; +const int CONFIG_SCALE_SCK_PIN = 23; +#endif + +#else const int CONFIG_SCALE_DOUT_PIN = D2; const int CONFIG_SCALE_SCK_PIN = D3; -const uint8_t CONFIG_TARE_AVG_COUNT = 50; // number of measurements in tare-phase (to find 0 ) -const int CONFIG_VALUE_DIVIDER = 128; // uint32 measurements are divided by this factor, before stored in uint16_t +#endif +const uint8_t CONFIG_MEASUREMENT_AVG_COUNT = 1; // number of measurements in normal phase +const uint8_t CONFIG_TARE_AVG_COUNT = 6; // number of measurements in tare-phase (to find 0 ) const int CONFIG_MEASURE_DELAY = 100; // interval in ms between measurements - +//const int CONFIG_VALUE_DIVIDER = 8; // uint32 measurements are divided by this factor, before stored in uint16_t +const int CONFIG_VALUE_DIVIDER = 256; // uint32 measurements are divided by this factor, before stored in uint16_t const uint32_t CONFIG_SESSION_CHUNK_SIZE = 1024; //1024*8 - 16 * sizeof(uint32_t); diff --git a/src/DeviceInfoLog.h b/src/DeviceInfoLog.h index fafa27d..fd93b7c 100644 --- a/src/DeviceInfoLog.h +++ b/src/DeviceInfoLog.h @@ -1,7 +1,12 @@ +#ifdef USE_ESP32 +#include "SPIFFS.h" +#else #include +#endif inline void printDeviceInfo() { + /* FSInfo fs_info; SPIFFS.info(fs_info); @@ -66,4 +71,5 @@ inline void printDeviceInfo() str += "\r\n"; } Serial.print(str); + */ } \ No newline at end of file diff --git a/src/firmware_main.cpp b/src/firmware_main.cpp index 8cc8963..1081287 100644 --- a/src/firmware_main.cpp +++ b/src/firmware_main.cpp @@ -1,7 +1,13 @@ +#define USE_ESP32 + // Arduino & ESP headers #include +#ifdef USE_ESP32 +#include +#else #include #include +#endif #include #include // for NTP #include // for NTP @@ -9,6 +15,7 @@ // Own libs #include "Dtypes.h" #include "MockScale.h" +#include "Scale.h" #include "MeasurementSession.h" #include "SpiffsStorage.h" #include "DeviceInfoLog.h" @@ -46,6 +53,7 @@ public: void stopMeasurements() { measuring_ = false; + session.finalize(); } bool isMeasuring() const { @@ -54,12 +62,14 @@ public: void iteration() { if( ! measuring_ ) { + //Serial.println("Disabled"); return; } - uint16_t measurement; + uint16_t measurement=-1; scale.measure(measurement); session.addPoint(measurement); - + Serial.print("Measurement: "); + Serial.println(measurement); if( lastCallTime_ != 0) { const long cycleDuration = millis() - lastCallTime_; if( cycleDuration <= CONFIG_MEASURE_DELAY) @@ -69,8 +79,7 @@ public: else { const long skipped = (cycleDuration / CONFIG_MEASURE_DELAY); - Serial.print("Warning: measurements skipped: "); - Serial.println(skipped); + //Serial.printf("Warning: measurements skipped: %d, cycleDuration %d", skipped, cycleDuration); for(int i=0; i < skipped; ++i) session.addPoint(measurement); @@ -84,7 +93,8 @@ public: Session_T & getSession() { return session; } private: - MockScale scale; + Scale scale; + //MockScale scale; Session_T session; bool measuring_; long lastCallTime_; @@ -100,12 +110,18 @@ template void httpSetup(SessionManager * sessionManager) { server.on("/api/session/start", HTTP_POST | HTTP_GET, [sessionManager](AsyncWebServerRequest * req) { - req->send(200, "text/plain", F("OK")); + AsyncWebServerResponse *response = req->beginResponse(200, "text/plain", F("OK")); + response->addHeader("Access-Control-Allow-Origin", "*"); + req->send(response); + //req->send(200, "text/plain", F("OK")); sessionManager->startMeasurements(); Serial.println("Started measurements"); }); server.on("/api/session/stop", HTTP_POST | HTTP_GET, [sessionManager](AsyncWebServerRequest * req) { - req->send(200, "text/plain", F("OK")); + AsyncWebServerResponse *response = req->beginResponse(200, "text/plain", F("OK")); + response->addHeader("Access-Control-Allow-Origin", "*"); + req->send(response); + //req->send(200, "text/plain", F("OK")); sessionManager->stopMeasurements(); Serial.println("Stopped measurements"); }); @@ -114,6 +130,8 @@ void httpSetup(SessionManager * sessionManager) if( req->hasParam("startIdx") ) { startIdx = req->getParam("startIdx")->value().toInt(); } + Serial.print("Data request, start index: "); + Serial.println(startIdx); StreamingMsgPackEncoder encoderToDetermineSize(nullptr); encoderToDetermineSize.setSizeCountMode(true); @@ -122,18 +140,14 @@ void httpSetup(SessionManager * sessionManager) Serial.print("Sending started of total size "); Serial.println(totalSize); auto callback = [=](uint8_t *buffer, size_t maxLen, size_t index) -> size_t { - Serial.print("Partial send maxLen "); - Serial.print(maxLen); - Serial.print(" index "); - Serial.println(index); CopyWriter copyWriter(buffer); ChunkedStreamingMsgPackEncoder encoder(©Writer, index, index + maxLen); sessionManager->getSession().serialize(encoder, startIdx); - Serial.print("Bytes sent "); - Serial.println(encoder.sentBytes() - index); return encoder.sentBytes() - index; }; AsyncWebServerResponse *response = req->beginResponse("application/x-msgpack", totalSize, callback); + response->addHeader("Access-Control-Allow-Origin", "*"); + auto sessionId = sessionManager->getSession().getStartTime(); response->addHeader("content-disposition", "attachment; filename=\"" + String(sessionId) + ".st\""); req->send(response); @@ -144,6 +158,38 @@ void httpSetup(SessionManager * sessionManager) server.begin(); } +void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ + Serial.printf("Listing directory: %s\r\n", dirname); + + File root = fs.open(dirname); + if(!root){ + Serial.println("- failed to open directory"); + return; + } + if(!root.isDirectory()){ + Serial.println(" - not a directory"); + return; + } + + File file = root.openNextFile(); + while(file){ + if(file.isDirectory()){ + Serial.print(" DIR : "); + Serial.println(file.name()); + if(levels){ + listDir(fs, file.name(), levels -1); + } + } else { + Serial.print(" FILE: "); + Serial.print(file.name()); + Serial.print("\tSIZE: "); + Serial.println(file.size()); + } + file = root.openNextFile(); + } +} + + void setup() { // Serial @@ -153,14 +199,19 @@ void setup() Serial.println("----- New start -----"); // File system - SPIFFS.begin(); + bool spiffsResult = SPIFFS.begin(true); + Serial.printf("Spiffs begin %d\n", spiffsResult); printDeviceInfo(); // WiFi WiFi.mode(WIFI_STA); WiFi.begin(CONFIG_WIFI_SSID, CONFIG_WIFI_PASSWORD); - WiFi.hostname(CONFIG_HOSTNAME); + #ifdef USE_ESP32 + WiFi.setHostname(CONFIG_HOSTNAME); + #else + WIFI.hostname(CONFIG_HOSTNAME); + #endif Serial.print(F("\n\n")); Serial.println(F("Waiting for WIFI connection...")); while (WiFi.status() != WL_CONNECTED) { @@ -178,6 +229,9 @@ void setup() // HTTP & Websocket server httpSetup(&sessionManager); + + Serial.println("Spiffs listing:"); + listDir(SPIFFS, "/", 3); } void loop() {