diff --git a/firmware/lib/session/SessionManager.h b/firmware/lib/session/SessionManager.h new file mode 100644 index 0000000..8473268 --- /dev/null +++ b/firmware/lib/session/SessionManager.h @@ -0,0 +1,118 @@ + +// NTP headers +#include +#include +#include + +template +class SessionManager +{ +public: + SessionManager(int scaleDoutPin, int scaleSckPin, uint8_t tareAvgCount); + + void begin(); + + void tare(); + void startMeasurements(); + void stopMeasurements(); + bool isMeasuring() const { return measuring_; } + SessionT &session() { return session_; } + + void iteration(); + +private: + WiFiUDP ntpUDP_; + NTPClient timeClient_; + + Scale scale_; + //MockScale scale; + SessionT session_; + bool measuring_; + long lastCallTime_; + + int scaleDoutPin_; + int scaleSckPin_; + uint8_t tareAvgCount_; +}; + +// ------------------------------------------------------------------------------------------------ + +template +SessionManager::SessionManager(int scaleDoutPin, int scaleSckPin, uint8_t tareAvgCount) + : timeClient_(ntpUDP_, "pool.ntp.org"), + measuring_(false), + lastCallTime_(0), + scaleDoutPin_(scaleDoutPin), + scaleSckPin_(scaleSckPin), + tareAvgCount_(tareAvgCount) +{ +} + +template +void SessionManager::tare() +{ + Serial.println("Beginning tare"); + scale_.begin(scaleDoutPin_, scaleSckPin_); + scale_.tare(CONFIG_TARE_AVG_COUNT); + Serial.println("Finished tare"); +} + +template +void SessionManager::begin() +{ + timeClient_.begin(); + timeClient_.update(); + tare(); + session_.init(timeClient_.getEpochTime()); +} + +template +void SessionManager::startMeasurements() +{ + measuring_ = true; + lastCallTime_ = 0; + session_.init(timeClient_.getEpochTime()); +} + +template +void SessionManager::stopMeasurements() +{ + session_.finalize(); + measuring_ = false; +} + +template +void SessionManager::iteration() +{ + if (!measuring_) + return; + + uint16_t measurement = -1; + scale_.measure(measurement); + bool addPointSuccessful = session_.addPoint(measurement); + if (!addPointSuccessful) + { + Serial.println("Maximum time of session reached - stopping"); + stopMeasurements(); + return; + } + if (lastCallTime_ != 0) + { + const long cycleDuration = millis() - lastCallTime_; + if (cycleDuration <= CONFIG_MEASURE_DELAY) + { + delay(CONFIG_MEASURE_DELAY - cycleDuration); + } + else + { + const long skipped = (cycleDuration / CONFIG_MEASURE_DELAY); + Serial.printf("Warning: measurements skipped: %ld, cycleDuration %ld", skipped, cycleDuration); + + for (int i = 0; i < skipped; ++i) + session_.addPoint(measurement); + + delay(CONFIG_MEASURE_DELAY * (skipped + 1) - cycleDuration); + } + } + lastCallTime_ = millis(); +} \ No newline at end of file diff --git a/firmware/lib/session/SimpleMeasurementSession.h b/firmware/lib/session/SimpleMeasurementSession.h index c3fe569..ab61abf 100644 --- a/firmware/lib/session/SimpleMeasurementSession.h +++ b/firmware/lib/session/SimpleMeasurementSession.h @@ -13,6 +13,7 @@ public: : chunk(nullptr), saveInterval_(saveInterval) { } + ~SimpleMeasurementSession() { if (chunk != nullptr) @@ -21,7 +22,7 @@ public: void init(uint32_t epochStartTime) { - if (chunk == nullptr) + if (chunk == nullptr) { // psram allocation doesn't seem to work in constructor chunk = (ChunkT *)heap_caps_malloc(sizeof(ChunkT), MALLOC_CAP_SPIRAM); @@ -35,15 +36,15 @@ public: bool success = chunk->addPoint(measurement); if (success && (chunk->numMeasurements() % saveInterval_) == 0) saveToFileSystem(); - if(!success) + if (!success) Serial.println("Failed to add point"); - //Serial.printf("Add point %d success %d\n", measurement, success); return success; } void finalize() { - saveToFileSystem(); + if (numMeasurements() > 0) + saveToFileSystem(); chunk->init(0, 0); } diff --git a/firmware/src/DeviceInfoLog.h b/firmware/src/DeviceInfoLog.h deleted file mode 100644 index fd93b7c..0000000 --- a/firmware/src/DeviceInfoLog.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifdef USE_ESP32 -#include "SPIFFS.h" -#else -#include -#endif - -inline void printDeviceInfo() -{ - /* - FSInfo fs_info; - SPIFFS.info(fs_info); - - float fileTotalKB = (float)fs_info.totalBytes / 1024.0; - float fileUsedKB = (float)fs_info.usedBytes / 1024.0; - - float flashChipSize = (float)ESP.getFlashChipSize() / 1024.0 / 1024.0; - float realFlashChipSize = (float)ESP.getFlashChipRealSize() / 1024.0 / 1024.0; - float flashFreq = (float)ESP.getFlashChipSpeed() / 1000.0 / 1000.0; - FlashMode_t ideMode = ESP.getFlashChipMode(); - - Serial.printf("\n#####################\n"); - - Serial.printf("__________________________\n\n"); - Serial.println("Firmware: "); - Serial.printf(" Chip Id: %08X\n", ESP.getChipId()); - Serial.print(" Core version: "); - Serial.println(ESP.getCoreVersion()); - Serial.print(" SDK version: "); - Serial.println(ESP.getSdkVersion()); - Serial.print(" Boot version: "); - Serial.println(ESP.getBootVersion()); - Serial.print(" Boot mode: "); - Serial.println(ESP.getBootMode()); - - Serial.printf("__________________________\n\n"); - - Serial.println("Flash chip information: "); - Serial.printf(" Flash chip Id: %08X (for example: Id=001640E0 Manuf=E0, Device=4016 (swap bytes))\n", ESP.getFlashChipId()); - Serial.printf(" Sketch thinks Flash RAM is size: "); - Serial.print(flashChipSize); - Serial.println(" MB"); - Serial.print(" Actual size based on chip Id: "); - Serial.print(realFlashChipSize); - Serial.println(" MB ... given by (2^( Device - 1) / 8 / 1024"); - Serial.print(" Flash frequency: "); - Serial.print(flashFreq); - Serial.println(" MHz"); - Serial.printf(" Flash write mode: %s\n", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT" : ideMode == FM_DIO ? "DIO" : ideMode == FM_DOUT ? "DOUT" : "UNKNOWN")); - - Serial.printf("__________________________\n\n"); - - Serial.println("File system (SPIFFS): "); - Serial.print(" Total KB: "); - Serial.print(fileTotalKB); - Serial.println(" KB"); - Serial.print(" Used KB: "); - Serial.print(fileUsedKB); - Serial.println(" KB"); - Serial.printf(" Block size: %u\n", fs_info.blockSize); - Serial.printf(" Page size: %u\n", fs_info.pageSize); - Serial.printf(" Maximum open files: %u\n", fs_info.maxOpenFiles); - Serial.printf(" Maximum path length: %u\n\n", fs_info.maxPathLength); - - String str = ""; - Dir dir = SPIFFS.openDir("/dat"); - while (dir.next()) - { - str += dir.fileName(); - str += " / "; - str += dir.fileSize(); - str += "\r\n"; - } - Serial.print(str); - */ -} \ No newline at end of file diff --git a/firmware/src/firmware_main.cpp b/firmware/src/firmware_main.cpp index ed59777..2878742 100644 --- a/firmware/src/firmware_main.cpp +++ b/firmware/src/firmware_main.cpp @@ -4,112 +4,24 @@ #include "SwimTrackerConfig.h" #include -#include // for NTP -#include // for NTP // Own libs #include "MockScale.h" #include "Scale.h" #include "MeasurementSession.h" +#include "SessionManager.h" #include "SpiffsStorage.h" -#include "DeviceInfoLog.h" #include "SimpleMeasurementSession.h" #include "EspHttp.h" #include "WebDAV.h" -WiFiUDP ntpUDP; -NTPClient timeClient(ntpUDP, "pool.ntp.org"); - -using Session_T = SimpleMeasurementSession; - -template -class SessionManager -{ -public: - SessionManager() : measuring_(false), lastCallTime_(0) - { - } - - void begin() - { - Serial.println("Beginning tare"); - scale.begin(CONFIG_SCALE_DOUT_PIN, CONFIG_SCALE_SCK_PIN); - scale.tare(CONFIG_TARE_AVG_COUNT); - Serial.println("Finished tare"); - session.init(timeClient.getEpochTime()); - Serial.println("Finished session init"); - } - - void startMeasurements() - { - measuring_ = true; - lastCallTime_ = 0; - session.init(timeClient.getEpochTime()); - } - - void stopMeasurements() - { - measuring_ = false; - session.finalize(); - } - - bool isMeasuring() const - { - return measuring_; - } - - void iteration() - { - if (!measuring_) - return; - - uint16_t measurement = -1; - scale.measure(measurement); - bool addPointSuccessful = session.addPoint(measurement); - if(!addPointSuccessful) { - Serial.println("Maximum time of session reached - stopping"); - stopMeasurements(); - return; - } - Serial.print("Measurement: "); - Serial.println(measurement); - if (lastCallTime_ != 0) - { - const long cycleDuration = millis() - lastCallTime_; - if (cycleDuration <= CONFIG_MEASURE_DELAY) - { - delay(CONFIG_MEASURE_DELAY - cycleDuration); - } - else - { - const long skipped = (cycleDuration / CONFIG_MEASURE_DELAY); - Serial.printf("Warning: measurements skipped: %ld, cycleDuration %ld", skipped, cycleDuration); - - for (int i = 0; i < skipped; ++i) - session.addPoint(measurement); - - delay(CONFIG_MEASURE_DELAY * (skipped + 1) - cycleDuration); - } - } - lastCallTime_ = millis(); - } - - Session_T &getSession() { return session; } - -private: - Scale scale; - //MockScale scale; - Session_T session; - bool measuring_; - long lastCallTime_; -}; - -SessionManager sessionManager; +using Session_T = SimpleMeasurementSession; +SessionManager sessionManager(CONFIG_SCALE_DOUT_PIN, CONFIG_SCALE_SCK_PIN, CONFIG_TARE_AVG_COUNT); EspHttp espHttpServer; -template -void httpSetup(SessionManager *sessionManager) +template +void httpSetup(SessionManager *sessionManager) { auto cbStartSession = [sessionManager](httpd_req_t *req) { httpd_resp_send(req, "Session started", -1); @@ -131,7 +43,7 @@ void httpSetup(SessionManager *sessionManager) result += "{ \"session\": "; if (sessionManager->isMeasuring()) { - const auto &session = sessionManager->getSession(); + const auto &session = sessionManager->session(); result += "{ \"started\":" + String(session.getStartTime()) + ", "; result += "\"num_measurements\":" + String(session.numMeasurements()) + "},\n"; } @@ -149,18 +61,18 @@ void httpSetup(SessionManager *sessionManager) const String freeBytes(ESP.getFreeHeap()); const String usedBytes(ESP.getHeapSize() - ESP.getFreeHeap()); result += "\"ram\": { \"used\": " + usedBytes + ", \"free\":" + freeBytes + "},\n"; - } + } // PSRAM { const String freeBytes(ESP.getFreePsram()); const String usedBytes(ESP.getPsramSize() - ESP.getFreePsram()); result += "\"psram\": { \"used\": " + usedBytes + ", \"free\":" + freeBytes + "}\n"; - } + } result += "}"; httpd_resp_send(req, result.c_str(), result.length()); }; auto cbGetData = [sessionManager](httpd_req_t *req) { - auto sessionId = sessionManager->getSession().getStartTime(); + auto sessionId = sessionManager->session().getStartTime(); uint32_t startIdx = getUrlQueryParameter(req, "startIdx", 0); Serial.printf("Data request, start index: %d", startIdx); @@ -172,13 +84,13 @@ void httpSetup(SessionManager *sessionManager) //data StreamingMsgPackEncoder encoderToDetermineSize(nullptr); encoderToDetermineSize.setSizeCountMode(true); - sessionManager->getSession().serialize(encoderToDetermineSize, startIdx); + sessionManager->session().serialize(encoderToDetermineSize, startIdx); auto totalSize = encoderToDetermineSize.getContentLength(); char *buf = (char *)malloc(totalSize); CopyWriter copyWriter((uint8_t *)buf); StreamingMsgPackEncoder encoder(©Writer); - sessionManager->getSession().serialize(encoder, startIdx); + sessionManager->session().serialize(encoder, startIdx); httpd_resp_send(req, buf, totalSize); free(buf); }; @@ -207,25 +119,19 @@ void setup() while (!Serial) { } - Serial.println(" "); - Serial.println("----- New start -----"); + Serial.println("Starting SwimTracker Firmware"); // File system bool spiffsResult = SPIFFS.begin(true); - Serial.printf("Spiffs begin %d\n", spiffsResult); - - printDeviceInfo(); + if (!spiffsResult) + Serial.println("Failed to mount/format SPIFFS file system"); ESP_ERROR_CHECK(esp_event_loop_create_default()); + // WiFi WiFi.mode(WIFI_STA); WiFi.begin(CONFIG_WIFI_SSID, CONFIG_WIFI_PASSWORD); -#ifdef PLATFORM_ESP32 WiFi.setHostname(CONFIG_HOSTNAME); -#else - WIFI.hostname(CONFIG_HOSTNAME); -#endif - Serial.print(F("\n\n")); Serial.println(F("Waiting for WIFI connection...")); int connectCounter = 0; while (WiFi.status() != WL_CONNECTED) @@ -234,23 +140,18 @@ void setup() connectCounter += 1; if (connectCounter > 5) { - Serial.println("Couldn't obtain WIFI - trying begin() again"); + Serial.println("Couldn't obtain WIFI - retrying.."); WiFi.begin(CONFIG_WIFI_SSID, CONFIG_WIFI_PASSWORD); } } - Serial.print(F("Connected to WiFi. IP:")); + Serial.print("Connected to WiFi. IP:"); Serial.println(WiFi.localIP()); - // NTP - timeClient.begin(); - timeClient.update(); - // Session sessionManager.begin(); // HTTP & Websocket server httpSetup(&sessionManager); - } void loop() diff --git a/measurement_sizes.ods b/measurement_sizes.ods new file mode 100644 index 0000000..f994510 Binary files /dev/null and b/measurement_sizes.ods differ