mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-08 20:46:52 +03:00
logfile rotating implemented
This commit is contained in:
@@ -84,7 +84,7 @@ static esp_err_t favicon_get_handler(httpd_req_t *req)
|
||||
* a list of all files and folders under the requested path.
|
||||
* In case of SPIFFS this returns empty list when path is any
|
||||
* string other than '/', since SPIFFS doesn't support directories */
|
||||
static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
|
||||
static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const char* uripath, bool readonly)
|
||||
{
|
||||
char entrypath[FILE_PATH_MAX];
|
||||
char entrysize[16];
|
||||
@@ -120,13 +120,13 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
|
||||
httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
if (!readonly) {
|
||||
FILE *fd = fopen("/sdcard/html/upload_script.html", "r");
|
||||
char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
|
||||
size_t chunksize;
|
||||
do {
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
// printf("Chunksize %d\n", chunksize);
|
||||
// printf("Chunksize %d\n", chunksize);
|
||||
if (chunksize > 0){
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
fclose(fd);
|
||||
@@ -136,8 +136,8 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
|
||||
}
|
||||
} while (chunksize != 0);
|
||||
fclose(fd);
|
||||
// ESP_LOGI(TAG, "File sending complete");
|
||||
|
||||
// ESP_LOGI(TAG, "File sending complete");
|
||||
}
|
||||
///////////////////////////////
|
||||
|
||||
std::string _zw = std::string(dirpath);
|
||||
@@ -149,12 +149,16 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
|
||||
httpd_resp_sendstr_chunk(req,
|
||||
"<table class=\"fixed\" border=\"1\">"
|
||||
"<col width=\"800px\" /><col width=\"300px\" /><col width=\"300px\" /><col width=\"100px\" />"
|
||||
"<thead><tr><th>Name</th><th>Type</th><th>Size (Bytes)</th><th>Delete<br>"
|
||||
"<thead><tr><th>Name</th><th>Type</th><th>Size (Bytes)</th>");
|
||||
if (!readonly) {
|
||||
httpd_resp_sendstr_chunk(req, "<th>Delete<br>"
|
||||
"<form method=\"post\" action=\"");
|
||||
httpd_resp_sendstr_chunk(req, _zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req,
|
||||
"\"><button type=\"submit\">DELETE ALL!</button></form>"
|
||||
"</th></tr></thead><tbody>\n");
|
||||
"</th></tr>");
|
||||
}
|
||||
httpd_resp_sendstr_chunk(req, "</thead><tbody>\n");
|
||||
|
||||
/* Iterate over all files / folders and fetch their names and sizes */
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
@@ -173,7 +177,8 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
|
||||
|
||||
/* Send chunk of HTML file containing table entries with file name and size */
|
||||
httpd_resp_sendstr_chunk(req, "<tr><td><a href=\"");
|
||||
httpd_resp_sendstr_chunk(req, req->uri);
|
||||
httpd_resp_sendstr_chunk(req, "/fileserver");
|
||||
httpd_resp_sendstr_chunk(req, uripath);
|
||||
httpd_resp_sendstr_chunk(req, entry->d_name);
|
||||
if (entry->d_type == DT_DIR) {
|
||||
httpd_resp_sendstr_chunk(req, "/");
|
||||
@@ -184,11 +189,13 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
|
||||
httpd_resp_sendstr_chunk(req, entrytype);
|
||||
httpd_resp_sendstr_chunk(req, "</td><td>");
|
||||
httpd_resp_sendstr_chunk(req, entrysize);
|
||||
if (!readonly) {
|
||||
httpd_resp_sendstr_chunk(req, "</td><td>");
|
||||
httpd_resp_sendstr_chunk(req, "<form method=\"post\" action=\"/delete");
|
||||
httpd_resp_sendstr_chunk(req, req->uri + strlen("/fileserver"));
|
||||
httpd_resp_sendstr_chunk(req, uripath);
|
||||
httpd_resp_sendstr_chunk(req, entry->d_name);
|
||||
httpd_resp_sendstr_chunk(req, "\"><button type=\"submit\">Delete</button></form>");
|
||||
}
|
||||
httpd_resp_sendstr_chunk(req, "</td></tr>\n");
|
||||
}
|
||||
}
|
||||
@@ -226,6 +233,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
// filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
|
||||
// req->uri, sizeof(filepath));
|
||||
|
||||
|
||||
if (!filename) {
|
||||
ESP_LOGE(TAG, "Filename is too long");
|
||||
/* Respond with 500 Internal Server Error */
|
||||
@@ -235,7 +243,22 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
|
||||
/* If name has trailing '/', respond with directory contents */
|
||||
if (filename[strlen(filename) - 1] == '/') {
|
||||
return http_resp_dir_html(req, filepath);
|
||||
bool readonly = false;
|
||||
size_t buf_len = httpd_req_get_url_query_len(req) + 1;
|
||||
if (buf_len > 1) {
|
||||
char buf[buf_len];
|
||||
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Found URL query => %s", buf);
|
||||
char param[32];
|
||||
/* Get value of expected key from query string */
|
||||
if (httpd_query_key_value(buf, "readonly", param, sizeof(param)) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Found URL query parameter => readonly=%s", param);
|
||||
readonly = param && strcmp(param,"true")==0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return http_resp_dir_html(req, filepath, filename, readonly);
|
||||
}
|
||||
|
||||
std::string testwlan = toUpper(std::string(filename));
|
||||
|
||||
@@ -281,6 +281,10 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
LogFile.SwitchOnOff(false);
|
||||
}
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
{
|
||||
LogFile.SetRetention(std::stoi(zerlegt[1]));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
static const char* TAG2 = "example";
|
||||
|
||||
#define BLINK_GPIO GPIO_NUM_4
|
||||
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
//#pragma warning(disable : 4996)
|
||||
|
||||
#include "Helper.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
|
||||
//#define ISWINDOWS_TRUE
|
||||
#define PATH_MAX_STRING_SIZE 256
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -159,6 +163,63 @@ string getFileType(string filename)
|
||||
return zw;
|
||||
}
|
||||
|
||||
/* recursive mkdir */
|
||||
int mkdir_r(const char *dir, const mode_t mode) {
|
||||
char tmp[PATH_MAX_STRING_SIZE];
|
||||
char *p = NULL;
|
||||
struct stat sb;
|
||||
size_t len;
|
||||
|
||||
/* copy path */
|
||||
len = strnlen (dir, PATH_MAX_STRING_SIZE);
|
||||
if (len == 0 || len == PATH_MAX_STRING_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
memcpy (tmp, dir, len);
|
||||
tmp[len] = '\0';
|
||||
|
||||
/* remove trailing slash */
|
||||
if(tmp[len - 1] == '/') {
|
||||
tmp[len - 1] = '\0';
|
||||
}
|
||||
|
||||
/* check if path exists and is a directory */
|
||||
if (stat (tmp, &sb) == 0) {
|
||||
if (S_ISDIR (sb.st_mode)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* recursive mkdir */
|
||||
for(p = tmp + 1; *p; p++) {
|
||||
if(*p == '/') {
|
||||
*p = 0;
|
||||
/* test path */
|
||||
if (stat(tmp, &sb) != 0) {
|
||||
/* path does not exist - create directory */
|
||||
if (mkdir(tmp, mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else if (!S_ISDIR(sb.st_mode)) {
|
||||
/* not a directory */
|
||||
return -1;
|
||||
}
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
/* test path */
|
||||
if (stat(tmp, &sb) != 0) {
|
||||
/* path does not exist - create directory */
|
||||
if (mkdir(tmp, mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else if (!S_ISDIR(sb.st_mode)) {
|
||||
/* not a directory */
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
string toUpper(string in)
|
||||
{
|
||||
for (int i = 0; i < in.length(); ++i)
|
||||
@@ -173,3 +234,9 @@ float temperatureRead()
|
||||
{
|
||||
return (temprature_sens_read() - 32) / 1.8;
|
||||
}
|
||||
|
||||
time_t addDays(time_t startTime, int days) {
|
||||
struct tm* tm = localtime(&startTime);
|
||||
tm->tm_mday += days;
|
||||
return mktime(tm);
|
||||
}
|
||||
@@ -17,6 +17,10 @@ bool ctype_space(const char c, string adddelimiter);
|
||||
|
||||
string getFileType(string filename);
|
||||
|
||||
int mkdir_r(const char *dir, const mode_t mode);
|
||||
|
||||
string toUpper(string in);
|
||||
|
||||
float temperatureRead();
|
||||
|
||||
time_t addDays(time_t startTime, int days);
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
#include "ClassLogFile.h"
|
||||
#include "time_sntp.h"
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include "Helper.h"
|
||||
|
||||
ClassLogFile LogFile("/sdcard/log.txt");
|
||||
static const char *TAG = "log";
|
||||
|
||||
ClassLogFile LogFile("/sdcard/log/message", "log_%Y-%m-%d.txt");
|
||||
|
||||
void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool _time)
|
||||
{
|
||||
@@ -13,7 +20,7 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool
|
||||
}
|
||||
|
||||
pFile = fopen(_fn.c_str(), "a+");
|
||||
|
||||
if (pFile!=NULL) {
|
||||
if (_time)
|
||||
{
|
||||
time_t rawtime;
|
||||
@@ -32,20 +39,92 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool
|
||||
fputs("\n", pFile);
|
||||
|
||||
fclose(pFile);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Can't open log file %s", _fn.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLogFile::SwitchOnOff(bool _doLogFile){
|
||||
doLogFile = _doLogFile;
|
||||
};
|
||||
|
||||
void ClassLogFile::SetRetention(unsigned short _retentionInDays){
|
||||
retentionInDays = _retentionInDays;
|
||||
};
|
||||
|
||||
void ClassLogFile::WriteToFile(std::string info, bool _time)
|
||||
{
|
||||
WriteToDedicatedFile(logfile, info, _time);
|
||||
struct stat path_stat;
|
||||
if (stat(logroot.c_str(), &path_stat) != 0) {
|
||||
ESP_LOGI(TAG, "Create log folder: %s", logroot.c_str());
|
||||
if (mkdir_r(logroot.c_str(), S_IRWXU) == -1) {
|
||||
ESP_LOGI(TAG, "Can't create log foolder");
|
||||
}
|
||||
}
|
||||
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char buffer[30];
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
strftime(buffer, 30, logfile.c_str(), timeinfo);
|
||||
std::string logpath = logroot + "/" + buffer;
|
||||
|
||||
WriteToDedicatedFile(logpath, info, _time);
|
||||
}
|
||||
|
||||
ClassLogFile::ClassLogFile(std::string _logfile)
|
||||
void ClassLogFile::RemoveOld()
|
||||
{
|
||||
if (retentionInDays == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char cmpfilename[30];
|
||||
|
||||
time(&rawtime);
|
||||
rawtime = addDays(rawtime, -retentionInDays);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
strftime(cmpfilename, 30, logfile.c_str(), timeinfo);
|
||||
//ESP_LOGE(TAG, "log file name to compare: %s", cmpfilename);
|
||||
|
||||
DIR *dir = opendir(logroot.c_str());
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", logroot.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent *entry;
|
||||
int deleted = 0;
|
||||
int notDeleted = 0;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (entry->d_type == DT_REG) {
|
||||
//ESP_LOGE(TAG, "list log file : %s", entry->d_name);
|
||||
if ((strlen(entry->d_name) == strlen(cmpfilename)) && (strcmp(entry->d_name, cmpfilename) < 0)) {
|
||||
ESP_LOGE(TAG, "delete log file : %s", entry->d_name);
|
||||
std::string filepath = logroot + "/" + entry->d_name;
|
||||
if (unlink(filepath.c_str()) == 0) {
|
||||
deleted ++;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "can't delete file : %s", entry->d_name);
|
||||
}
|
||||
} else {
|
||||
notDeleted ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ESP_LOGE(TAG, "%d older log files deleted. %d current log files not deleted.", deleted, notDeleted);
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
ClassLogFile::ClassLogFile(std::string _logroot, std::string _logfile)
|
||||
{
|
||||
logroot = _logroot;
|
||||
logfile = _logfile;
|
||||
doLogFile = true;
|
||||
retentionInDays = 10;
|
||||
}
|
||||
@@ -5,15 +5,19 @@
|
||||
class ClassLogFile
|
||||
{
|
||||
private:
|
||||
std::string logroot;
|
||||
std::string logfile;
|
||||
bool doLogFile;
|
||||
unsigned short retentionInDays;
|
||||
public:
|
||||
ClassLogFile(std::string _logfile);
|
||||
ClassLogFile(std::string _logpath, std::string _logfile);
|
||||
|
||||
void SwitchOnOff(bool _doLogFile);
|
||||
void SetRetention(unsigned short _retentionInDays);
|
||||
|
||||
void WriteToFile(std::string info, bool _time = true);
|
||||
void WriteToDedicatedFile(std::string _fn, std::string info, bool _time = true);
|
||||
void RemoveOld();
|
||||
};
|
||||
|
||||
extern ClassLogFile LogFile;
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
#include <esp_http_server.h>
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
extern httpd_handle_t server;
|
||||
|
||||
httpd_handle_t start_webserver(void);
|
||||
|
||||
@@ -433,6 +433,8 @@ void task_autodoFlow(void *pvParameter)
|
||||
printf("Autoflow: doFLow wird gestartet\n");
|
||||
flowisrunning = true;
|
||||
doflow();
|
||||
printf("Remove older log files\n");
|
||||
LogFile.RemoveOld();
|
||||
}
|
||||
|
||||
LogFile.WriteToFile("task_autodoFlow - round done");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const char* GIT_REV="2ab2f07";
|
||||
const char* GIT_REV="05a0f6f";
|
||||
const char* GIT_TAG="";
|
||||
const char* GIT_BRANCH="master";
|
||||
const char* BUILD_TIME="2020-11-03 22:12";
|
||||
const char* BUILD_TIME="2020-11-06 17:57";
|
||||
@@ -1,4 +1,4 @@
|
||||
const char* GIT_REV="2ab2f07";
|
||||
const char* GIT_REV="05a0f6f";
|
||||
const char* GIT_TAG="";
|
||||
const char* GIT_BRANCH="master";
|
||||
const char* BUILD_TIME="2020-11-03 22:12";
|
||||
const char* BUILD_TIME="2020-11-06 17:57";
|
||||
@@ -51,5 +51,7 @@ Intervall = 4.85
|
||||
|
||||
[Debug]
|
||||
Logfile = False
|
||||
; Number of days before a log file is deleted. 0 = disabled. 10 is default value (if not defined)
|
||||
;LogfileRetentionInDays = 10
|
||||
|
||||
[Ende]
|
||||
@@ -91,7 +91,7 @@ li.dropdown {
|
||||
<a href="javascript:void(0)" class="dropbtn">System</a>
|
||||
<div class="dropdown-content">
|
||||
<a href="#"onclick="document.getElementById('maincontent').src = '/ota_page.html';">OTA Update</a>
|
||||
<a href="#"onclick="document.getElementById('maincontent').src = '/fileserver/log.txt';">Log Viewer</a>
|
||||
<a href="#"onclick="document.getElementById('maincontent').src = '/fileserver/log/message/?readonly=true';">Log Viewer</a>
|
||||
<a href="#"onclick="document.getElementById('maincontent').src = '/reboot_page.html';">Reboot</a>
|
||||
<a href="#"onclick="document.getElementById('maincontent').src = '/info.html';">Info</a>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user