Worked on firmware

This commit is contained in:
Martin Bauer 2019-08-22 21:33:36 +02:00
parent 9889d41805
commit 6a724b284f
24 changed files with 422 additions and 209 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.pio
CMakeListsPrivate.txt

View File

@ -1,7 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
<component name="CidrRootsConfiguration">
<sourceRoots>
<file path="$PROJECT_DIR$/src" />
</sourceRoots>
<libraryRoots>
<file path="$PROJECT_DIR$/lib" />
<file path="$PROJECT_DIR$/.pio/libdeps" />
</libraryRoots>
<excludeRoots>
<file path="$PROJECT_DIR$/.pio" />
</excludeRoots>
</component>
</project>

View File

@ -2,7 +2,8 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/firmware.iml" filepath="$PROJECT_DIR$/.idea/firmware.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/clion.iml" filepath="$PROJECT_DIR$/.idea/clion.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/platformio.iml" filepath="$PROJECT_DIR$/.idea/platformio.iml" />
</modules>
</component>
</project>

View File

@ -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)
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})

View File

@ -1,18 +0,0 @@
#include <FS.h>
#include <ESP8266WebServer.h>
class ESP8266HttpMsgPackWriter {
public:
HttpWriterAdaptor(ESP8266WebServer
* o)
:
obj_(o) {}
void write(const char *data, uint32_t size) {
obj_->sendContent_P(data, size);
}
private:
ESP8266WebServer *obj_;
};

6
dimensions.txt Normal file
View File

@ -0,0 +1,6 @@
92 x 28 x 30
35x20
95x 50 x 30 (absolute min)
100 x 55 x 35

View File

@ -1,138 +0,0 @@
#include "HX711.h"
#include <ESP8266WiFi.h>
#include <WiFiUdp.h> // for NTP
#include <NTPClient.h> // for NTP
#include <ESP8266WebServer.h>
#include <FS.h>
#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);
}
}

17
lib/basic/Dtypes.h Normal file
View File

@ -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__))

32
lib/scale/MockScale.h Normal file
View File

@ -0,0 +1,32 @@
#include <cstdint>
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;
};

30
lib/scale/Scale.h Normal file
View File

@ -0,0 +1,30 @@
#include "HX711.h"
#include <cstdint>
template<int DIVIDER=128>
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_;
};

View File

@ -1,12 +1,12 @@
#include "SessionChunk.h"
template<typename Measurement_T, typename Reader, typename Writer, uint_t CHUNK_SIZE>
class Session {
template<typename Measurement_T, typename Reader, typename Writer, uint32_t CHUNK_SIZE>
class MeasurementSession {
public:
typedef SessionChunk<Measurement_T, CHUNK_SIZE> Chunk_T;
Session()
MeasurementSession()
: currentChunk(&chunks[0]),
otherChunk(&chunks[1]) {}
@ -100,8 +100,9 @@ private:
reader.seek(Chunk_T::template valueOffset<T>());
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)
{

View File

@ -1,7 +1,8 @@
#include "StreamingMsgPackEncoder.h"
#include <cstdint>
template<typename Measurement_T, uint_t SIZE>
template<typename Measurement_T, uint32_t SIZE>
class SessionChunk
{
public:

View File

@ -20,7 +20,7 @@ private:
class SpiffsStorageReader
{
public:
SpiffsBackendReader(const String &fileName) :
SpiffsStorageReader(const String &fileName) :
f_(SPIFFS.open(fileName, "w"))
{}

View File

@ -1,3 +1,4 @@
#pragma once
template<typename T> struct TypeToMsgPackCode{};
template<> struct TypeToMsgPackCode<uint8_t> { static const char CODE; };

25
platformio.ini Normal file
View File

@ -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

10
src/ConfigHardware.h Normal file
View File

@ -0,0 +1,10 @@
#include <cstdint>
// 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);

5
src/ConfigWifi.h Normal file
View File

@ -0,0 +1,5 @@
const char *CONFIG_WIFI_SSID = "WLAN";
const char *CONFIG_WIFI_PASSWORD = "Bau3rWLAN";
const char* CONFIG_HOSTNAME = "smartcords";

View File

@ -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

123
src/firmware_main.cpp Normal file
View File

@ -0,0 +1,123 @@
// Arduino & ESP headers
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <WiFiUdp.h> // for NTP
#include <NTPClient.h> // 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<uint16_t, SpiffsStorageReader, SpiffsStorageWriter, CONFIG_SESSION_CHUNK_SIZE> Session_T;
template<typename Session_T>
class SessionManager
{
public:
void begin();
void startMeasurements();
void stopMeasurements();
void iteration();
private:
MockScale scale;
Session_T session;
};
SessionManager<Session_T> sessionManager;
void onNotFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found");
}
template<typename Session_T>
void httpSetup(SessionManager<Session_T> * 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 <IP>/get?message=<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 <IP>/post with a form field message set to <message>
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() {
}

View File

@ -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 <unity.h>
#include <vector>
template<typename Measurement_T>
@ -14,14 +14,15 @@ std::vector<Measurement_T> parseMessagePack(const uint8_t * data, uint32_t &star
const int expectedMapSize = 3;
auto mapHeader = reinterpret_cast<const uint8_t*>(&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<const char*>(&data[offset++]);
auto stringSize = reinterpret_cast<const uint8_t*>(&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<Measurement_T> parseMessagePack(const uint8_t * data, uint32_t &star
// string255: startIndex
stringHeader = reinterpret_cast<const char*>(&data[offset++]);
stringSize = reinterpret_cast<const uint8_t*>(&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<Measurement_T> parseMessagePack(const uint8_t * data, uint32_t &star
// string255: values
stringHeader = reinterpret_cast<const char*>(&data[offset++]);
stringSize = reinterpret_cast<const uint8_t*>(&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<const char*>(&data[offset++]);
assert( *vectorHeader == '\xc9', "Vector header wrong");
TEST_ASSERT_MESSAGE( *vectorHeader == '\xc9', "Vector header wrong");
size_t vectorLength = ntohl(*reinterpret_cast<const uint32_t*>(&data[offset])) / sizeof(Measurement_T);
offset += 4;
offset += 1; // jump over type
@ -68,12 +69,12 @@ void testSessionChunkAdd()
SessionChunk<uint16_t, size> 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<uint8_t> data;
@ -109,16 +110,16 @@ void testSessionChunkSerialization()
uint32_t readStartTime=0;
uint32_t readStartIndex=0;
auto result = parseMessagePack<uint16_t>(&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<uint16_t, MockStorageReader, MockStorageWriter, SESSION_SIZE> MockSession;
typedef MeasurementSession<uint16_t, MockStorageReader, MockStorageWriter, SESSION_SIZE> 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<uint16_t>(&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

20
todo.txt Normal file
View File

@ -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