Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d59e53d
[GPS] Improve GPS resolution
TD-er Jul 19, 2024
2e4ed8a
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jul 27, 2024
12312d5
[Build] Remove CUL reader from ESP8266 collection D build due to size
TD-er Jul 27, 2024
392e113
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Aug 22, 2024
734b5f8
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Sep 24, 2024
ff9180f
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Sep 26, 2024
2e393f8
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Sep 28, 2024
b803b9f
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Sep 28, 2024
a149f59
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Oct 2, 2024
d1b75a9
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Oct 7, 2024
754ed10
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Dec 16, 2024
398fc3b
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Dec 29, 2024
278af4d
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Dec 30, 2024
ba09610
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jan 12, 2025
ee61ee6
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jan 27, 2025
0031729
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Feb 16, 2025
5f25fde
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Feb 26, 2025
550a321
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Mar 6, 2025
93a6bf9
Merge remote-tracking branch 'letscontrolit/mega' into bugfix/GPS_res…
TD-er Apr 19, 2025
a27cc40
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Apr 21, 2025
6e0ecb7
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Apr 22, 2025
1429a98
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Apr 25, 2025
8e7d10f
Merge remote-tracking branch 'letscontrolit/mega' into bugfix/GPS_res…
TD-er May 25, 2025
01b8ba8
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jun 12, 2025
f350b9b
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jun 14, 2025
2f933eb
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jun 23, 2025
d760351
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jun 25, 2025
7775b1d
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jun 26, 2025
12572b5
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jun 26, 2025
6b52561
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jun 26, 2025
f8c6143
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jul 2, 2025
92a664c
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jul 3, 2025
e78c2f3
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jul 27, 2025
694f347
Merge branch 'mega' into bugfix/GPS_resolution
TD-er Jul 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 48 additions & 9 deletions src/_P082_GPS.ino
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)
dev.TimerOption = true;
dev.PluginStats = true;
dev.CustomVTypeVar = true;
# if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE

// Allow to use double type for improved accuracy
dev.HasFormatUserVar = true;
# endif // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
break;
}

Expand All @@ -68,7 +73,7 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)
switch (choice) {
case P082_query::P082_QUERY_LONG:
case P082_query::P082_QUERY_LAT:
ExtraTaskSettings.TaskDeviceValueDecimals[i] = 6;
ExtraTaskSettings.TaskDeviceValueDecimals[i] = P082_MAX_NR_DECIMALS;
break;
default:
ExtraTaskSettings.TaskDeviceValueDecimals[i] = 2;
Expand Down Expand Up @@ -133,6 +138,37 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)
break;
}

# if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
case PLUGIN_FORMAT_USERVAR:
{
P082_data_struct *P082_data =
static_cast<P082_data_struct *>(getPluginTaskData(event->TaskIndex));

if ((nullptr != P082_data) && P082_data->isInitialized()) {
if (event->idx < P082_NR_OUTPUT_VALUES) {
const uint8_t pconfigIndex = event->idx + P082_QUERY1_CONFIG_POS;
const P082_query query = static_cast<P082_query>(PCONFIG(pconfigIndex));

if ((query == P082_query::P082_QUERY_LONG) ||
(query == P082_query::P082_QUERY_LAT))
{
const uint8_t nrDecimals = Cache.getTaskDeviceValueDecimals(event->TaskIndex, event->idx);

if (nrDecimals > 5) {
const ESPEASY_RULES_FLOAT_TYPE value = P082_data->_cache[static_cast<uint8_t>(query)];

if (!isnan(value)) {
string = doubleToString(value, nrDecimals);
success = true;
}
}
}
}
}
break;
}
# endif // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE

case PLUGIN_GET_CONFIG_VALUE:
{
P082_data_struct *P082_data =
Expand All @@ -142,19 +178,22 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)
const P082_query query = Plugin_082_from_valuename(string);

if (query != P082_query::P082_NR_OUTPUT_OPTIONS) {
const float value = P082_data->_cache[static_cast<uint8_t>(query)];
int nrDecimals = 2;
const ESPEASY_RULES_FLOAT_TYPE value = P082_data->_cache[static_cast<uint8_t>(query)];
int nrDecimals = 2;

if ((query == P082_query::P082_QUERY_LONG) || (query == P082_query::P082_QUERY_LAT)) {
nrDecimals = 6;
nrDecimals = P082_MAX_NR_DECIMALS;
} else if ((query == P082_query::P082_QUERY_SATVIS) ||
(query == P082_query::P082_QUERY_SATUSE) ||
(query == P082_query::P082_QUERY_FIXQ) ||
(query == P082_query::P082_QUERY_CHKSUM_FAIL)) {
nrDecimals = 0;
}

string = toString(value, nrDecimals);
# if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
string = doubleToString(value, nrDecimals);
# else // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
string = toString(value, nrDecimals);
# endif // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
success = true;
}
}
Expand Down Expand Up @@ -417,8 +456,8 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)

if (curFixStatus) {
if (P082_data->gps->location.isUpdated()) {
const float lng = P082_data->gps->location.lng();
const float lat = P082_data->gps->location.lat();
const ESPEASY_RULES_FLOAT_TYPE lng = P082_data->gps->location.lng();
const ESPEASY_RULES_FLOAT_TYPE lat = P082_data->gps->location.lat();
P082_setOutputValue(event, static_cast<uint8_t>(P082_query::P082_QUERY_LONG), lng);
P082_setOutputValue(event, static_cast<uint8_t>(P082_query::P082_QUERY_LAT), lat);

Expand Down Expand Up @@ -584,7 +623,7 @@ bool P082_referencePointSet(struct EventStruct *event) {
&& (P082_LAT_REF < 0.1f) && (P082_LAT_REF > -0.1f));
}

void P082_setOutputValue(struct EventStruct *event, uint8_t outputType, float value) {
void P082_setOutputValue(struct EventStruct *event, uint8_t outputType, ESPEASY_RULES_FLOAT_TYPE value) {
P082_data_struct *P082_data =
static_cast<P082_data_struct *>(getPluginTaskData(event->TaskIndex));

Expand Down
133 changes: 78 additions & 55 deletions src/src/DataStructs/PluginStats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ PluginStats::PluginStats(uint8_t nrDecimals, float errorValue) :
else {
_samples = new (ptr) PluginStatsBuffer_t();
}
# if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
_offset = 0.0f;
# endif // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
_errorValueIsNaN = isnan(_errorValue);
_minValue = std::numeric_limits<float>::max();
_maxValue = std::numeric_limits<float>::lowest();
_minValue = std::numeric_limits<ESPEASY_RULES_FLOAT_TYPE>::max();
_maxValue = std::numeric_limits<ESPEASY_RULES_FLOAT_TYPE>::lowest();
_minValueTimestamp = 0;
_maxValueTimestamp = 0;
}
Expand Down Expand Up @@ -58,51 +61,55 @@ void PluginStats::processTimeSet(const double& time_offset)
}
}

bool PluginStats::push(float value)
bool PluginStats::push(ESPEASY_RULES_FLOAT_TYPE value)
{
if (_samples == nullptr) { return false; }
# if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE

if (_samples->isEmpty() && usableValue(value)) {
// When the first value isn't usable, we keep the offset at 0 and thus loose accuracy
_offset = value;
}
return _samples->push(value - _offset);
# else // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
return _samples->push(value);
# endif // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
}

bool PluginStats::matchesLastTwoEntries(float value) const
bool PluginStats::matchesLastTwoEntries(ESPEASY_RULES_FLOAT_TYPE value) const
{
const size_t nrSamples = getNrSamples();

if (nrSamples < 2) { return false; }

const float last = (*_samples)[nrSamples - 1];
const float beforeLast = (*_samples)[nrSamples - 2];
# if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
return matchesLastTwoEntries(doubleToString(value, _nrDecimals));
# else // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
return matchesLastTwoEntries(toString(value, _nrDecimals));
# endif // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
}

bool PluginStats::matchesLastTwoEntries(const String& value_str) const
{
const size_t nrSamples = getNrSamples();

if (nrSamples < 2) { return false; }

const String value_str = toString(value, _nrDecimals);
const ESPEASY_RULES_FLOAT_TYPE last = get(nrSamples - 1);
const ESPEASY_RULES_FLOAT_TYPE beforeLast = get(nrSamples - 2);

# if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
return
doubleToString(last, _nrDecimals).equals(value_str) &&
doubleToString(beforeLast, _nrDecimals).equals(value_str);
# else // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
return
toString(last, _nrDecimals).equals(value_str) &&
toString(beforeLast, _nrDecimals).equals(value_str);


/*
const bool value_valid = isValidFloat(value);
const bool last_valid = isValidFloat(last);

if (value_valid != last_valid) {
return false;
}
const bool beforeLast_valid = isValidFloat(beforeLast);

if (value_valid != beforeLast_valid) {
return false;
}

if (value_valid) {
return
approximatelyEqual(value, last) &&
approximatelyEqual(value, beforeLast);
}
return true;
*/
# endif // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
}

void PluginStats::trackPeak(float value, int64_t timestamp)
void PluginStats::trackPeak(ESPEASY_RULES_FLOAT_TYPE value, int64_t timestamp)
{
if ((value > _maxValue) || (value < _minValue)) {
if (timestamp == 0) {
Expand All @@ -124,8 +131,8 @@ void PluginStats::trackPeak(float value, int64_t timestamp)

void PluginStats::resetPeaks()
{
_minValue = std::numeric_limits<float>::max();
_maxValue = std::numeric_limits<float>::lowest();
_minValue = std::numeric_limits<ESPEASY_RULES_FLOAT_TYPE>::max();
_maxValue = std::numeric_limits<ESPEASY_RULES_FLOAT_TYPE>::lowest();
_minValueTimestamp = 0;
_maxValueTimestamp = 0;
}
Expand All @@ -141,16 +148,16 @@ size_t PluginStats::getNrSamples() const {
return _samples->size();
}

float PluginStats::getSampleAvg() const {
ESPEASY_RULES_FLOAT_TYPE PluginStats::getSampleAvg() const {
return getSampleAvg(getNrSamples());
}

float PluginStats::getSampleAvg(PluginStatsBuffer_t::index_t lastNrSamples) const
ESPEASY_RULES_FLOAT_TYPE PluginStats::getSampleAvg(PluginStatsBuffer_t::index_t lastNrSamples) const
{
const size_t nrSamples = getNrSamples();

if (nrSamples == 0) { return _errorValue; }
float sum = 0.0f;
ESPEASY_RULES_FLOAT_TYPE sum{};

PluginStatsBuffer_t::index_t i = 0;

Expand All @@ -160,7 +167,7 @@ float PluginStats::getSampleAvg(PluginStatsBuffer_t::index_t lastNrSamples) cons
PluginStatsBuffer_t::index_t samplesUsed = 0;

for (; i < nrSamples; ++i) {
const float sample((*_samples)[i]);
const ESPEASY_RULES_FLOAT_TYPE sample(get(i));

if (usableValue(sample)) {
++samplesUsed;
Expand All @@ -172,7 +179,7 @@ float PluginStats::getSampleAvg(PluginStatsBuffer_t::index_t lastNrSamples) cons
return sum / samplesUsed;
}

float PluginStats::getSampleAvg_time(PluginStatsBuffer_t::index_t lastNrSamples, uint64_t& totalDuration_usec) const
ESPEASY_RULES_FLOAT_TYPE PluginStats::getSampleAvg_time(PluginStatsBuffer_t::index_t lastNrSamples, uint64_t& totalDuration_usec) const
{
const size_t nrSamples = getNrSamples();

Expand All @@ -188,13 +195,13 @@ float PluginStats::getSampleAvg_time(PluginStatsBuffer_t::index_t lastNrSamples,
i = nrSamples - lastNrSamples;
}

int64_t lastTimestamp = 0;
float lastValue = 0.0f;
bool lastValueUsable = false;
float sum = 0.0f;
int64_t lastTimestamp = 0;
ESPEASY_RULES_FLOAT_TYPE lastValue{};
bool lastValueUsable = false;
ESPEASY_RULES_FLOAT_TYPE sum{};

for (; i < nrSamples; ++i) {
const float sample((*_samples)[i]);
const ESPEASY_RULES_FLOAT_TYPE sample(get(i));
const int64_t curTimestamp = (*_plugin_stats_timestamps)[i];
const bool curValueUsable = usableValue(sample);

Expand All @@ -203,7 +210,7 @@ float PluginStats::getSampleAvg_time(PluginStatsBuffer_t::index_t lastNrSamples,

if (curValueUsable) {
// Old and new value usable, take average of this period.
sum += ((lastValue + sample) / 2.0f) * duration_usec;
sum += ((lastValue + sample) / 2) * duration_usec;
} else {
// New value is not usable, so just add the last value for the duration.
sum += lastValue * duration_usec;
Expand All @@ -220,11 +227,11 @@ float PluginStats::getSampleAvg_time(PluginStatsBuffer_t::index_t lastNrSamples,
return sum / totalDuration_usec;
}

float PluginStats::getSampleStdDev(PluginStatsBuffer_t::index_t lastNrSamples) const
ESPEASY_RULES_FLOAT_TYPE PluginStats::getSampleStdDev(PluginStatsBuffer_t::index_t lastNrSamples) const
{
const size_t nrSamples = getNrSamples();
float variance = 0.0f;
const float average = getSampleAvg(lastNrSamples);
ESPEASY_RULES_FLOAT_TYPE variance{};
const ESPEASY_RULES_FLOAT_TYPE average = getSampleAvg(lastNrSamples);

if (!usableValue(average)) { return 0.0f; }

Expand All @@ -236,22 +243,26 @@ float PluginStats::getSampleStdDev(PluginStatsBuffer_t::index_t lastNrSamples) c
PluginStatsBuffer_t::index_t samplesUsed = 0;

for (; i < nrSamples; ++i) {
const float sample((*_samples)[i]);
const ESPEASY_RULES_FLOAT_TYPE sample(get(i));

if (usableValue(sample)) {
++samplesUsed;
const float diff = sample - average;
const ESPEASY_RULES_FLOAT_TYPE diff = sample - average;
variance += diff * diff;
}
}

if (samplesUsed < 2) { return 0.0f; }

variance /= samplesUsed;
# if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
return sqrt(variance);
# else // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
return sqrtf(variance);
# endif // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
}

float PluginStats::getSampleExtreme(PluginStatsBuffer_t::index_t lastNrSamples, bool getMax) const
ESPEASY_RULES_FLOAT_TYPE PluginStats::getSampleExtreme(PluginStatsBuffer_t::index_t lastNrSamples, bool getMax) const
{
const size_t nrSamples = getNrSamples();

Expand All @@ -265,10 +276,10 @@ float PluginStats::getSampleExtreme(PluginStatsBuffer_t::index_t lastNrSamples,

bool changed = false;

float res = getMax ? INT_MIN : INT_MAX;
ESPEASY_RULES_FLOAT_TYPE res = getMax ? INT_MIN : INT_MAX;

for (; i < nrSamples; ++i) {
const float sample((*_samples)[i]);
const ESPEASY_RULES_FLOAT_TYPE sample(get(i));

if (usableValue(sample)) {
if ((getMax && (sample > res)) ||
Expand All @@ -284,7 +295,7 @@ float PluginStats::getSampleExtreme(PluginStatsBuffer_t::index_t lastNrSamples,
return res;
}

float PluginStats::getSample(int lastNrSamples) const
ESPEASY_RULES_FLOAT_TYPE PluginStats::getSample(int lastNrSamples) const
{
const size_t nrSamples = getNrSamples();

Expand All @@ -299,16 +310,28 @@ float PluginStats::getSample(int lastNrSamples) const
}

if (i < nrSamples) {
return (*_samples)[i];
return get(i);
}
return _errorValue;
}

float PluginStats::operator[](PluginStatsBuffer_t::index_t index) const
ESPEASY_RULES_FLOAT_TYPE PluginStats::operator[](PluginStatsBuffer_t::index_t index) const
{
return get(index);
}

ESPEASY_RULES_FLOAT_TYPE PluginStats::get(PluginStatsBuffer_t::index_t index) const
{
const size_t nrSamples = getNrSamples();

if (index < nrSamples) { return (*_samples)[index]; }
if (index < nrSamples) {
# if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
ESPEASY_RULES_FLOAT_TYPE res = _offset + (*_samples)[index];
return res;
# else // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
return (*_samples)[index];
# endif // if FEATURE_USE_DOUBLE_AS_ESPEASY_RULES_FLOAT_TYPE
}
return _errorValue;
}

Expand Down
Loading
Loading