New logger & removed old unused files
This commit is contained in:
parent
28c85f749c
commit
ce12c846f6
|
@ -3,19 +3,12 @@
|
||||||
#ifndef PLATFORM_NATIVE
|
#ifndef PLATFORM_NATIVE
|
||||||
|
|
||||||
// ---------------------------------- Arduino -------------------------------------------------------------
|
// ---------------------------------- Arduino -------------------------------------------------------------
|
||||||
|
#include "Logger.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
inline void _assert(const char *expression, const char *message, const char *file, int line)
|
inline void _assert(const char *expression, const char *message, const char *file, int line)
|
||||||
{
|
{
|
||||||
Serial.print("Assert ");
|
LOG_WARNING("Assert %s:%d '%s' failed.\n%s", file, line, expression, message);
|
||||||
Serial.print(file);
|
|
||||||
Serial.print(" : ");
|
|
||||||
Serial.print(line);
|
|
||||||
Serial.print(" '");
|
|
||||||
Serial.print(expression);
|
|
||||||
Serial.println("' failed.");
|
|
||||||
Serial.println(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <esp_http_server.h>
|
#include <esp_http_server.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "Dtypes.h"
|
#include "Dtypes.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
constexpr int MAX_URI_HANDLERS = 25;
|
constexpr int MAX_URI_HANDLERS = 25;
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ public:
|
||||||
.handler = rawCallback,
|
.handler = rawCallback,
|
||||||
.user_ctx = (void *)(&handlerCallbacks_[nextFreeHandler_])};
|
.user_ctx = (void *)(&handlerCallbacks_[nextFreeHandler_])};
|
||||||
if (httpd_register_uri_handler(server_, &uri_endpoint_cfg) != ESP_OK)
|
if (httpd_register_uri_handler(server_, &uri_endpoint_cfg) != ESP_OK)
|
||||||
Serial.println("Failed to register url handler");
|
LOG_WARNING("Failed to register url handler");
|
||||||
++nextFreeHandler_;
|
++nextFreeHandler_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "FilesystemAbstraction.h"
|
#include "FilesystemAbstraction.h"
|
||||||
#include "WebDAV.h"
|
#include "WebDAV.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
namespace webdav_constants
|
namespace webdav_constants
|
||||||
{
|
{
|
||||||
|
@ -93,7 +94,7 @@ size_t webdavFileListingSpiffs(char *buffer, size_t maxLength,
|
||||||
toBuffer(MULTISTATUS_END);
|
toBuffer(MULTISTATUS_END);
|
||||||
|
|
||||||
if (incomplete)
|
if (incomplete)
|
||||||
Serial.println("WebDAV listing response is incomplete, because buffer was too small");
|
LOG_WARNING("WebDAV listing response is incomplete, because buffer was too small");
|
||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ std::function<void(httpd_req_t *)> webdavHandler(const char *uriPrefix,
|
||||||
case HTTP_GET:
|
case HTTP_GET:
|
||||||
{
|
{
|
||||||
auto filename = uriToFileName(uri, spiffsFolder);
|
auto filename = uriToFileName(uri, spiffsFolder);
|
||||||
Serial.printf("GET filename %s\n", filename.c_str());
|
LOG_INFO("GET filename %s", filename.c_str());
|
||||||
auto file = portablefs::open(filename.c_str(), "r");
|
auto file = portablefs::open(filename.c_str(), "r");
|
||||||
if (file.available())
|
if (file.available())
|
||||||
{
|
{
|
||||||
|
@ -154,14 +155,14 @@ std::function<void(httpd_req_t *)> webdavHandler(const char *uriPrefix,
|
||||||
}
|
}
|
||||||
case HTTP_OPTIONS:
|
case HTTP_OPTIONS:
|
||||||
{
|
{
|
||||||
Serial.println("Options request");
|
LOG_INFO("Options request");
|
||||||
httpd_resp_set_status(req, "204 No Content");
|
httpd_resp_set_status(req, "204 No Content");
|
||||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Methods", "GET, PROPFIND, DELETE, OPTIONS");
|
httpd_resp_set_hdr(req, "Access-Control-Allow-Methods", "GET, PROPFIND, DELETE, OPTIONS");
|
||||||
httpd_resp_send(req, "", 0);
|
httpd_resp_send(req, "", 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
Serial.printf("Sending 404 %d uri %s\n", req->method, req->uri);
|
LOG_INFO("Sending 404 %d uri %s", req->method, req->uri);
|
||||||
httpd_resp_send_404(req);
|
httpd_resp_send_404(req);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
constexpr size_t LOG_SIZE = 1024 * 1024 * 2;
|
||||||
|
|
||||||
|
static Logger *theLogger = nullptr;
|
||||||
|
|
||||||
|
Logger *Logger::getInstance()
|
||||||
|
{
|
||||||
|
return theLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::init()
|
||||||
|
{
|
||||||
|
theLogger = new Logger();
|
||||||
|
Serial.begin(115200);
|
||||||
|
while (!Serial)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::Logger()
|
||||||
|
{
|
||||||
|
data_ = (char *)heap_caps_malloc(LOG_SIZE, MALLOC_CAP_SPIRAM);
|
||||||
|
totalSize_ = LOG_SIZE;
|
||||||
|
currentSize_ = 0;
|
||||||
|
|
||||||
|
// write header placeholder
|
||||||
|
const auto millisPlaceholder = 0;
|
||||||
|
memcpy(&data_[currentSize_], &millisPlaceholder, sizeof(millisPlaceholder));
|
||||||
|
currentSize_ += sizeof(millisPlaceholder);
|
||||||
|
|
||||||
|
NtpTimeT ntpPlaceholder = 0;
|
||||||
|
memcpy(&data_[currentSize_], &ntpPlaceholder, sizeof(ntpPlaceholder));
|
||||||
|
currentSize_ += sizeof(ntpPlaceholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::setNtpTime(NtpTimeT ntpTime)
|
||||||
|
{
|
||||||
|
auto data = getInstance()->data_;
|
||||||
|
|
||||||
|
const auto millisTime = millis();
|
||||||
|
memcpy(&data[0], &millisTime, sizeof(millisTime));
|
||||||
|
memcpy(&data[sizeof(millisTime)], &ntpTime, sizeof(ntpTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Logger::~Logger()
|
||||||
|
{
|
||||||
|
free(data_);
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#define LOG_INFO(...) \
|
||||||
|
{ \
|
||||||
|
Logger::getInstance()->log(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOG_TRACE(...) \
|
||||||
|
{ \
|
||||||
|
Logger::getInstance()->log(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOG_WARNING(...) \
|
||||||
|
{ \
|
||||||
|
Logger::getInstance()->log(__VA_ARGS__); \
|
||||||
|
}
|
||||||
|
|
||||||
|
class Logger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using NtpTimeT = unsigned long;
|
||||||
|
|
||||||
|
~Logger();
|
||||||
|
|
||||||
|
template <class... Args>
|
||||||
|
inline bool log(const char *formatStr, Args &&...args)
|
||||||
|
{
|
||||||
|
const auto time = millis();
|
||||||
|
|
||||||
|
if (totalSize_ - currentSize_ <= sizeof(time))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memcpy(&data_[currentSize_], &time, sizeof(time));
|
||||||
|
currentSize_ += time;
|
||||||
|
|
||||||
|
const auto spaceLeft = totalSize_ - currentSize_;
|
||||||
|
auto charsWritten = snprintf(&data_[currentSize_], spaceLeft, formatStr,
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
Serial.println(&data_[currentSize_]);
|
||||||
|
|
||||||
|
if (charsWritten < spaceLeft)
|
||||||
|
{
|
||||||
|
currentSize_ += charsWritten;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Logger *getInstance();
|
||||||
|
static void init();
|
||||||
|
static void setNtpTime(NtpTimeT time);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Logger();
|
||||||
|
|
||||||
|
char *data_;
|
||||||
|
size_t totalSize_;
|
||||||
|
size_t currentSize_;
|
||||||
|
};
|
|
@ -7,8 +7,10 @@ class Scale
|
||||||
public:
|
public:
|
||||||
bool measure(uint16_t &measurementOut)
|
bool measure(uint16_t &measurementOut)
|
||||||
{
|
{
|
||||||
long value = hx711_.read_average(CONFIG_MEASUREMENT_AVG_COUNT) - offset_;
|
long value = hx711_.read_average(CONFIG_MEASUREMENT_AVG_COUNT);
|
||||||
Serial.println(value);
|
LOG_TRACE("rv %ld\n", value);
|
||||||
|
value -= offset_;
|
||||||
|
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
measurementOut = (int16_t)(-(value >> valueRightShift_ ));
|
measurementOut = (int16_t)(-(value >> valueRightShift_ ));
|
||||||
else
|
else
|
||||||
|
@ -24,9 +26,9 @@ public:
|
||||||
|
|
||||||
void tare(uint32_t numMeasurementsToAverage = 50)
|
void tare(uint32_t numMeasurementsToAverage = 50)
|
||||||
{
|
{
|
||||||
hx711_.read_average(3);
|
auto v1 = hx711_.read_average(3);
|
||||||
offset_ = hx711_.read_average(numMeasurementsToAverage);
|
offset_ = hx711_.read_average(numMeasurementsToAverage);
|
||||||
Serial.printf("Tare offset %ld\n", offset_);
|
LOG_INFO("Init reading %ld, Tare offset %ld\n", v1, offset_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const long &offset() const { return offset_; }
|
const long &offset() const { return offset_; }
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
#include "SessionChunk.h"
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Measurement_T, typename Reader, typename Writer, uint32_t CHUNK_SIZE>
|
|
||||||
class MeasurementSession {
|
|
||||||
public:
|
|
||||||
typedef SessionChunk<Measurement_T, CHUNK_SIZE> Chunk_T;
|
|
||||||
|
|
||||||
MeasurementSession()
|
|
||||||
: currentChunk(&chunks[0]),
|
|
||||||
otherChunk(&chunks[1]) {}
|
|
||||||
|
|
||||||
void init(uint32_t epochStartTime) {
|
|
||||||
currentChunk = &chunks[0];
|
|
||||||
otherChunk = &chunks[1];
|
|
||||||
currentChunk->init(epochStartTime, 0);
|
|
||||||
otherChunk->init(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool addPoint(Measurement_T measurement) {
|
|
||||||
const bool successful = currentChunk->addPoint(measurement);
|
|
||||||
if (!successful) {
|
|
||||||
Serial.println("Starting session rotate");
|
|
||||||
rotate();
|
|
||||||
const bool secondInsertSuccess = currentChunk->addPoint(measurement);
|
|
||||||
assert_msg(secondInsertSuccess, "Session: insertion after rotation failed");
|
|
||||||
// TODO check that there is place for file - remove old files
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void finalize() {
|
|
||||||
if( otherChunkFilled() )
|
|
||||||
saveChunkToFile(otherChunk);
|
|
||||||
if( currentChunk->numMeasurements() > 0) {
|
|
||||||
saveChunkToFile(currentChunk);
|
|
||||||
}
|
|
||||||
currentChunk->init(0, 0);
|
|
||||||
otherChunk->init(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t numMeasurements() const {
|
|
||||||
return currentChunk->getStartIndex() + currentChunk->numMeasurements();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Encoder_T>
|
|
||||||
void serialize(Encoder_T & encoder, uint32_t startIdx) const
|
|
||||||
{
|
|
||||||
const uint32_t lastIdx = currentChunk->getStartIndex() + currentChunk->numMeasurements();
|
|
||||||
if( lastIdx <= startIdx) {
|
|
||||||
encoder.template sendArray<Measurement_T>(nullptr, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Chunk_T::sendHeader(encoder, currentChunk->getStartTime(), startIdx);
|
|
||||||
encoder.template sendArrayHeader<Measurement_T>(lastIdx - startIdx);
|
|
||||||
while(startIdx < lastIdx)
|
|
||||||
startIdx = serializeChunk(encoder, startIdx);
|
|
||||||
assert_msg(startIdx == lastIdx, "Not all data was sent");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getStartTime() const {
|
|
||||||
return currentChunk->getStartTime();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
void rotate() {
|
|
||||||
if( otherChunkFilled() )
|
|
||||||
saveChunkToFile(otherChunk);
|
|
||||||
swapChunks();
|
|
||||||
|
|
||||||
currentChunk->init(otherChunk->getStartTime(), otherChunk->getStartIndex() + CHUNK_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool otherChunkFilled() const {
|
|
||||||
return otherChunk->numMeasurements() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void swapChunks() {
|
|
||||||
Chunk_T *tmp = currentChunk;
|
|
||||||
currentChunk = otherChunk;
|
|
||||||
otherChunk = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void saveChunkToFile(Chunk_T *chunk) const {
|
|
||||||
const uint32_t chunkNr = chunk->getStartIndex() / CHUNK_SIZE;
|
|
||||||
const auto fileName = chunkFileName(chunkNr, chunk->getStartTime());
|
|
||||||
Serial.print("Writing session to file ");
|
|
||||||
Serial.println(fileName);
|
|
||||||
Writer writer(fileName);
|
|
||||||
chunk->serialize(writer.encoder());
|
|
||||||
};
|
|
||||||
|
|
||||||
template< typename Encoder_T>
|
|
||||||
uint32_t serializeChunk(Encoder_T & encoder, uint32_t startIdx) const {
|
|
||||||
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_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_msg( otherChunk->numMeasurements(), CHUNK_SIZE );
|
|
||||||
return otherChunk->getStartIndex() + otherChunk->numMeasurements();
|
|
||||||
} else {
|
|
||||||
if( encoder.getSizeCountMode() ) {
|
|
||||||
encoder.template sendArrayPartialContents<Measurement_T>(nullptr, CHUNK_SIZE);
|
|
||||||
} else {
|
|
||||||
const uint32_t chunkNr = startIdx / CHUNK_SIZE;
|
|
||||||
const auto chunkFileNameStr = chunkFileName(chunkNr, currentChunk->getStartTime());
|
|
||||||
Reader reader(chunkFileNameStr);
|
|
||||||
reader.seek(Chunk_T::valueOffset());
|
|
||||||
|
|
||||||
const uint32_t PART_SIZE = 32;
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
reader.readBytes((char*) buffer, sizeof(Measurement_T) * PART_SIZE);
|
|
||||||
encoder.template sendArrayPartialContents<Measurement_T>(buffer, PART_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return startIdx + CHUNK_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static String chunkFileName(uint32_t chunkNr, uint32_t startTime) {
|
|
||||||
return("/dat/" + toString(startTime) + String("_") + toString(chunkNr));
|
|
||||||
}
|
|
||||||
|
|
||||||
Chunk_T chunks[2];
|
|
||||||
Chunk_T *currentChunk;
|
|
||||||
Chunk_T *otherChunk;
|
|
||||||
};
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <NTPClient.h>
|
#include <NTPClient.h>
|
||||||
|
|
||||||
#include "AutoStartStop.h"
|
#include "AutoStartStop.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
template <typename SessionT>
|
template <typename SessionT>
|
||||||
class SessionManager
|
class SessionManager
|
||||||
|
@ -32,7 +33,8 @@ public:
|
||||||
void enableAutoStop(bool enable) { autoStop_.enable(enable); }
|
void enableAutoStop(bool enable) { autoStop_.enable(enable); }
|
||||||
bool autoStartEnabled() const { return autoStart_.enabled(); };
|
bool autoStartEnabled() const { return autoStart_.enabled(); };
|
||||||
bool autoStopEnabled() const { return autoStop_.enabled(); }
|
bool autoStopEnabled() const { return autoStop_.enabled(); }
|
||||||
|
|
||||||
|
unsigned long getNtpTime() { return timeClient_.getEpochTime(); }
|
||||||
private:
|
private:
|
||||||
void onMeasurementTaken(MeasurementType measurement);
|
void onMeasurementTaken(MeasurementType measurement);
|
||||||
|
|
||||||
|
@ -69,10 +71,10 @@ void SessionManager<SessionT>::tare()
|
||||||
{
|
{
|
||||||
if (measuring_)
|
if (measuring_)
|
||||||
stopMeasurements();
|
stopMeasurements();
|
||||||
Serial.println("Beginning tare");
|
LOG_INFO("Beginning tare");
|
||||||
scale_.begin(scaleDoutPin_, scaleSckPin_, valueRightShift_);
|
scale_.begin(scaleDoutPin_, scaleSckPin_, valueRightShift_);
|
||||||
scale_.tare(CONFIG_TARE_AVG_COUNT);
|
scale_.tare(CONFIG_TARE_AVG_COUNT);
|
||||||
Serial.println("Finished tare");
|
LOG_INFO("Finished tare");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SessionT>
|
template <typename SessionT>
|
||||||
|
@ -135,7 +137,7 @@ void SessionManager<SessionT>::iteration()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const long skipped = (cycleDuration / CONFIG_MEASURE_DELAY);
|
const long skipped = (cycleDuration / CONFIG_MEASURE_DELAY);
|
||||||
Serial.printf("Measurements skipped: %ld, cycleDuration %ld\n", skipped, cycleDuration);
|
LOG_WARNING("Measurements skipped: %ld, cycleDuration %ld", skipped, cycleDuration);
|
||||||
|
|
||||||
for (int i = 0; i < skipped; ++i)
|
for (int i = 0; i < skipped; ++i)
|
||||||
onMeasurementTaken(measurement);
|
onMeasurementTaken(measurement);
|
||||||
|
@ -154,7 +156,7 @@ void SessionManager<SessionT>::onMeasurementTaken(MeasurementType measurement)
|
||||||
bool autoStop = autoStop_.autoStop(measurement);
|
bool autoStop = autoStop_.autoStop(measurement);
|
||||||
if (autoStop)
|
if (autoStop)
|
||||||
{
|
{
|
||||||
Serial.println("Auto stop");
|
LOG_INFO("Auto stop");
|
||||||
stopMeasurements();
|
stopMeasurements();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +164,7 @@ void SessionManager<SessionT>::onMeasurementTaken(MeasurementType measurement)
|
||||||
bool addPointSuccessful = session_.addPoint(measurement);
|
bool addPointSuccessful = session_.addPoint(measurement);
|
||||||
if (!addPointSuccessful)
|
if (!addPointSuccessful)
|
||||||
{
|
{
|
||||||
Serial.println("Maximum time of session reached - stopping");
|
LOG_INFO("Maximum time of session reached - stopping");
|
||||||
stopMeasurements();
|
stopMeasurements();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -171,7 +173,7 @@ void SessionManager<SessionT>::onMeasurementTaken(MeasurementType measurement)
|
||||||
{
|
{
|
||||||
if (autoStart_.autoStart(measurement))
|
if (autoStart_.autoStart(measurement))
|
||||||
{
|
{
|
||||||
Serial.println("Auto start");
|
LOG_INFO("Auto start");
|
||||||
startMeasurements();
|
startMeasurements();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "Dtypes.h"
|
#include "Dtypes.h"
|
||||||
#include "SessionChunk.h"
|
#include "SessionChunk.h"
|
||||||
#include "FilesystemAbstraction.h"
|
#include "FilesystemAbstraction.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
|
||||||
template <typename Measurement_T, uint32_t MAX_SIZE>
|
template <typename Measurement_T, uint32_t MAX_SIZE>
|
||||||
class SimpleMeasurementSession
|
class SimpleMeasurementSession
|
||||||
|
@ -37,7 +39,7 @@ public:
|
||||||
if (success && (chunk->numMeasurements() % saveInterval_) == 0)
|
if (success && (chunk->numMeasurements() % saveInterval_) == 0)
|
||||||
saveToFileSystem();
|
saveToFileSystem();
|
||||||
if (!success)
|
if (!success)
|
||||||
Serial.println("Failed to add point");
|
LOG_WARNING("Failed to add point");
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +81,9 @@ private:
|
||||||
|
|
||||||
// todo: check this! free doesn't mean that the file writing actually works ok
|
// todo: check this! free doesn't mean that the file writing actually works ok
|
||||||
// use error codes of write instead? anyway: test it!
|
// use error codes of write instead? anyway: test it!
|
||||||
Serial.printf("%ld saveToFileSystem start\n", millis());
|
LOG_INFO("%ld saveToFileSystem start", millis());
|
||||||
deleteUntilBytesFree(CONFIG_SESSION_MAX_SIZE);
|
deleteUntilBytesFree(CONFIG_SESSION_MAX_SIZE);
|
||||||
Serial.printf(" %ld after deleteUntilBytesFree()\n", millis());
|
LOG_INFO(" %ld after deleteUntilBytesFree()", millis());
|
||||||
|
|
||||||
String filename = String(CONFIG_DATA_PATH) + "/" + String(chunk->getStartTime());
|
String filename = String(CONFIG_DATA_PATH) + "/" + String(chunk->getStartTime());
|
||||||
if (portablefs::exists(filename.c_str()))
|
if (portablefs::exists(filename.c_str()))
|
||||||
|
@ -104,7 +106,7 @@ private:
|
||||||
StreamingMsgPackEncoder<portablefs::File> encoder(&file);
|
StreamingMsgPackEncoder<portablefs::File> encoder(&file);
|
||||||
chunk->serialize(encoder);
|
chunk->serialize(encoder);
|
||||||
}
|
}
|
||||||
Serial.printf(" %ld saveToFileSystem done\n", millis());
|
LOG_INFO(" %ld saveToFileSystem done", millis());
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteUntilBytesFree(size_t requiredSpace)
|
void deleteUntilBytesFree(size_t requiredSpace)
|
||||||
|
@ -132,7 +134,7 @@ private:
|
||||||
}
|
}
|
||||||
assert(nextSessionToDelete > 0);
|
assert(nextSessionToDelete > 0);
|
||||||
assert(nextSessionToDelete < uint32_t(-1));
|
assert(nextSessionToDelete < uint32_t(-1));
|
||||||
Serial.printf("Removing old session %s to make space\n", filenameToDelete.c_str());
|
LOG_INFO("Removing old session %s to make space", filenameToDelete.c_str());
|
||||||
portablefs::remove(filenameToDelete.c_str());
|
portablefs::remove(filenameToDelete.c_str());
|
||||||
auto newFreeBytes = portablefs::totalBytes() - portablefs::usedBytes();
|
auto newFreeBytes = portablefs::totalBytes() - portablefs::usedBytes();
|
||||||
assert(newFreeBytes > freeBytes);
|
assert(newFreeBytes > freeBytes);
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include "StreamingMsgPackEncoder.h"
|
|
||||||
#include "FilesystemAbstraction.h"
|
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
|
||||||
|
|
||||||
struct WriterAdaptor
|
|
||||||
{
|
|
||||||
File * f;
|
|
||||||
void write(const char * ptr, size_t size) {
|
|
||||||
f->write(reinterpret_cast<const uint8_t *>(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<WriterAdaptor> &encoder() { return encoder_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
File f_;
|
|
||||||
WriterAdaptor adaptor_;
|
|
||||||
StreamingMsgPackEncoder<WriterAdaptor> encoder_;
|
|
||||||
String fileName_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class SpiffsStorageWriter {
|
|
||||||
public:
|
|
||||||
SpiffsStorageWriter(const String &fileName) :
|
|
||||||
f_(SPIFFS.open(fileName, "w")),
|
|
||||||
encoder_(&f_),
|
|
||||||
fileName_(fileName)
|
|
||||||
{
|
|
||||||
bool success = f_;
|
|
||||||
Serial.println(success);
|
|
||||||
}
|
|
||||||
~SpiffsStorageWriter() {
|
|
||||||
f_.close();
|
|
||||||
Serial.println(fileName_);
|
|
||||||
Serial.println(SPIFFS.exists(fileName_));
|
|
||||||
}
|
|
||||||
StreamingMsgPackEncoder<File> &encoder() { return encoder_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
File f_;
|
|
||||||
StreamingMsgPackEncoder<File> encoder_;
|
|
||||||
String fileName_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SpiffsStorageReader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SpiffsStorageReader(const String &fileName) :
|
|
||||||
f_(SPIFFS.open(fileName, "r"))
|
|
||||||
{}
|
|
||||||
~SpiffsStorageReader() {
|
|
||||||
f_.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t readBytes(char *buffer, size_t length) {
|
|
||||||
return f_.readBytes(buffer, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool seek(uint32_t pos) {
|
|
||||||
return f_.seek(pos);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
File f_;
|
|
||||||
};
|
|
|
@ -60,7 +60,7 @@ public:
|
||||||
{
|
{
|
||||||
auto len = strlen_P(s);
|
auto len = strlen_P(s);
|
||||||
if( len >= 255 ) {
|
if( len >= 255 ) {
|
||||||
Serial.println(F("ERROR: StreamingMsgPackEncoder::string255 - string too long"));
|
LOG_WARNING("ERROR: StreamingMsgPackEncoder::string255 - string too long");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
byte castedLen = (byte)(len);
|
byte castedLen = (byte)(len);
|
||||||
|
|
|
@ -1,237 +0,0 @@
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include "FilesystemAbstraction.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define FLASH_TEXT(name) const char *name
|
|
||||||
|
|
||||||
namespace webdav_constants
|
|
||||||
{
|
|
||||||
FLASH_TEXT(MULTISTATUS_START) = "<?xml version=\"1.0\" ?><D:multistatus xmlns:D=\"DAV:\">";
|
|
||||||
FLASH_TEXT(MULTISTATUS_END) = "</D:multistatus>";
|
|
||||||
FLASH_TEXT(RESPONSE_START) = "<D:response>";
|
|
||||||
FLASH_TEXT(RESPONSE_END) = "</D:response>\n";
|
|
||||||
FLASH_TEXT(HREF_START) = "<D:href>";
|
|
||||||
FLASH_TEXT(HREF_END) = "</D:href>";
|
|
||||||
FLASH_TEXT(PROPSTAT_START) = "<D:propstat>";
|
|
||||||
FLASH_TEXT(PROPSTAT_END) = "</D:propstat>";
|
|
||||||
FLASH_TEXT(PROP_START) = "<D:prop>";
|
|
||||||
FLASH_TEXT(PROP_END) = "</D:prop>";
|
|
||||||
FLASH_TEXT(RESOURCETYPE_START) = "<D:resourcetype>";
|
|
||||||
FLASH_TEXT(RESOURCETYPE_END) = "</D:resourcetype>";
|
|
||||||
FLASH_TEXT(RESOURCE_COLLECTION) = "<D:collection/>";
|
|
||||||
FLASH_TEXT(HTTP_204_NO_CONTENT) = "HTTP/1.1 204 No Content";
|
|
||||||
|
|
||||||
FLASH_TEXT(CONTENTLEN_START) = "<D:getcontentlength>";
|
|
||||||
FLASH_TEXT(CONTENTLEN_END) = "</D:getcontentlength>";
|
|
||||||
FLASH_TEXT(CREATEDATE_START) = "<D:creationdate>";
|
|
||||||
FLASH_TEXT(CREATEDATE_END) = "</D:creationdate>";
|
|
||||||
FLASH_TEXT(MODDATE_START) = "<D:getlastmodified>";
|
|
||||||
FLASH_TEXT(MODDATE_END) = "</D:getlastmodified>";
|
|
||||||
FLASH_TEXT(STATUS_OK) = "<D:status>HTTP/1.1 200 OK</D:status>";
|
|
||||||
} // namespace webdav_constants
|
|
||||||
|
|
||||||
class WebdavFileListCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WebdavFileListCallback(const String &path)
|
|
||||||
: path_(path), headerWritten_(false), finished_(false)
|
|
||||||
{
|
|
||||||
dir_ = portablefs::openDir(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t operator()(uint8_t *buffer, size_t maxLen, size_t index)
|
|
||||||
{
|
|
||||||
Serial.printf("%ld index %u\n", millis(), index);
|
|
||||||
|
|
||||||
using namespace webdav_constants;
|
|
||||||
uint8_t *bufferStart = buffer;
|
|
||||||
|
|
||||||
if (finished_)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!headerWritten_)
|
|
||||||
{
|
|
||||||
toBuffer(buffer, MULTISTATUS_START);
|
|
||||||
headerWritten_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fileFound = false;
|
|
||||||
Serial.printf("%ld (0)\n", millis());
|
|
||||||
while (dir_.next())
|
|
||||||
{
|
|
||||||
if (isFirstFileOfTrainingGroup())
|
|
||||||
{
|
|
||||||
fileFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileFound)
|
|
||||||
{
|
|
||||||
//toBuffer(buffer, path_.c_str());
|
|
||||||
toBuffer(buffer, RESPONSE_START);
|
|
||||||
toBuffer(buffer, HREF_START);
|
|
||||||
Serial.printf("%ld (1)\n", millis());
|
|
||||||
const auto fileName = dir_.fileName();
|
|
||||||
const auto fileNameWithoutDir = fileName.substring(fileName.lastIndexOf("/") + 1);
|
|
||||||
String fileBaseName = fileNameWithoutDir.substring(0, fileNameWithoutDir.indexOf('_'));
|
|
||||||
fileBaseName += ".st";
|
|
||||||
Serial.printf("%ld (2)\n", millis());
|
|
||||||
toBuffer(buffer, fileBaseName.c_str());
|
|
||||||
toBuffer(buffer, HREF_END);
|
|
||||||
toBuffer(buffer, PROPSTAT_START);
|
|
||||||
toBuffer(buffer, PROP_START);
|
|
||||||
if (dir_.isDirectory())
|
|
||||||
{
|
|
||||||
toBuffer(buffer, RESOURCETYPE_START);
|
|
||||||
toBuffer(buffer, RESOURCE_COLLECTION);
|
|
||||||
toBuffer(buffer, RESOURCETYPE_END);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toBuffer(buffer, CONTENTLEN_START);
|
|
||||||
String fileSizeStr(getFileSize(fileName));
|
|
||||||
//toBuffer(buffer, fileSizeStr.c_str());
|
|
||||||
toBuffer(buffer, "1");
|
|
||||||
toBuffer(buffer, CONTENTLEN_END);
|
|
||||||
}
|
|
||||||
Serial.printf("%ld (3)\n", millis());
|
|
||||||
|
|
||||||
toBuffer(buffer, PROP_END);
|
|
||||||
toBuffer(buffer, STATUS_OK);
|
|
||||||
toBuffer(buffer, PROPSTAT_END);
|
|
||||||
toBuffer(buffer, webdav_constants::RESPONSE_END);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toBuffer(buffer, MULTISTATUS_END);
|
|
||||||
finished_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t bytesWritten = buffer - bufferStart;
|
|
||||||
assert_msg(bytesWritten < maxLen, "Written too much!");
|
|
||||||
Serial.printf("%ld Bytes written %u\n", millis(), bytesWritten);
|
|
||||||
//Serial.print("Max bytes ");
|
|
||||||
//Serial.println(maxLen);
|
|
||||||
return bytesWritten;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool isFirstFileOfTrainingGroup()
|
|
||||||
{
|
|
||||||
return !dir_.isDirectory() && dir_.fileName().endsWith("_0");
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t getFileSize(const String &fileZero)
|
|
||||||
{
|
|
||||||
size_t size = 0;
|
|
||||||
auto fileBase = fileZero.substring(0, fileZero.indexOf('_'));
|
|
||||||
auto newDirInstance = portablefs::openDir(path_);
|
|
||||||
while (newDirInstance.next())
|
|
||||||
if (newDirInstance.isFile() && newDirInstance.fileName().startsWith(fileBase))
|
|
||||||
size += newDirInstance.fileSize();
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void toBuffer(uint8_t *&buffer, const char *text)
|
|
||||||
{
|
|
||||||
auto len = strlen(text);
|
|
||||||
memcpy(buffer, text, len);
|
|
||||||
buffer += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
portablefs::Dir dir_;
|
|
||||||
const String path_;
|
|
||||||
bool headerWritten_;
|
|
||||||
bool finished_;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool deleteMeasurementFiles(const String &stName, const String &folder)
|
|
||||||
{
|
|
||||||
String baseName = folder + "/" + stName.substring(0, stName.indexOf("."));
|
|
||||||
int counter = 0;
|
|
||||||
{
|
|
||||||
auto d = portablefs::openDir(folder);
|
|
||||||
while (d.next())
|
|
||||||
if (d.isFile() && d.fileName().startsWith(baseName))
|
|
||||||
++counter;
|
|
||||||
}
|
|
||||||
if (counter == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (int i = 0; i < counter; ++i)
|
|
||||||
{
|
|
||||||
const String pathToDelete = baseName + "_" + String(i);
|
|
||||||
if (!SPIFFS.remove(pathToDelete))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SpiffsWebDavHandler : public AsyncWebHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SpiffsWebDavHandler(const String &prefix, const String &folder)
|
|
||||||
: prefix_(prefix), folder_(folder)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool canHandle(AsyncWebServerRequest *request) override final
|
|
||||||
{
|
|
||||||
Serial.print("Can handle for url : ");
|
|
||||||
Serial.println(request->url());
|
|
||||||
return request->url().startsWith(prefix_);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void handleRequest(AsyncWebServerRequest *request) override final
|
|
||||||
{
|
|
||||||
if (request->url() == prefix_ + "/" && (request->method() == HTTP_GET || request->method() == HTTP_PROPFIND))
|
|
||||||
{
|
|
||||||
// send chunked response - it is too large to send in one go
|
|
||||||
auto response = request->beginChunkedResponse("application/xml",
|
|
||||||
WebdavFileListCallback(folder_));
|
|
||||||
request->send(response);
|
|
||||||
} /*
|
|
||||||
else if(request->url() == prefix_ + "/" && request->method() == HTTP_GET) {
|
|
||||||
AsyncResponseStream * response = request->beginResponseStream("text/plain", 1460*10);
|
|
||||||
Dir dir = SPIFFS.openDir(folder_);
|
|
||||||
Serial.print("Opening folder ");
|
|
||||||
Serial.println(folder_);
|
|
||||||
while (dir.next()) {
|
|
||||||
Serial.print(" File: ");
|
|
||||||
Serial.println(dir.fileName());
|
|
||||||
response->println(dir.fileName());
|
|
||||||
}
|
|
||||||
request->send(response);
|
|
||||||
}*/
|
|
||||||
else if (request->method() == HTTP_GET)
|
|
||||||
{
|
|
||||||
auto path = folder_ + request->url().substring(prefix_.length());
|
|
||||||
if (SPIFFS.exists(path))
|
|
||||||
request->send(SPIFFS, path, "application/x-msgpack");
|
|
||||||
else
|
|
||||||
request->send(404, "text/plain", "Webdav: File not found");
|
|
||||||
}
|
|
||||||
else if (request->method() == HTTP_DELETE)
|
|
||||||
{
|
|
||||||
auto stFileName = request->url().substring(prefix_.length() + 1);
|
|
||||||
Serial.print("HTTP_DELETE for ");
|
|
||||||
Serial.println(stFileName);
|
|
||||||
bool deleteSuccessful = deleteMeasurementFiles(stFileName, folder_);
|
|
||||||
if (deleteSuccessful)
|
|
||||||
request->send(204, "text/plain", "Success");
|
|
||||||
else
|
|
||||||
request->send(404, "text/plain", "Webdav: File to delete not found");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
request->send(404, "text/plain", "Webdav: Invalid request");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual bool isRequestHandlerTrivial() override final { return false; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
String prefix_;
|
|
||||||
String folder_;
|
|
||||||
};
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "WifiManager.h"
|
#include "WifiManager.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
void WifiManager::begin(const String &hostname, const String & wifiStaModeName)
|
void WifiManager::begin(const String &hostname, const String & wifiStaModeName)
|
||||||
{
|
{
|
||||||
|
@ -21,7 +22,7 @@ void WifiManager::startWifi()
|
||||||
// station mode
|
// station mode
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
WiFi.begin(staSSID.c_str(), staPassword.c_str());
|
WiFi.begin(staSSID.c_str(), staPassword.c_str());
|
||||||
Serial.printf("Starting WiFi station mode to ssid %s, hostname %s\n", staSSID.c_str(), hostname_.c_str());
|
LOG_INFO("Starting WiFi station mode to ssid %s, hostname %s", staSSID.c_str(), hostname_.c_str());
|
||||||
WiFi.setHostname(hostname_.c_str());
|
WiFi.setHostname(hostname_.c_str());
|
||||||
int connectCounter = 0;
|
int connectCounter = 0;
|
||||||
bool successful = true;
|
bool successful = true;
|
||||||
|
@ -29,7 +30,7 @@ void WifiManager::startWifi()
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED)
|
while (WiFi.status() != WL_CONNECTED)
|
||||||
{
|
{
|
||||||
Serial.printf("WiFI connection problem %d\n", WiFi.status());
|
LOG_INFO("WiFI connection problem %d", WiFi.status());
|
||||||
WiFi.begin(staSSID.c_str(), staPassword.c_str());
|
WiFi.begin(staSSID.c_str(), staPassword.c_str());
|
||||||
|
|
||||||
connectCounter += 1;
|
connectCounter += 1;
|
||||||
|
@ -51,13 +52,13 @@ void WifiManager::startWifi()
|
||||||
|
|
||||||
if (apPassword.length() > 0)
|
if (apPassword.length() > 0)
|
||||||
{
|
{
|
||||||
Serial.printf("Secured AP mode, name %s\n", wifiStaModeName_.c_str());
|
LOG_INFO("Secured AP mode, name %s\n", wifiStaModeName_.c_str());
|
||||||
WiFi.softAP(wifiStaModeName_.c_str(), apPassword.c_str());
|
WiFi.softAP(wifiStaModeName_.c_str(), apPassword.c_str());
|
||||||
state_ = AP_SECURE;
|
state_ = AP_SECURE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serial.printf("Provisioning AP mode, name %s\n", wifiStaModeName_.c_str());
|
LOG_INFO("Provisioning AP mode, name %s\n", wifiStaModeName_.c_str());
|
||||||
WiFi.softAP(wifiStaModeName_.c_str());
|
WiFi.softAP(wifiStaModeName_.c_str());
|
||||||
state_ = AP_PROVISIONING;
|
state_ = AP_PROVISIONING;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +93,7 @@ void WifiManager::iteration()
|
||||||
if (state_ == STA && WiFi.status() != WL_CONNECTED)
|
if (state_ == STA && WiFi.status() != WL_CONNECTED)
|
||||||
{
|
{
|
||||||
startWifi();
|
startWifi();
|
||||||
Serial.println("Connection lost - Restarting WIFI");
|
LOG_WARNING("Connection lost - Restarting WIFI");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,11 +86,11 @@ bool SessionAPI<T>::handleMessage(websockets::WebsocketsClient &client, MessageC
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case MessageCode::START_SESSION:
|
case MessageCode::START_SESSION:
|
||||||
Serial.println("SessionAPI: starting measurement session");
|
LOG_INFO("SessionAPI: starting measurement session");
|
||||||
this->sessionManager_.startMeasurements();
|
this->sessionManager_.startMeasurements();
|
||||||
return true;
|
return true;
|
||||||
case MessageCode::STOP_SESSION:
|
case MessageCode::STOP_SESSION:
|
||||||
Serial.println("SessionAPI: stopping measurement session");
|
LOG_INFO("SessionAPI: stopping measurement session");
|
||||||
this->sessionManager_.stopMeasurements();
|
this->sessionManager_.stopMeasurements();
|
||||||
return true;
|
return true;
|
||||||
case MessageCode::TARE:
|
case MessageCode::TARE:
|
||||||
|
|
|
@ -48,15 +48,14 @@ public:
|
||||||
|
|
||||||
if (server_.poll())
|
if (server_.poll())
|
||||||
{
|
{
|
||||||
Serial.printf("new websocket connection, storing at pos %d - occupancy: ", nextFreeClient_);
|
LOG_INFO("new websocket connection, storing at pos %d - occupancy: ", nextFreeClient_);
|
||||||
clients_[nextFreeClient_] = server_.accept();
|
clients_[nextFreeClient_] = server_.accept();
|
||||||
clients_[nextFreeClient_].onMessage(onMessage);
|
clients_[nextFreeClient_].onMessage(onMessage);
|
||||||
this->onClientConnectImpl(clients_[nextFreeClient_]);
|
this->onClientConnectImpl(clients_[nextFreeClient_]);
|
||||||
nextFreeClient_ = (nextFreeClient_ + 1) % MAX_WEBSOCKET_CONNECTIONS;
|
nextFreeClient_ = (nextFreeClient_ + 1) % MAX_WEBSOCKET_CONNECTIONS;
|
||||||
|
|
||||||
for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i)
|
for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i)
|
||||||
Serial.print((clients_[i].available()) ? "x" : "o");
|
LOG_INFO((clients_[i].available()) ? "x" : "o");
|
||||||
Serial.print("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i)
|
for (int i = 0; i < MAX_WEBSOCKET_CONNECTIONS; ++i)
|
||||||
|
|
|
@ -35,21 +35,21 @@ bool WifiAPI::handleMessage(websockets::WebsocketsClient &client, MessageCode co
|
||||||
}
|
}
|
||||||
if (json.containsKey("reset_to_provisioning") && json["reset_to_provisioning"].as<bool>())
|
if (json.containsKey("reset_to_provisioning") && json["reset_to_provisioning"].as<bool>())
|
||||||
{
|
{
|
||||||
Serial.println("wifi: reset_to_provisioning");
|
LOG_INFO("wifi: reset_to_provisioning");
|
||||||
wifiManager_.resetToApProvisioning();
|
wifiManager_.resetToApProvisioning();
|
||||||
restartScheduled_ = true;
|
restartScheduled_ = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (json.containsKey("ap_password"))
|
else if (json.containsKey("ap_password"))
|
||||||
{
|
{
|
||||||
Serial.println("wifi: ap_password");
|
LOG_INFO("wifi: ap_password");
|
||||||
wifiManager_.setApCredentials(json["ap_password"].as<const char *>());
|
wifiManager_.setApCredentials(json["ap_password"].as<const char *>());
|
||||||
restartScheduled_ = true;
|
restartScheduled_ = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (json.containsKey("sta_ssid") && json.containsKey("sta_password"))
|
else if (json.containsKey("sta_ssid") && json.containsKey("sta_password"))
|
||||||
{
|
{
|
||||||
Serial.println("wifi: sta_ssid");
|
LOG_INFO("wifi: sta_ssid");
|
||||||
wifiManager_.setStaCredentials(json["sta_ssid"].as<const char *>(), //
|
wifiManager_.setStaCredentials(json["sta_ssid"].as<const char *>(), //
|
||||||
json["sta_password"].as<const char *>());
|
json["sta_password"].as<const char *>());
|
||||||
restartScheduled_ = true;
|
restartScheduled_ = true;
|
||||||
|
|
|
@ -36,7 +36,7 @@ void WifiAPI::iteration(TServer &server)
|
||||||
{
|
{
|
||||||
if (restartScheduled_)
|
if (restartScheduled_)
|
||||||
{
|
{
|
||||||
Serial.print("Restart triggered by WifiAPI");
|
LOG_INFO("Restart triggered by WifiAPI");
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
reportScanResultIfAvailable(server);
|
reportScanResultIfAvailable(server);
|
||||||
|
|
|
@ -14,19 +14,20 @@
|
||||||
#include "WifiManager.h"
|
#include "WifiManager.h"
|
||||||
#include "MockScale.h"
|
#include "MockScale.h"
|
||||||
#include "Scale.h"
|
#include "Scale.h"
|
||||||
#include "MeasurementSession.h"
|
|
||||||
#include "SessionManager.h"
|
#include "SessionManager.h"
|
||||||
#include "SpiffsStorage.h"
|
|
||||||
#include "SimpleMeasurementSession.h"
|
#include "SimpleMeasurementSession.h"
|
||||||
#include "EspHttp.h"
|
#include "EspHttp.h"
|
||||||
#include "WebDAV.h"
|
#include "WebDAV.h"
|
||||||
#include "UserDB.h"
|
#include "UserDB.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
|
||||||
// Api
|
// Api
|
||||||
#include "WebsocketServer.h"
|
#include "WebsocketServer.h"
|
||||||
#include "SessionAPI.h"
|
#include "SessionAPI.h"
|
||||||
#include "WifiAPI.h"
|
#include "WifiAPI.h"
|
||||||
|
|
||||||
|
|
||||||
using Session_T = SimpleMeasurementSession<MeasurementT, CONFIG_SESSION_MAX_SIZE>;
|
using Session_T = SimpleMeasurementSession<MeasurementT, CONFIG_SESSION_MAX_SIZE>;
|
||||||
SessionManager<Session_T> sessionManager;
|
SessionManager<Session_T> sessionManager;
|
||||||
|
|
||||||
|
@ -55,20 +56,19 @@ String getIdSuffix()
|
||||||
bool firmwareUpdate()
|
bool firmwareUpdate()
|
||||||
{
|
{
|
||||||
esp_http_client_config_t config;
|
esp_http_client_config_t config;
|
||||||
Serial.println((char *)certificate_pem);
|
|
||||||
memset(&config, 0, sizeof(esp_http_client_config_t));
|
memset(&config, 0, sizeof(esp_http_client_config_t));
|
||||||
config.url = UPDATE_URL;
|
config.url = UPDATE_URL;
|
||||||
config.cert_pem = (char *)certificate_pem;
|
config.cert_pem = (char *)certificate_pem;
|
||||||
Serial.println("Starting firmware upgrade");
|
LOG_INFO("Starting firmware upgrade");
|
||||||
esp_err_t ret = esp_https_ota(&config);
|
esp_err_t ret = esp_https_ota(&config);
|
||||||
if (ret == ESP_OK)
|
if (ret == ESP_OK)
|
||||||
{
|
{
|
||||||
Serial.println("Firmware upgrade successful - restarting");
|
LOG_INFO("Firmware upgrade successful - restarting");
|
||||||
esp_restart();
|
esp_restart();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serial.println("Firmware upgrade failed");
|
LOG_WARNING("Firmware upgrade failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -108,23 +108,23 @@ void httpSetup(SessionManager<SessionT> *sessionManager, WifiManager *wifiManage
|
||||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||||
httpd_resp_send(req, "Session started", -1);
|
httpd_resp_send(req, "Session started", -1);
|
||||||
sessionManager->startMeasurements();
|
sessionManager->startMeasurements();
|
||||||
Serial.println("Started session");
|
LOG_INFO("RestAPI: Started session");
|
||||||
};
|
};
|
||||||
auto cbStopSession = [sessionManager](httpd_req_t *req)
|
auto cbStopSession = [sessionManager](httpd_req_t *req)
|
||||||
{
|
{
|
||||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||||
httpd_resp_send(req, "Session stopped", -1);
|
httpd_resp_send(req, "Session stopped", -1);
|
||||||
sessionManager->stopMeasurements();
|
sessionManager->stopMeasurements();
|
||||||
Serial.println("Stopped session");
|
LOG_INFO("RestAPI: Stopped session");
|
||||||
};
|
};
|
||||||
auto cbRestart = [](httpd_req_t *req)
|
auto cbRestart = [](httpd_req_t *req)
|
||||||
{
|
{
|
||||||
Serial.println("Restarted requested");
|
LOG_INFO("RestAPI: Restarted requested");
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
};
|
};
|
||||||
auto cbTare = [sessionManager](httpd_req_t *req)
|
auto cbTare = [sessionManager](httpd_req_t *req)
|
||||||
{
|
{
|
||||||
Serial.println("Tare");
|
LOG_INFO("RestAPI: Tare");
|
||||||
sessionManager->tare();
|
sessionManager->tare();
|
||||||
};
|
};
|
||||||
auto cbFirmwareUpdate = [](httpd_req_t *req)
|
auto cbFirmwareUpdate = [](httpd_req_t *req)
|
||||||
|
@ -409,11 +409,11 @@ void httpSetup(SessionManager<SessionT> *sessionManager, WifiManager *wifiManage
|
||||||
espHttpServer.on("/webdav/*?", HTTP_PROPFIND, webdav);
|
espHttpServer.on("/webdav/*?", HTTP_PROPFIND, webdav);
|
||||||
espHttpServer.on("/webdav/*?", HTTP_DELETE, webdav);
|
espHttpServer.on("/webdav/*?", HTTP_DELETE, webdav);
|
||||||
espHttpServer.on("/webdav/*?", HTTP_OPTIONS, webdav);
|
espHttpServer.on("/webdav/*?", HTTP_OPTIONS, webdav);
|
||||||
Serial.println("HTTP setup done");
|
LOG_INFO("HTTP setup done");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serial.println("HTTP setup with limited API in provisioning mode");
|
LOG_INFO("HTTP setup with limited API in provisioning mode");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,49 +421,47 @@ void mdnsSetup(const String &fullHostname)
|
||||||
{
|
{
|
||||||
if (!MDNS.begin(fullHostname.c_str()))
|
if (!MDNS.begin(fullHostname.c_str()))
|
||||||
{
|
{
|
||||||
Serial.println("Error setting up MDNS responder!");
|
LOG_INFO("Error setting up MDNS responder!");
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Serial.printf("mDNS started %s\n", fullHostname.c_str());
|
LOG_INFO("mDNS started %s", fullHostname.c_str());
|
||||||
MDNS.addService("swimtracker", "tcp", 81);
|
MDNS.addService("swimtracker", "tcp", 81);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// Serial
|
// Serial
|
||||||
Serial.begin(115200);
|
Logger::init();
|
||||||
while (!Serial)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// File system
|
// File system
|
||||||
auto millisBeforeSpiffsInit = millis();
|
auto millisBeforeSpiffsInit = millis();
|
||||||
bool spiffsResult = SPIFFS.begin(true);
|
bool spiffsResult = SPIFFS.begin(true);
|
||||||
if (!spiffsResult)
|
if (!spiffsResult)
|
||||||
Serial.println("Failed to mount/format SPIFFS file system");
|
LOG_WARNING("Failed to mount/format SPIFFS file system");
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
|
||||||
auto spiffsSetupTimeSecs = (millis() - millisBeforeSpiffsInit) / 1000;
|
auto spiffsSetupTimeSecs = (millis() - millisBeforeSpiffsInit) / 1000;
|
||||||
|
|
||||||
userStorage.init();
|
userStorage.init();
|
||||||
Serial.printf("Spiffs size: %d MB, setup time %d secs\n", portablefs::totalBytes() / 1024 / 1024, spiffsSetupTimeSecs);
|
LOG_INFO("Spiffs size: %d MB, setup time %ld secs", portablefs::totalBytes() / 1024 / 1024, spiffsSetupTimeSecs);
|
||||||
|
|
||||||
// WiFi
|
// WiFi
|
||||||
Preferences prefs;
|
Preferences prefs;
|
||||||
String uniqueName = "swimtracker" + getIdSuffix();
|
String uniqueName = "swimtracker" + getIdSuffix();
|
||||||
String configuredHostname = prefs.getString("hostname", CONFIG_HOSTNAME + getIdSuffix());
|
String configuredHostname = prefs.getString("hostname", CONFIG_HOSTNAME + getIdSuffix());
|
||||||
wifiManager.begin(configuredHostname, uniqueName);
|
wifiManager.begin(configuredHostname, uniqueName);
|
||||||
Serial.print("Connected to WiFi. IP:");
|
const auto ip = WiFi.localIP();
|
||||||
Serial.println(WiFi.localIP());
|
LOG_INFO("Connected to WiFi. IP: %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
||||||
Serial.printf("WIFI state: %s\n", wifiManager.stateStr());
|
LOG_INFO("WIFI state: %s", wifiManager.stateStr());
|
||||||
|
|
||||||
mdnsSetup(configuredHostname);
|
mdnsSetup(configuredHostname);
|
||||||
|
|
||||||
sessionManagerSetup();
|
sessionManagerSetup();
|
||||||
|
Logger::setNtpTime(sessionManager.getNtpTime());
|
||||||
sessionManager.tare();
|
sessionManager.tare();
|
||||||
|
|
||||||
// HTTP & Websocket server
|
// HTTP & Websocket server
|
||||||
|
|
Loading…
Reference in New Issue