Add option to either store native data or averaged data (for chart smootihing) in history buffer

This commit is contained in:
Ulrich Meine
2026-07-06 22:36:18 +02:00
parent da4c66bec2
commit 71e3ba79f6
2 changed files with 42 additions and 22 deletions
+35 -20
View File
@@ -107,7 +107,6 @@ void CalibrationData::readConfig(GwConfigHandler* config)
LOG_DEBUG(GwLog::LOG, "Calibration data type added: %s, offset: %f, slope: %f, smoothing: %f", instance.c_str(), LOG_DEBUG(GwLog::LOG, "Calibration data type added: %s, offset: %f, slope: %f, smoothing: %f", instance.c_str(),
calibrationMap[instance].offset, calibrationMap[instance].slope, calibrationMap[instance].smooth); calibrationMap[instance].offset, calibrationMap[instance].slope, calibrationMap[instance].smooth);
} }
// LOG_DEBUG(GwLog::LOG, "All calibration data read");
} }
// Handle calibrationMap and calibrate all boat data values // Handle calibrationMap and calibrate all boat data values
@@ -208,15 +207,14 @@ bool CalibrationData::smoothInstance(GwApi::BoatValue* boatDataValue)
calibrationMap[instance].value = dataValue; // store the smoothed value in the list calibrationMap[instance].value = dataValue; // store the smoothed value in the list
calibrationMap[instance].isCalibrated = true; calibrationMap[instance].isCalibrated = true;
// LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s: smooth: %f, oldValue: %f, result: %f", instance.c_str(), smoothFactor, oldValue, calibrationMap[instance].value);
return true; return true;
} }
// --- End Class CalibrationData --------------- // --- End Class CalibrationData ---------------
// --- Class HstryBuf --------------- // --- Class HstryBuf ---------------
HstryBuf::HstryBuf(const String& name, int size, BoatValueList* boatValues, GwLog* log) HstryBuf::HstryBuf(const String& name, const int size, BoatValueList* boatValues, const bool smooth, GwLog* log)
: logger(log) : logger(log)
, smoothing(smooth)
, boatDataName(name) , boatDataName(name)
{ {
hstryBuf.resize(size); hstryBuf.resize(size);
@@ -232,23 +230,42 @@ void HstryBuf::init(const String& format, int updFreq, double mltplr, double min
if (!boatValue->valid) { if (!boatValue->valid) {
boatValue->value = std::numeric_limits<double>::max(); // mark current value invalid boatValue->value = std::numeric_limits<double>::max(); // mark current value invalid
} }
isTypeAngle = format == "formatCourse" || format == "formatWind" || format == "formatRot";
// initialize correct variant of buffer for averaging history data
if (smoothing) {
if (isTypeAngle) {
chrtAvgAngle.begin();
} else {
chrtAvg.begin();
}
}
} }
void HstryBuf::add(double value) void HstryBuf::add(const double value)
{ {
double bufVal = value;
if (value >= hstryMin && value <= hstryMax) { if (value >= hstryMin && value <= hstryMax) {
hstryBuf.add(value);
if (smoothing) {
if (isTypeAngle) {
bufVal = chrtAvgAngle.reading(value);
} else {
bufVal = chrtAvg.reading(value);
}
}
hstryBuf.add(bufVal);
// LOG_DEBUG(GwLog::DEBUG, "HstryBuf::add: name: %s, value: %.3f, value buffer: %.3f", hstryBuf.getName(), value, hstryBuf.getLast()); // LOG_DEBUG(GwLog::DEBUG, "HstryBuf::add: name: %s, value: %.3f, value buffer: %.3f", hstryBuf.getName(), value, hstryBuf.getLast());
} }
} }
void HstryBuf::handle(bool useSimuData, CommonData& common) void HstryBuf::handle(const bool useSimuData, CommonData& common)
{ {
if ((millis() - bufUpdateTime) >= hstryBuf.getUpdFreq()) { if ((millis() - bufUpdateTime) >= hstryBuf.getUpdFreq()) {
bufUpdateTime = millis(); bufUpdateTime = millis();
// LOG_DEBUG(GwLog::DEBUG, "HstryBuf::handle: name: %s, frequency: %d, format: %s, value: %.3f", hstryBuf.getName(), hstryBuf.getUpdFreq(),
// boatValue->getFormat().c_str(), boatValue->value);
if (boatValue->valid) { if (boatValue->valid) {
add(boatValue->value); add(boatValue->value);
@@ -262,20 +279,20 @@ void HstryBuf::handle(bool useSimuData, CommonData& common)
double simSIValue = formatValue(tmpBVal.get(), common).value; // simulated value is generated at <formatValue>; here: retreive SI value double simSIValue = formatValue(tmpBVal.get(), common).value; // simulated value is generated at <formatValue>; here: retreive SI value
add(simSIValue); add(simSIValue);
} else { } else {
// here we will add invalid (DBL_MAX) value; this will mark periods of missing data in buffer together with a timestamp // TODO: add invalid (DBL_MAX) value; this will mark periods of missing data in buffer together with a timestamp
} }
} }
} }
// --- End Class HstryBuf --------------- // --- End Class HstryBuf ---------------
// --- Class HstryBuffers --------------- // --- Class HstryBuffers ---------------
HstryBuffers::HstryBuffers(int size, BoatValueList* boatValues, GwLog* log) HstryBuffers::HstryBuffers(const int size, BoatValueList* boatValues, GwLog* log)
: size(size) : size(size)
, boatValueList(boatValues) , boatValueList(boatValues)
, logger(log) { }; , logger(log) { };
// Create history buffer for boat data type // Create history buffer for boat data type
void HstryBuffers::addBuffer(const String& name) void HstryBuffers::addBuffer(const String& name, const bool smooth)
{ {
if (HstryBuffers::getBuffer(name) != nullptr) { // buffer for this data type already exists if (HstryBuffers::getBuffer(name) != nullptr) { // buffer for this data type already exists
return; return;
@@ -288,8 +305,9 @@ void HstryBuffers::addBuffer(const String& name)
} }
// create buffer only; initialization with metadata can only be done later after boat data have been updated first time // create buffer only; initialization with metadata can only be done later after boat data have been updated first time
hstryBuffers[name] = std::unique_ptr<HstryBuf>(new HstryBuf(name, size, boatValueList, logger)); hstryBuffers[name] = std::unique_ptr<HstryBuf>(new HstryBuf(name, size, boatValueList, smooth, logger));
LOG_DEBUG(GwLog::DEBUG, "HstryBuffers: new buffer added: name: %s", name);
LOG_DEBUG(GwLog::LOG, "HstryBuffers: new buffer added: name: %s", name);
} }
// Handle all registered history buffers // Handle all registered history buffers
@@ -301,7 +319,7 @@ void HstryBuffers::handleHstryBufs(bool useSimuData, CommonData& common)
if (!buf->hasMetaData()) { // meta data initialization for buffer has not been done before if (!buf->hasMetaData()) { // meta data initialization for buffer has not been done before
String valueFormat = boatValueList->findValueOrCreate(buf->boatDataName)->getFormat().c_str(); String valueFormat = boatValueList->findValueOrCreate(buf->boatDataName)->getFormat().c_str();
LOG_DEBUG(GwLog::DEBUG, "HstryBuffers: value name: %s, format: %s", boatValueList->findValueOrCreate(buf->boatDataName)->getName().c_str(), valueFormat); // LOG_DEBUG(GwLog::DEBUG, "HstryBuffers: value name: %s, format: %s", boatValueList->findValueOrCreate(buf->boatDataName)->getName().c_str(), valueFormat);
if (!valueFormat.isEmpty()) { if (!valueFormat.isEmpty()) {
String lookupKey = buf->boatDataName; String lookupKey = buf->boatDataName;
@@ -321,7 +339,7 @@ void HstryBuffers::handleHstryBufs(bool useSimuData, CommonData& common)
hstryBuffers[buf->boatDataName]->init(valueFormat, hstryUpdFreq, mltplr, bufferMinVal, bufferMaxVal); hstryBuffers[buf->boatDataName]->init(valueFormat, hstryUpdFreq, mltplr, bufferMinVal, bufferMaxVal);
buf->metaDataDefined = true; buf->metaDataDefined = true;
LOG_DEBUG(GwLog::DEBUG, "HstryBuffers::handleBufs: metadata added: name: %s, format: %s, frequency: %d, multiplier: %f, min value: %.2f, max value: %.2f", buf->boatDataName, valueFormat, hstryUpdFreq, LOG_DEBUG(GwLog::LOG, "HstryBuffers::handleBufs: metadata added: name: %s, format: %s, frequency: %d, multiplier: %f, min value: %.2f, max value: %.2f", buf->boatDataName, valueFormat, hstryUpdFreq,
mltplr, bufferMinVal, bufferMaxVal); mltplr, bufferMinVal, bufferMaxVal);
} }
} }
@@ -433,8 +451,6 @@ bool WindUtils::calcHDT(const double* hdmVal, const double* varVal, const double
*hdtVal = DBL_MAX; // Cannot calculate HDT without valid HDM or HDM+VAR or COG *hdtVal = DBL_MAX; // Cannot calculate HDT without valid HDM or HDM+VAR or COG
return false; return false;
} }
// LOG_DEBUG(GwLog::DEBUG, "WindUtils:calcHDT: HDT: %.1f, HDM %.1f, VAR %.1f, COG %.1f, SOG %.1f", *hdtVal * RAD_TO_DEG, *hdmVal * RAD_TO_DEG, *varVal * RAD_TO_DEG,
// *cogVal * RAD_TO_DEG, *sogVal * 3.6 / 1.852);
return true; return true;
} }
@@ -482,7 +498,6 @@ bool WindUtils::calcTrueWinds(const double* awaVal, const double* awsVal, const
// If STW and SOG are not available, we cannot calculate true wind // If STW and SOG are not available, we cannot calculate true wind
return false; return false;
} }
// LOG_DEBUG(GwLog::DEBUG, "WindUtils:calcTrueWinds: HDT: %.1f, CTW %.1f, STW %.1f", *hdtVal * RAD_TO_DEG, ctw * RAD_TO_DEG, stw * 3.6 / 1.852);
calcTwdSA(awaVal, awsVal, awd, &ctw, &stw, hdtVal, &twa, &tws, &twd); calcTwdSA(awaVal, awsVal, awd, &ctw, &stw, hdtVal, &twa, &tws, &twd);
*twaVal = twa; *twaVal = twa;
@@ -501,7 +516,7 @@ void WindUtils::setMaxWs(GwApi::BoatValue* wsMaxValue, const double* wsVal)
maxWs = *wsVal; maxWs = *wsVal;
} }
if ( maxWs > 0.0 && maxWs >= wsMaxValue->value) { if (maxWs > 0.0 && maxWs >= wsMaxValue->value) {
wsMaxValue->value = maxWs; // overwrite core gateway value each second again with own user task value if that value is larger wsMaxValue->value = maxWs; // overwrite core gateway value each second again with own user task value if that value is larger
wsMaxValue->valid = true; wsMaxValue->valid = true;
} }
+7 -2
View File
@@ -3,6 +3,7 @@
#include "OBPRingBuffer.h" #include "OBPRingBuffer.h"
#include "Pagedata.h" #include "Pagedata.h"
#include "obp60task.h" #include "obp60task.h"
#include "movingAvg.h"
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
@@ -36,10 +37,14 @@ public:
class HstryBuf { class HstryBuf {
private: private:
RingBuffer<uint16_t> hstryBuf; // Circular buffer to store history values RingBuffer<uint16_t> hstryBuf; // Circular buffer to store history values
movingAvg<double> chrtAvg {6}; // Store average of the last 6 chart values if chart gradient shall be smoothed
movingAvgAngle<double> chrtAvgAngle {6}; // Store average of the last 6 chart values (angle data) if chart gradient shall be smoothed
String boatDataName; String boatDataName;
double hstryMin; double hstryMin;
double hstryMax; double hstryMax;
bool metaDataDefined = false; bool metaDataDefined = false;
bool smoothing = false;
bool isTypeAngle = false;
unsigned long bufUpdateTime; unsigned long bufUpdateTime;
GwApi::BoatValue* boatValue; GwApi::BoatValue* boatValue;
GwLog* logger; GwLog* logger;
@@ -47,7 +52,7 @@ private:
friend class HstryBuffers; friend class HstryBuffers;
public: public:
HstryBuf(const String& name, int size, BoatValueList* boatValues, GwLog* log); HstryBuf(const String& name, const int size, BoatValueList* boatValues, const bool smooth, GwLog* log);
bool hasMetaData() const { return metaDataDefined; }; bool hasMetaData() const { return metaDataDefined; };
void init(const String& format, int updFreq, double mltplr, double minVal, double maxVal); void init(const String& format, int updFreq, double mltplr, double minVal, double maxVal);
void add(double value); void add(double value);
@@ -101,7 +106,7 @@ private:
public: public:
HstryBuffers(int size, BoatValueList* boatValues, GwLog* log); HstryBuffers(int size, BoatValueList* boatValues, GwLog* log);
void addBuffer(const String& name); void addBuffer(const String& name, const bool smooth);
void handleHstryBufs(bool useSimuData, CommonData& common); void handleHstryBufs(bool useSimuData, CommonData& common);
RingBuffer<uint16_t>* getBuffer(const String& name); RingBuffer<uint16_t>* getBuffer(const String& name);
}; };