mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-09-14 10:35:30 +00:00
[Cleanup] Group timingstats & fix delete of cache controller files
This commit is contained in:
@@ -102,8 +102,8 @@ boolean Plugin_146(uint8_t function, struct EventStruct *event, String& string)
|
||||
P146_MQTT_MESSAGE_LENGTH = 800;
|
||||
|
||||
String strings[P146_Nlines];
|
||||
strings[P146_TaskInfoTopicIndex] = F("tracker_v2/%sysname%_%unit%/%tskname%/upload_meta");
|
||||
strings[P146_PublishTopicIndex] = F("tracker_v2/%sysname%_%unit%/%tskname%/upload");
|
||||
strings[P146_TaskInfoTopicIndex] = F("%sysname%_%unit%/%tskname%/upload_meta");
|
||||
strings[P146_PublishTopicIndex] = F("%sysname%_%unit%/%tskname%/upload");
|
||||
|
||||
SaveCustomTaskSettings(event->TaskIndex, strings, P146_Nlines, 0);
|
||||
|
||||
@@ -114,6 +114,9 @@ boolean Plugin_146(uint8_t function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
// Init the controller cache handler, just in case the cache controller may not be enabled
|
||||
ControllerCache.init();
|
||||
|
||||
// Restore the last position from RTC when rebooting.
|
||||
ControllerCache.setPeekFilePos(
|
||||
P146_TASKVALUE_FILENR,
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include "../Commands/Common.h"
|
||||
|
||||
#include "../DataStructs/TimingStats.h"
|
||||
|
||||
#include "../ESPEasyCore/Controller.h"
|
||||
#include "../ESPEasyCore/Serial.h"
|
||||
|
||||
@@ -190,7 +192,10 @@ const __FlashStringHelper * Command_Task_ValueSetAndRun(struct EventStruct *even
|
||||
const __FlashStringHelper * returnvalue = taskValueSet(event, Line, taskIndex, success);
|
||||
if (success)
|
||||
{
|
||||
START_TIMER;
|
||||
SensorSendTask(taskIndex);
|
||||
STOP_TIMER(SENSOR_SEND_TASK);
|
||||
|
||||
return return_command_success();
|
||||
}
|
||||
return returnvalue;
|
||||
@@ -208,7 +213,10 @@ const __FlashStringHelper * Command_Task_Run(struct EventStruct *event, const ch
|
||||
return F("TASK_NOT_ENABLED");
|
||||
}
|
||||
|
||||
START_TIMER;
|
||||
SensorSendTask(taskIndex);
|
||||
STOP_TIMER(SENSOR_SEND_TASK);
|
||||
|
||||
return return_command_success();
|
||||
}
|
||||
|
||||
|
||||
@@ -144,19 +144,23 @@ String Caches::getTaskDeviceValueName(taskIndex_t TaskIndex, uint8_t rel_index)
|
||||
return EMPTY_STRING;
|
||||
}
|
||||
|
||||
bool Caches::hasFormula(taskIndex_t TaskIndex)
|
||||
{
|
||||
if (validTaskIndex(TaskIndex)) {
|
||||
// Just a quick test to see if we do have a formula present.
|
||||
// Task Formula are not used very often, so we will probably almost always have to return an empty string.
|
||||
auto it = getExtraTaskSettings(TaskIndex);
|
||||
|
||||
if (it != extraTaskSettings_cache.end()) {
|
||||
return it->second.hasFormula;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String Caches::getTaskDeviceFormula(taskIndex_t TaskIndex, uint8_t rel_index)
|
||||
{
|
||||
if (validTaskIndex(TaskIndex) && (rel_index < VARS_PER_TASK)) {
|
||||
{
|
||||
// Just a quick test to see if we do have a formula present.
|
||||
// Task Formula are not used very often, so we will probably almost always have to return an empty string.
|
||||
auto it = getExtraTaskSettings(TaskIndex);
|
||||
|
||||
if (it != extraTaskSettings_cache.end()) {
|
||||
if (!it->second.hasFormula) { return EMPTY_STRING; }
|
||||
}
|
||||
}
|
||||
|
||||
if (rel_index < VARS_PER_TASK && hasFormula(TaskIndex)) {
|
||||
LoadTaskSettings(TaskIndex);
|
||||
return ExtraTaskSettings.TaskDeviceFormula[rel_index];
|
||||
}
|
||||
|
||||
@@ -67,6 +67,10 @@ struct Caches {
|
||||
String getTaskDeviceValueName(taskIndex_t TaskIndex,
|
||||
uint8_t rel_index);
|
||||
|
||||
// Check to see if at least one of the taskvalues has a non-empty formula field.
|
||||
bool hasFormula(taskIndex_t TaskIndex);
|
||||
|
||||
|
||||
String getTaskDeviceFormula(taskIndex_t TaskIndex,
|
||||
uint8_t rel_index);
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ struct ControllerCache_struct {
|
||||
|
||||
bool deleteAllCacheBlocks();
|
||||
|
||||
void closeOpenFiles();
|
||||
|
||||
void resetpeek();
|
||||
|
||||
bool peekDataAvailable() const;
|
||||
|
||||
@@ -54,6 +54,12 @@ bool ControllerCache_struct::deleteOldestCacheBlock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ControllerCache_struct::closeOpenFiles() {
|
||||
if (_RTC_cache_handler != nullptr) {
|
||||
_RTC_cache_handler->closeOpenFiles();
|
||||
}
|
||||
}
|
||||
|
||||
bool ControllerCache_struct::deleteAllCacheBlocks() {
|
||||
if (_RTC_cache_handler != nullptr) {
|
||||
return _RTC_cache_handler->deleteAllCacheBlocks();
|
||||
|
||||
@@ -75,8 +75,9 @@ bool RTC_cache_handler_struct::peekDataAvailable() const {
|
||||
|
||||
if (_peekfilenr == RTC_cache.writeFileNr) {
|
||||
if (fw) {
|
||||
if ((_peekreadpos + 1) < fw.position()) { return true; }
|
||||
return ((_peekreadpos + 1) < fw.position());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -361,6 +362,17 @@ bool RTC_cache_handler_struct::deleteOldestCacheBlock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void RTC_cache_handler_struct::closeOpenFiles()
|
||||
{
|
||||
if (fr) {
|
||||
fr.close();
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
fp.close();
|
||||
}
|
||||
}
|
||||
|
||||
bool RTC_cache_handler_struct::deleteAllCacheBlocks()
|
||||
{
|
||||
if (updateRTC_filenameCounters()) {
|
||||
|
||||
@@ -70,6 +70,9 @@ struct RTC_cache_handler_struct
|
||||
|
||||
bool deleteAllCacheBlocks();
|
||||
|
||||
// When trying to access cache files, like deleting them, these files must be closed first.
|
||||
void closeOpenFiles();
|
||||
|
||||
private:
|
||||
|
||||
bool loadMetaData();
|
||||
|
||||
@@ -208,9 +208,9 @@ const __FlashStringHelper* getMiscStatsName_F(TimingStatsElements stat) {
|
||||
case TimingStatsElements::SENSOR_SEND_TASK: return F("SensorSendTask()");
|
||||
case TimingStatsElements::SEND_DATA_STATS: return F("sendData()");
|
||||
case TimingStatsElements::COMPUTE_FORMULA_STATS: return F("Compute formula");
|
||||
case TimingStatsElements::COMPUTE_STATS: return F("Compute()");
|
||||
case TimingStatsElements::PLUGIN_CALL_DEVICETIMER_IN: return F("PLUGIN_DEVICETIMER_IN");
|
||||
case TimingStatsElements::SET_NEW_TIMER: return F("setNewTimerAt()");
|
||||
case TimingStatsElements::TIME_DIFF_COMPUTE: return F("timeDiff()");
|
||||
case TimingStatsElements::MQTT_DELAY_QUEUE: return F("Delay queue MQTT");
|
||||
case TimingStatsElements::TRY_CONNECT_HOST_TCP: return F("try_connect_host() (TCP)");
|
||||
case TimingStatsElements::TRY_CONNECT_HOST_UDP: return F("try_connect_host() (UDP)");
|
||||
|
||||
@@ -23,21 +23,8 @@
|
||||
// These TimingStatsElements must not be excluded when FEATURE_TIMING_STATS is not defined.
|
||||
// The Cxxx_DELAY_QUEUE defines are used in the macros to process the controller queues.
|
||||
enum class TimingStatsElements {
|
||||
LOADFILE_STATS,
|
||||
SAVEFILE_STATS,
|
||||
LOOP_STATS,
|
||||
PLUGIN_CALL_50PS,
|
||||
PLUGIN_CALL_10PS,
|
||||
PLUGIN_CALL_10PSU,
|
||||
PLUGIN_CALL_1PS,
|
||||
SENSOR_SEND_TASK,
|
||||
CPLUGIN_CALL_10PS,
|
||||
CPLUGIN_CALL_50PS,
|
||||
SEND_DATA_STATS,
|
||||
COMPUTE_FORMULA_STATS,
|
||||
PLUGIN_CALL_DEVICETIMER_IN,
|
||||
SET_NEW_TIMER,
|
||||
TIME_DIFF_COMPUTE,
|
||||
|
||||
// Controller queue
|
||||
MQTT_DELAY_QUEUE,
|
||||
C001_DELAY_QUEUE,
|
||||
C002_DELAY_QUEUE,
|
||||
@@ -57,6 +44,7 @@ enum class TimingStatsElements {
|
||||
C016_DELAY_QUEUE,
|
||||
C017_DELAY_QUEUE,
|
||||
C018_DELAY_QUEUE,
|
||||
C018_AIR_TIME,
|
||||
C019_DELAY_QUEUE,
|
||||
C020_DELAY_QUEUE,
|
||||
C021_DELAY_QUEUE,
|
||||
@@ -64,40 +52,69 @@ enum class TimingStatsElements {
|
||||
C023_DELAY_QUEUE,
|
||||
C024_DELAY_QUEUE,
|
||||
C025_DELAY_QUEUE,
|
||||
C018_AIR_TIME,
|
||||
LOAD_TASK_SETTINGS,
|
||||
SAVE_TASK_SETTINGS,
|
||||
LOAD_CUSTOM_TASK_STATS,
|
||||
LOAD_CONTROLLER_SETTINGS,
|
||||
TRY_OPEN_FILE,
|
||||
FS_GC_SUCCESS,
|
||||
FS_GC_FAIL,
|
||||
|
||||
|
||||
// Related to Task runs & sending data + rules
|
||||
PLUGIN_CALL_50PS,
|
||||
PLUGIN_CALL_10PS,
|
||||
PLUGIN_CALL_10PSU,
|
||||
PLUGIN_CALL_1PS,
|
||||
CPLUGIN_CALL_10PS,
|
||||
CPLUGIN_CALL_50PS,
|
||||
SENSOR_SEND_TASK,
|
||||
SEND_DATA_STATS,
|
||||
COMPUTE_FORMULA_STATS,
|
||||
COMPUTE_STATS,
|
||||
PARSE_SYSVAR,
|
||||
PARSE_SYSVAR_NOCHANGE,
|
||||
PARSE_TEMPLATE_PADDED,
|
||||
RULES_PROCESSING,
|
||||
RULES_PARSE_LINE,
|
||||
RULES_PROCESS_MATCHED,
|
||||
RULES_MATCH,
|
||||
GRAT_ARP_STATS,
|
||||
SAVE_TO_RTC,
|
||||
BACKGROUND_TASKS,
|
||||
PROCESS_SYSTEM_EVENT_QUEUE,
|
||||
HANDLE_SCHEDULER_IDLE,
|
||||
RULES_MATCH,
|
||||
RULES_PROCESSING,
|
||||
RULES_PROCESS_MATCHED,
|
||||
RULES_PARSE_LINE,
|
||||
|
||||
// Related to file access
|
||||
LOADFILE_STATS,
|
||||
LOAD_TASK_SETTINGS,
|
||||
LOAD_CUSTOM_TASK_STATS,
|
||||
LOAD_CONTROLLER_SETTINGS,
|
||||
SAVEFILE_STATS,
|
||||
SAVE_TASK_SETTINGS,
|
||||
TRY_OPEN_FILE,
|
||||
FS_GC_SUCCESS,
|
||||
FS_GC_FAIL,
|
||||
|
||||
// Scheduler related
|
||||
SAVE_TO_RTC,
|
||||
PLUGIN_CALL_DEVICETIMER_IN,
|
||||
SET_NEW_TIMER,
|
||||
HANDLE_SCHEDULER_TASK,
|
||||
HANDLE_SCHEDULER_IDLE,
|
||||
BACKGROUND_TASKS,
|
||||
|
||||
// Web serving
|
||||
HANDLE_SERVING_WEBPAGE,
|
||||
HANDLE_SERVING_WEBPAGE_JSON,
|
||||
|
||||
// Network related
|
||||
TRY_CONNECT_HOST_TCP,
|
||||
TRY_CONNECT_HOST_UDP,
|
||||
HOST_BY_NAME_STATS,
|
||||
GRAT_ARP_STATS,
|
||||
WIFI_ISCONNECTED_STATS,
|
||||
WIFI_NOTCONNECTED_STATS,
|
||||
CONNECT_CLIENT_STATS,
|
||||
WIFI_SCAN_ASYNC,
|
||||
WIFI_SCAN_SYNC,
|
||||
|
||||
// Time sync (also network related)
|
||||
NTP_SUCCESS,
|
||||
NTP_FAIL,
|
||||
SYSTIME_UPDATED
|
||||
SYSTIME_UPDATED,
|
||||
|
||||
// Close to the lifetime stats shown on the timing stats page
|
||||
LOOP_STATS
|
||||
};
|
||||
|
||||
#if FEATURE_TIMING_STATS
|
||||
|
||||
@@ -648,7 +648,7 @@ void SensorSendTask(taskIndex_t TaskIndex)
|
||||
const uint8_t valueCount = getValueCountForTask(TaskIndex);
|
||||
// Store the previous value, in case %pvalue% is used in the formula
|
||||
String preValue[VARS_PER_TASK];
|
||||
if (Device[DeviceIndex].FormulaOption) {
|
||||
if (Device[DeviceIndex].FormulaOption && Cache.hasFormula(TaskIndex)) {
|
||||
for (uint8_t varNr = 0; varNr < valueCount; varNr++)
|
||||
{
|
||||
const String formula = Cache.getTaskDeviceFormula(TaskIndex, varNr);
|
||||
@@ -672,14 +672,14 @@ void SensorSendTask(taskIndex_t TaskIndex)
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (Device[DeviceIndex].FormulaOption) {
|
||||
START_TIMER;
|
||||
|
||||
if (Device[DeviceIndex].FormulaOption && Cache.hasFormula(TaskIndex)) {
|
||||
for (uint8_t varNr = 0; varNr < valueCount; varNr++)
|
||||
{
|
||||
String formula = Cache.getTaskDeviceFormula(TaskIndex, varNr);
|
||||
if (!formula.isEmpty())
|
||||
{
|
||||
START_TIMER;
|
||||
|
||||
// TD-er: Should we use the set nr of decimals here, or not round at all?
|
||||
// See: https://github.com/letscontrolit/ESPEasy/issues/3721#issuecomment-889649437
|
||||
formula.replace(F("%pvalue%"), preValue[varNr]);
|
||||
@@ -689,9 +689,10 @@ void SensorSendTask(taskIndex_t TaskIndex)
|
||||
if (!isError(Calculate(parseTemplate(formula), result))) {
|
||||
UserVar[TempEvent.BaseVarIndex + varNr] = result;
|
||||
}
|
||||
|
||||
STOP_TIMER(COMPUTE_FORMULA_STATS);
|
||||
}
|
||||
}
|
||||
STOP_TIMER(COMPUTE_FORMULA_STATS);
|
||||
}
|
||||
sendData(&TempEvent);
|
||||
}
|
||||
|
||||
@@ -8,49 +8,6 @@
|
||||
#include "../Globals/Protocol.h"
|
||||
#include "../Helpers/Convert.h"
|
||||
|
||||
/*
|
||||
void logStatistics(uint8_t loglevel, bool clearStats) {
|
||||
if (loglevelActiveFor(loglevel)) {
|
||||
String log;
|
||||
log.reserve(80);
|
||||
for (auto& x: pluginStats) {
|
||||
if (!x.second.isEmpty()) {
|
||||
const int deviceIndex = x.first/256;
|
||||
log = F("PluginStats P_");
|
||||
log += deviceIndex + 1;
|
||||
log += '_';
|
||||
log += getPluginNameFromDeviceIndex(deviceIndex);
|
||||
log += ' ';
|
||||
log += getPluginFunctionName(x.first%256);
|
||||
log += ' ';
|
||||
log += getLogLine(x.second);
|
||||
addLog(loglevel, log);
|
||||
if (clearStats) x.second.reset();
|
||||
}
|
||||
}
|
||||
for (auto& x: miscStats) {
|
||||
if (!x.second.isEmpty()) {
|
||||
log = getMiscStatsName(x.first);
|
||||
log += F(" stats: ");
|
||||
log += getLogLine(x.second);
|
||||
addLog(loglevel, log);
|
||||
if (clearStats) x.second.reset();
|
||||
}
|
||||
}
|
||||
log = getMiscStatsName(TIME_DIFF_COMPUTE);
|
||||
log += F(" stats: Count: ");
|
||||
log += timediff_calls;
|
||||
log += F(" - CPU cycles per call: ");
|
||||
log += static_cast<float>(timediff_cpu_cycles_total) / static_cast<float>(timediff_calls);
|
||||
addLog(loglevel, log);
|
||||
if (clearStats) {
|
||||
timediff_calls = 0;
|
||||
timediff_cpu_cycles_total = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void stream_json_timing_stats(const TimingStats& stats, long timeSinceLastReset) {
|
||||
uint64_t minVal, maxVal;
|
||||
uint64_t count = stats.getMinMax(minVal, maxVal);
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
#include "../Helpers/StringConverter.h"
|
||||
#include "../Helpers/StringParser.h"
|
||||
|
||||
#if FEATURE_RTC_CACHE_STORAGE
|
||||
# include "../Globals/C016_ControllerCache.h"
|
||||
#endif
|
||||
|
||||
#ifdef ESP32
|
||||
#include <esp_partition.h>
|
||||
@@ -124,7 +127,7 @@ String appendToFile(const String& fname, const uint8_t *data, unsigned int size)
|
||||
SPIFFS_CHECK(f, fname.c_str());
|
||||
SPIFFS_CHECK(f.write(data, size), fname.c_str());
|
||||
f.close();
|
||||
return "";
|
||||
return EMPTY_STRING;
|
||||
}
|
||||
|
||||
bool fileExists(const __FlashStringHelper * fname)
|
||||
@@ -148,8 +151,12 @@ bool fileExists(const String& fname) {
|
||||
res = SD.exists(patched_fname);
|
||||
}
|
||||
#endif
|
||||
// Only keep track of existing files. Not the non-existing files from the cache controller
|
||||
if (res || patched_fname.indexOf(F("cache_")) == -1) {
|
||||
// Only keep track of existing files or non-existing filenames that may be requested several times.
|
||||
// Not the non-existing files from the cache controller
|
||||
#if FEATURE_RTC_CACHE_STORAGE
|
||||
if (res || !isCacheFile(patched_fname))
|
||||
#endif
|
||||
{
|
||||
Cache.fileExistsMap[patched_fname] = res;
|
||||
}
|
||||
if (Cache.fileCacheClearMoment == 0) {
|
||||
@@ -213,6 +220,11 @@ bool tryRenameFile(const String& fname_old, const String& fname_new) {
|
||||
bool tryDeleteFile(const String& fname) {
|
||||
if (fname.length() > 0)
|
||||
{
|
||||
#if FEATURE_RTC_CACHE_STORAGE
|
||||
if (isCacheFile(fname)) {
|
||||
ControllerCache.closeOpenFiles();
|
||||
}
|
||||
#endif
|
||||
if (fileMatchesTaskSettingsType(fname)) {
|
||||
clearAllCaches();
|
||||
} else {
|
||||
@@ -1736,7 +1748,7 @@ String createCacheFilename(unsigned int count) {
|
||||
|
||||
// Match string with an integer between '_' and ".bin"
|
||||
int getCacheFileCountFromFilename(const String& fname) {
|
||||
if (fname.indexOf(F("cache_")) == -1) return -1;
|
||||
if (!isCacheFile(fname)) return -1;
|
||||
int startpos = fname.indexOf('_');
|
||||
|
||||
if (startpos < 0) { return -1; }
|
||||
@@ -1753,6 +1765,10 @@ int getCacheFileCountFromFilename(const String& fname) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool isCacheFile(const String& fname) {
|
||||
return fname.indexOf(F("cache_")) != -1;
|
||||
}
|
||||
|
||||
// Look into the filesystem to see if there are any cache files present on the filesystem
|
||||
// Return true if any found.
|
||||
bool getCacheFileCounters(uint16_t& lowest, uint16_t& highest, size_t& filesizeHighest) {
|
||||
|
||||
@@ -300,6 +300,8 @@ bool SpiffsFull();
|
||||
\*********************************************************************************************/
|
||||
String createCacheFilename(unsigned int count);
|
||||
|
||||
bool isCacheFile(const String& fname);
|
||||
|
||||
// Match string with an integer between '_' and ".bin"
|
||||
int getCacheFileCountFromFilename(const String& fname);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "../DataStructs/TimingStats.h"
|
||||
#include "../ESPEasyCore/ESPEasy_Log.h"
|
||||
#include "../Globals/RamTracker.h"
|
||||
#include "../Helpers/ESPEasy_math.h"
|
||||
@@ -649,6 +650,7 @@ int CalculateParam(const String& TmpStr) {
|
||||
CalculateReturnCode Calculate(const String& input,
|
||||
double & result)
|
||||
{
|
||||
START_TIMER;
|
||||
CalculateReturnCode returnCode = RulesCalculate.doCalculate(
|
||||
RulesCalculate_t::preProces(input).c_str(),
|
||||
&result);
|
||||
@@ -690,5 +692,6 @@ CalculateReturnCode Calculate(const String& input,
|
||||
addLogMove(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
}
|
||||
STOP_TIMER(COMPUTE_STATS);
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user