Worked on firmware
This commit is contained in:
parent
9889d41805
commit
6a724b284f
|
@ -0,0 +1,2 @@
|
|||
.pio
|
||||
CMakeListsPrivate.txt
|
|
@ -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>
|
|
@ -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>
|
|
@ -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})
|
||||
|
|
|
@ -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_;
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
92 x 28 x 30
|
||||
35x20
|
||||
|
||||
|
||||
95x 50 x 30 (absolute min)
|
||||
100 x 55 x 35
|
138
firmware.ino
138
firmware.ino
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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__))
|
|
@ -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;
|
||||
};
|
|
@ -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_;
|
||||
};
|
|
@ -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)
|
||||
{
|
|
@ -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:
|
|
@ -20,7 +20,7 @@ private:
|
|||
class SpiffsStorageReader
|
||||
{
|
||||
public:
|
||||
SpiffsBackendReader(const String &fileName) :
|
||||
SpiffsStorageReader(const String &fileName) :
|
||||
f_(SPIFFS.open(fileName, "w"))
|
||||
{}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
template<typename T> struct TypeToMsgPackCode{};
|
||||
template<> struct TypeToMsgPackCode<uint8_t> { static const char CODE; };
|
|
@ -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
|
|
@ -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);
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
|
||||
const char *CONFIG_WIFI_SSID = "WLAN";
|
||||
const char *CONFIG_WIFI_PASSWORD = "Bau3rWLAN";
|
||||
const char* CONFIG_HOSTNAME = "smartcords";
|
|
@ -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
|
|
@ -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() {
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue