From 6a724b284f971c005beaed74b6378fe1d661df73 Mon Sep 17 00:00:00 2001 From: Martin Bauer Date: Thu, 22 Aug 2019 21:33:36 +0200 Subject: [PATCH] Worked on firmware --- .gitignore | 2 + .idea/misc.xml | 13 +- .idea/modules.xml | 3 +- CMakeLists.txt | 79 +++++++++- SessionChunkIO.h | 18 --- dimensions.txt | 6 + firmware.ino | 138 ------------------ lib/basic/Dtypes.h | 17 +++ MockDtypes.h => lib/basic/MockDtypes.h | 0 MockSerial.h => lib/basic/MockSerial.h | 0 lib/scale/MockScale.h | 32 ++++ lib/scale/Scale.h | 30 ++++ .../session/MeasurementSession.h | 11 +- {session => lib/session}/MockStorage.h | 0 {session => lib/session}/SessionChunk.h | 3 +- {session => lib/session}/SpiffsStorage.h | 2 +- .../session}/StreamingMsgPackEncoder.h | 1 + platformio.ini | 25 ++++ src/ConfigHardware.h | 10 ++ src/ConfigWifi.h | 5 + config.h => src/config.h | 9 -- src/firmware_main.cpp | 123 ++++++++++++++++ .../test_common/sessiontest.cpp | 84 +++++++---- todo.txt | 20 +++ 24 files changed, 422 insertions(+), 209 deletions(-) create mode 100644 .gitignore delete mode 100644 SessionChunkIO.h create mode 100644 dimensions.txt delete mode 100644 firmware.ino create mode 100644 lib/basic/Dtypes.h rename MockDtypes.h => lib/basic/MockDtypes.h (100%) rename MockSerial.h => lib/basic/MockSerial.h (100%) create mode 100644 lib/scale/MockScale.h create mode 100644 lib/scale/Scale.h rename session/Session.h => lib/session/MeasurementSession.h (95%) rename {session => lib/session}/MockStorage.h (100%) rename {session => lib/session}/SessionChunk.h (97%) rename {session => lib/session}/SpiffsStorage.h (92%) rename {session => lib/session}/StreamingMsgPackEncoder.h (99%) create mode 100644 platformio.ini create mode 100644 src/ConfigHardware.h create mode 100644 src/ConfigWifi.h rename config.h => src/config.h (64%) create mode 100644 src/firmware_main.cpp rename sessiontest.cpp => test/test_common/sessiontest.cpp (63%) create mode 100644 todo.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff1a518 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.pio +CMakeListsPrivate.txt diff --git a/.idea/misc.xml b/.idea/misc.xml index 8822db8..3463fba 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,16 @@ - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index cb860b6..9ce81f0 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,8 @@ - + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index dea4edf..e5b6297 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,77 @@ -cmake_minimum_required (VERSION 2.6) -project (pooltrainer_firmware) +# !!! WARNING !!! AUTO-GENERATED FILE, PLEASE DO NOT MODIFY IT AND USE +# https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags +# +# If you need to override existing CMake configuration or add extra, +# please create `CMakeListsUser.txt` in the root of project. +# The `CMakeListsUser.txt` will not be overwritten by PlatformIO. -add_executable(test sessiontest.cpp) \ No newline at end of file +cmake_minimum_required(VERSION 3.2) +project(firmware) + +include(CMakeListsPrivate.txt) + +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeListsUser.txt) +include(CMakeListsUser.txt) +endif() + +add_custom_target( + PLATFORMIO_BUILD ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_BUILD_VERBOSE ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --verbose + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_UPLOAD ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --target upload + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_CLEAN ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --target clean + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_MONITOR ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion device monitor + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_TEST ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion test + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_PROGRAM ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --target program + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_UPLOADFS ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion run --target uploadfs + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_UPDATE_ALL ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion update + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_custom_target( + PLATFORMIO_REBUILD_PROJECT_INDEX ALL + COMMAND ${PLATFORMIO_CMD} -f -c clion init --ide clion + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_executable(${PROJECT_NAME} ${SRC_LIST}) diff --git a/SessionChunkIO.h b/SessionChunkIO.h deleted file mode 100644 index 8df9110..0000000 --- a/SessionChunkIO.h +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - - -class ESP8266HttpMsgPackWriter { -public: - HttpWriterAdaptor(ESP8266WebServer - * o) - : - obj_(o) {} - - void write(const char *data, uint32_t size) { - obj_->sendContent_P(data, size); - } - -private: - ESP8266WebServer *obj_; -}; diff --git a/dimensions.txt b/dimensions.txt new file mode 100644 index 0000000..b9b95cb --- /dev/null +++ b/dimensions.txt @@ -0,0 +1,6 @@ +92 x 28 x 30 +35x20 + + + 95x 50 x 30 (absolute min) +100 x 55 x 35 \ No newline at end of file diff --git a/firmware.ino b/firmware.ino deleted file mode 100644 index 4357902..0000000 --- a/firmware.ino +++ /dev/null @@ -1,138 +0,0 @@ -#include "HX711.h" -#include -#include // for NTP -#include // for NTP -#include -#include - -#include "config.h" - - -int16_t compressMeasurement(int32_t value) { - return (int16_t)(measurement / DIVIDER) -} - - - -HX711 scale; -WiFiUDP ntpUDP; -NTPClient timeClient(ntpUDP, "pool.ntp.org"); -TrainingSession session; -ESP8266WebServer webServer(80); - -bool makeMeasurement(long & measurementOut) -{ - if (scale.is_ready()) - { - measurementOut = scale.get_value(MEASUREMENT_AVG_COUNT); - return true; - } - else - return false; -} - - -void setup() -{ - digitalWrite(LED_PIN, HIGH); - - // Serial - Serial.begin(115200); - while(!Serial) {} - - // wifi - WiFi.mode(WIFI_STA); - WiFi.hostname(HOSTNAME); - WiFi.begin(WIFI_SSID, WIFI_PASSWD); - - Serial.print(F("\n\n")); - Serial.println(F("Waiting for WIFI connection...")); - while (WiFi.status() != WL_CONNECTED) { - delay(1000); - } - - Serial.print(F("Connected to WiFi. IP:")); - Serial.println(WiFi.localIP()); - - timeClient.begin(); - timeClient.update(); - - // initialize cell - scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); - scale.tare( TARE_AVG_COUNT ); - - // NTP - session.init( &timeClient ); - Serial.print("Initialized NTP client: "); - Serial.println(timeClient.getEpochTime()); - - // webserver - webServer.on("/api/session", [] () { - session.send(&webServer); - }); - webServer.on("/api/save", [] () { - webServer.send(200, "text/plain", session.saveToFileSystem()); - }); - webServer.on("/api/tare", [] () { - scale.tare( TARE_AVG_COUNT ); - webServer.send(200, "text/plain", "OK"); - }); - webServer.on("/", HTTP_GET, [](){ - Serial.println("index.html requested"); - File file = SPIFFS.open("/index.html", "r"); - size_t sent = webServer.streamFile(file, "text/html"); - file.close(); - }); - webServer.on("/swimtrainer.webmanifest", HTTP_GET, [](){ - File file = SPIFFS.open("/swimtrainer.webmanifest", "r"); - size_t sent = webServer.streamFile(file, "application/manifest+json"); - file.close(); - }); - - - - webServer.begin(); - Serial.println("Webserver started"); - - // flash file system - if(!SPIFFS.begin()){ - Serial.println("An Error has occurred while mounting SPIFFS"); - } -} - - -void loop() -{ - const long cycleStart = millis(); - - - digitalWrite(LED_PIN, HIGH); - - - long measurement = 0; - if(makeMeasurement(measurement)) - { - session.addPoint(measurement); - } else { - Serial.println("Measurement skipped - cell not ready"); - } - - webServer.handleClient(); - - const long cycleDuration = millis() - cycleStart; - if( cycleDuration <= DELAY) - { - delay(DELAY - cycleDuration); - } - else - { - Serial.print("Skipping measurement, cycle duration was "); - Serial.println(cycleDuration); - const long skipped = (cycleDuration / DELAY); - //for(int i=0; i < skipped; ++i) - // session.addPoint(0xFFFFFFFE); - - delay(DELAY * (skipped + 1) - cycleDuration); - } - -} \ No newline at end of file diff --git a/lib/basic/Dtypes.h b/lib/basic/Dtypes.h new file mode 100644 index 0000000..512fe62 --- /dev/null +++ b/lib/basic/Dtypes.h @@ -0,0 +1,17 @@ +inline void _assert(const char* expression, const char* message, const char* file, int line) +{ + Serial.print("Assert "); + Serial.print(file); + Serial.print(" : "); + Serial.print(line); + Serial.print(" '"); + Serial.print(expression); + Serial.println("' failed."); +} + +template< typename T> +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 diff --git a/MockDtypes.h b/lib/basic/MockDtypes.h similarity index 100% rename from MockDtypes.h rename to lib/basic/MockDtypes.h diff --git a/MockSerial.h b/lib/basic/MockSerial.h similarity index 100% rename from MockSerial.h rename to lib/basic/MockSerial.h diff --git a/lib/scale/MockScale.h b/lib/scale/MockScale.h new file mode 100644 index 0000000..a07a549 --- /dev/null +++ b/lib/scale/MockScale.h @@ -0,0 +1,32 @@ +#include + + +class MockScale +{ +public: + MockScale( uint16_t valueMin=0, uint16_t valueMax=50) + : valueMin_(valueMin), valueMax_(valueMax), currentValue_(valueMin), direction(1) + {} + + bool measure(uint16_t & measurementOut) { + currentValue_ += direction; + if ( currentValue_ >= valueMax_) + direction = -1; + else if ( currentValue_ <= valueMin_ ) + direction = +1; + + measurementOut = currentValue_; + return true; + } + + void begin(uint32_t , uint32_t ) { + }; + + void tare(uint32_t ) { + } +private: + uint16_t valueMin_; + uint16_t valueMax_; + uint16_t currentValue_; + int direction; +}; diff --git a/lib/scale/Scale.h b/lib/scale/Scale.h new file mode 100644 index 0000000..47a7f7c --- /dev/null +++ b/lib/scale/Scale.h @@ -0,0 +1,30 @@ +#include "HX711.h" +#include + + +template +class Scale +{ +public: + bool measure(uint16_t & measurementOut) { + if (hx711_.is_ready()) + { + uint32_t value = hx711_.get_value(MEASUREMENT_AVG_COUNT); + measurementOut = (int16_t)(value / DIVIDER); + return true; + } + else + return false; + } + + void begin(uint32_t pinDOUT, uint32_t pinSCK) { + hx711_.begin(pinDOUT, pinSCK); + }; + + void tare(uint32_t numMeasurementsToAverage=50) { + hx711_.tare(numMeasurementsToAverage); + } + +private: + HX711 hx711_; +}; diff --git a/session/Session.h b/lib/session/MeasurementSession.h similarity index 95% rename from session/Session.h rename to lib/session/MeasurementSession.h index e52e036..30e4f51 100644 --- a/session/Session.h +++ b/lib/session/MeasurementSession.h @@ -1,12 +1,12 @@ #include "SessionChunk.h" -template -class Session { +template +class MeasurementSession { public: typedef SessionChunk Chunk_T; - Session() + MeasurementSession() : currentChunk(&chunks[0]), otherChunk(&chunks[1]) {} @@ -100,8 +100,9 @@ private: reader.seek(Chunk_T::template valueOffset()); const uint32_t PART_SIZE = 32; - static_assert( PART_SIZE < CHUNK_SIZE && CHUNK_SIZE % PART_SIZE == 0); - +#ifndef ARDUINO + static_assert((PART_SIZE < CHUNK_SIZE) && (CHUNK_SIZE % PART_SIZE == 0)); +#endif Measurement_T buffer[PART_SIZE]; for(uint32_t i = 0; i < CHUNK_SIZE; i += PART_SIZE) { diff --git a/session/MockStorage.h b/lib/session/MockStorage.h similarity index 100% rename from session/MockStorage.h rename to lib/session/MockStorage.h diff --git a/session/SessionChunk.h b/lib/session/SessionChunk.h similarity index 97% rename from session/SessionChunk.h rename to lib/session/SessionChunk.h index 9881405..ed16f40 100644 --- a/session/SessionChunk.h +++ b/lib/session/SessionChunk.h @@ -1,7 +1,8 @@ #include "StreamingMsgPackEncoder.h" +#include -template +template class SessionChunk { public: diff --git a/session/SpiffsStorage.h b/lib/session/SpiffsStorage.h similarity index 92% rename from session/SpiffsStorage.h rename to lib/session/SpiffsStorage.h index d4d625a..2e44b6c 100644 --- a/session/SpiffsStorage.h +++ b/lib/session/SpiffsStorage.h @@ -20,7 +20,7 @@ private: class SpiffsStorageReader { public: - SpiffsBackendReader(const String &fileName) : + SpiffsStorageReader(const String &fileName) : f_(SPIFFS.open(fileName, "w")) {} diff --git a/session/StreamingMsgPackEncoder.h b/lib/session/StreamingMsgPackEncoder.h similarity index 99% rename from session/StreamingMsgPackEncoder.h rename to lib/session/StreamingMsgPackEncoder.h index 5a357ea..efef8cd 100644 --- a/session/StreamingMsgPackEncoder.h +++ b/lib/session/StreamingMsgPackEncoder.h @@ -1,3 +1,4 @@ +#pragma once template struct TypeToMsgPackCode{}; template<> struct TypeToMsgPackCode { static const char CODE; }; diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..2e85943 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,25 @@ +;PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:d1] +platform = espressif8266 +board = d1 +framework = arduino +monitor_port = /dev/ttyUSB0 +upload_port = /dev/ttyUSB0 +monitor_speed = 115200 +lib_deps = + ESP Async WebServer + AsyncTCP + NTPClient + +;[env:native] +;platform = native +;test_ignore = test_embedded diff --git a/src/ConfigHardware.h b/src/ConfigHardware.h new file mode 100644 index 0000000..8cfbef7 --- /dev/null +++ b/src/ConfigHardware.h @@ -0,0 +1,10 @@ +#include + +// HX711 load cell +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 + + +const uint32_t CONFIG_SESSION_CHUNK_SIZE = 1024*8 - 3 * sizeof(uint32_t); diff --git a/src/ConfigWifi.h b/src/ConfigWifi.h new file mode 100644 index 0000000..0e18227 --- /dev/null +++ b/src/ConfigWifi.h @@ -0,0 +1,5 @@ + + +const char *CONFIG_WIFI_SSID = "WLAN"; +const char *CONFIG_WIFI_PASSWORD = "Bau3rWLAN"; +const char* CONFIG_HOSTNAME = "smartcords"; diff --git a/config.h b/src/config.h similarity index 64% rename from config.h rename to src/config.h index af74308..0c8d400 100644 --- a/config.h +++ b/src/config.h @@ -1,14 +1,5 @@ -// WIFI Parameters -const char* WIFI_SSID = "RepeaterWZ"; -const char* WIFI_PASSWD = "Bau3rWLAN"; -const char* HOSTNAME = "swimtrainer"; -const bool CORS_HEADER = true; -// HX711 connection -const int LOADCELL_DOUT_PIN = D2; -const int LOADCELL_SCK_PIN = D3; -const int LED_PIN = D1; // Measurement parameters const int DELAY = 100; // interval in ms between measurements diff --git a/src/firmware_main.cpp b/src/firmware_main.cpp new file mode 100644 index 0000000..a6a5922 --- /dev/null +++ b/src/firmware_main.cpp @@ -0,0 +1,123 @@ +// Arduino & ESP headers +#include +#include +#include +#include +#include // for NTP +#include // for NTP + +// Own libs +#include "Dtypes.h" +#include "MockScale.h" +#include "MeasurementSession.h" +#include "SpiffsStorage.h" + +// Configuration +#include "ConfigWifi.h" +#include "ConfigHardware.h" + +AsyncWebServer server(80); +WiFiUDP ntpUDP; +NTPClient timeClient(ntpUDP, "pool.ntp.org"); + +typedef MeasurementSession Session_T; + +template +class SessionManager +{ +public: + void begin(); + + void startMeasurements(); + void stopMeasurements(); + void iteration(); +private: + MockScale scale; + Session_T session; +}; + +SessionManager sessionManager; + +void onNotFound(AsyncWebServerRequest *request) { + request->send(404, "text/plain", "Not found"); +} + +template +void httpSetup(SessionManager * sessionManager) +{ + server.on("/api/session/start", HTTP_POST, [sessionManager](AsyncWebServerRequest * req) { + req->send(200, "text/plain", F("OK")); + sessionManager->startMeasurements(); + }); + server.on("/api/session/stop", HTTP_POST, [sessionManager](AsyncWebServerRequest * req) { + req->send(200, "text/plain", F("OK")); + sessionManager->stopMeasurements(); + }); + server.on("/api/session/data", HTTP_GET, [sessionManager](AsyncWebServerRequest * req) { + //TODO + }); + + + server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send(200, "text/plain", "Hello, world"); + }); + + // Send a GET request to /get?message= + server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) { + String message; + if (request->hasParam(PARAM_MESSAGE)) { + message = request->getParam(PARAM_MESSAGE)->value(); + } else { + message = "No message sent"; + } + request->send(200, "text/plain", "Hello, GET: " + message); + }); + + // Send a POST request to /post with a form field message set to + server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){ + String message; + if (request->hasParam(PARAM_MESSAGE, true)) { + message = request->getParam(PARAM_MESSAGE, true)->value(); + } else { + message = "No message sent"; + } + request->send(200, "text/plain", "Hello, POST: " + message); + }); + + server.onNotFound(onNotFound); + + server.begin(); +} + +void setup() +{ + // Serial + Serial.begin(115200); + while(!Serial) {} + + // WiFi + WiFi.mode(WIFI_STA); + WiFi.begin(CONFIG_WIFI_SSID, CONFIG_WIFI_PASSWORD); + Serial.print(F("\n\n")); + Serial.println(F("Waiting for WIFI connection...")); + while (WiFi.status() != WL_CONNECTED) { + delay(1000); + } + Serial.print(F("Connected to WiFi. IP:")); + Serial.println(WiFi.localIP()); + + // NTP + timeClient.begin(); + timeClient.update(); + session.init( timeClient.getEpochTime() ); + + // Scale + scale.begin(CONFIG_SCALE_DOUT_PIN, CONFIG_SCALE_SCK_PIN); + scale.tare( CONFIG_TARE_AVG_COUNT ); + + // HTTP & Websocket server + httpSetup(); +} + +void loop() { +} diff --git a/sessiontest.cpp b/test/test_common/sessiontest.cpp similarity index 63% rename from sessiontest.cpp rename to test/test_common/sessiontest.cpp index 8777f12..2c9cbb0 100644 --- a/sessiontest.cpp +++ b/test/test_common/sessiontest.cpp @@ -1,8 +1,8 @@ #include "MockDtypes.h" #include "MockSerial.h" -#include "session/Session.h" -#include "session/MockStorage.h" - +#include "MeasurementSession.h" +#include "MockStorage.h" +#include #include template @@ -14,14 +14,15 @@ std::vector parseMessagePack(const uint8_t * data, uint32_t &star const int expectedMapSize = 3; auto mapHeader = reinterpret_cast(&data[offset]); offset += 1; - assert( *mapHeader == (0b10000000 | expectedMapSize), "Map Header wrong"); + TEST_ASSERT_MESSAGE( *mapHeader == (0b10000000 | expectedMapSize), "Map Header wrong"); // string255: sessionStartTime auto stringHeader = reinterpret_cast(&data[offset++]); auto stringSize = reinterpret_cast(&data[offset++]); - assert(*stringHeader == '\xd9', "String header wrong"); + + TEST_ASSERT_EQUAL(*stringHeader, '\xd9'); std::string sessionStartTimeStr = std::string((const char*)(&data[offset]), (size_t)(*stringSize)); - assert( sessionStartTimeStr == "sessionStartTime", "sessionStartTime string is wrong"); + TEST_ASSERT( sessionStartTimeStr == "sessionStartTime"); offset += *stringSize; //uint32 @@ -32,9 +33,9 @@ std::vector parseMessagePack(const uint8_t * data, uint32_t &star // string255: startIndex stringHeader = reinterpret_cast(&data[offset++]); stringSize = reinterpret_cast(&data[offset++]); - assert(*stringHeader == '\xd9', "String header wrong"); + TEST_ASSERT_MESSAGE(*stringHeader == '\xd9', "String header wrong"); std::string startIndexStr = std::string((const char*)(&data[offset]), (size_t)(*stringSize)); - assert( startIndexStr == "startIndex", "startIndex string is wrong"); + TEST_ASSERT_MESSAGE( startIndexStr == "startIndex", "startIndex string is wrong"); offset += *stringSize; //uint32 @@ -45,14 +46,14 @@ std::vector parseMessagePack(const uint8_t * data, uint32_t &star // string255: values stringHeader = reinterpret_cast(&data[offset++]); stringSize = reinterpret_cast(&data[offset++]); - assert(*stringHeader == '\xd9', "String header wrong"); + TEST_ASSERT_MESSAGE(*stringHeader == '\xd9', "String header wrong"); std::string valueStr = std::string((const char*)(&data[offset]), (size_t)(*stringSize)); - assert( valueStr == "values", "values string is wrong"); + TEST_ASSERT_MESSAGE( valueStr == "values", "values string is wrong"); offset += *stringSize; // vector auto vectorHeader = reinterpret_cast(&data[offset++]); - assert( *vectorHeader == '\xc9', "Vector header wrong"); + TEST_ASSERT_MESSAGE( *vectorHeader == '\xc9', "Vector header wrong"); size_t vectorLength = ntohl(*reinterpret_cast(&data[offset])) / sizeof(Measurement_T); offset += 4; offset += 1; // jump over type @@ -68,12 +69,12 @@ void testSessionChunkAdd() SessionChunk chunk; for( uint16_t i=0; i < size; ++i) { bool res = chunk.addPoint(i); - assert(res, "Adding point failed"); - assert( chunk.numMeasurements() == i+1, "Number of measurements reported wrong"); + TEST_ASSERT_MESSAGE(res, "Adding point failed"); + TEST_ASSERT_MESSAGE( chunk.numMeasurements() == i+1, "Number of measurements reported wrong"); } bool res = chunk.addPoint(0); - assert(!res, "Full chunk was not detected"); - assert(chunk.numMeasurements() == size, "Point appears to be added"); + TEST_ASSERT_MESSAGE(!res, "Full chunk was not detected"); + TEST_ASSERT_MESSAGE(chunk.numMeasurements() == size, "Point appears to be added"); } void testSessionChunkGetterSetter() @@ -83,8 +84,8 @@ void testSessionChunkGetterSetter() const uint32_t time = 244213; const uint32_t startIdx = 131; chunk.init(time, startIdx); - assert( chunk.getStartIndex() == startIdx, "Start Index wrong"); - assert( chunk.getStartTime() == time, "Start time wrong"); + TEST_ASSERT_MESSAGE( chunk.getStartIndex() == startIdx, "Start Index wrong"); + TEST_ASSERT_MESSAGE( chunk.getStartTime() == time, "Start time wrong"); } void testSessionChunkSerialization() @@ -98,8 +99,8 @@ void testSessionChunkSerialization() chunk.init(startTime, startIndex); for( uint16_t i=0; i < fillSize; ++i) { bool res = chunk.addPoint(i); - assert(res, "Adding point failed"); - assert( chunk.numMeasurements() == i+1, "Number of measurements reported wrong"); + TEST_ASSERT_MESSAGE(res, "Adding point failed"); + TEST_ASSERT_MESSAGE( chunk.numMeasurements() == i+1, "Number of measurements reported wrong"); } std::vector data; @@ -109,16 +110,16 @@ void testSessionChunkSerialization() uint32_t readStartTime=0; uint32_t readStartIndex=0; auto result = parseMessagePack(&data[0], readStartTime, readStartIndex); - assert(startIndex == readStartIndex && startTime == readStartTime, ""); - assert(result.size() == fillSize, "Wrong result array size"); + TEST_ASSERT_MESSAGE(startIndex == readStartIndex && startTime == readStartTime, ""); + TEST_ASSERT_MESSAGE(result.size() == fillSize, "Wrong result array size"); for( uint16_t i=0; i < fillSize; ++i) { - assert(result[i] == i, "Wrong array contents"); + TEST_ASSERT_MESSAGE(result[i] == i, "Wrong array contents"); } } void testSession() { const uint32_t SESSION_SIZE = 128; - typedef Session MockSession; + typedef MeasurementSession MockSession; const uint32_t startTime = 194842; const uint_t fillSize = SESSION_SIZE * 4 + 7; @@ -136,19 +137,40 @@ void testSession() { uint32_t readStartTime=0; uint32_t readStartIndex=0; auto result = parseMessagePack(&data[0], readStartTime, readStartIndex); - assert(readStartIndex == 0 && startTime == readStartTime, ""); - assert(result.size() == fillSize, "Wrong result array size"); + TEST_ASSERT_MESSAGE(readStartIndex == 0 && startTime == readStartTime, ""); + TEST_ASSERT_MESSAGE(result.size() == fillSize, "Wrong result array size"); for( uint16_t i=0; i < fillSize; ++i) { - assert(result[i] == i, "Wrong array contents"); + TEST_ASSERT_MESSAGE(result[i] == i, "Wrong array contents"); } } +void allTests() +{ + UNITY_BEGIN(); + RUN_TEST(testSessionChunkAdd); + RUN_TEST(testSessionChunkGetterSetter); + RUN_TEST(testSessionChunkSerialization); + RUN_TEST(testSession); + UNITY_END(); +} + +#ifdef ARDUINO +void setup() { + // NOTE!!! Wait for >2 secs + // if board doesn't support software reset via Serial.DTR/RTS + delay(2000); + allTests(); +} + +void loop() { +} + +#else + int main(int argc, char**argv) { - testSessionChunkAdd(); - testSessionChunkGetterSetter(); - testSessionChunkSerialization(); - testSession(); - + allTests(); return 0; } + +#endif \ No newline at end of file diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..d0eab02 --- /dev/null +++ b/todo.txt @@ -0,0 +1,20 @@ +-> setup platform.io based development with tests + - re-write tests with unity + + + +- backend + /api/session/start + /api/session/finish + /api/session/data?startIndex=25 (returns nothing if no session is active) + // by default only the in-memory data is reported back + + /api/sessionhistory/ -> list in webdav fashion + /api/sessionhistory/sessionid?startIndex -> returns full session data + // delete file with method + + + // auto start session? ringbuffer with last n measurements + // detect spikes -> more than s spikes -> start session + // auto stop session if one full chunk is empty +