mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 11:16:34 +00:00
Add file logging
This commit is contained in:
parent
ed21cfd487
commit
3365fd0d0b
@ -332,6 +332,7 @@
|
||||
#define D_CMND_OTAURL "OtaUrl"
|
||||
#define D_CMND_SERIALLOG "SerialLog"
|
||||
#define D_CMND_SYSLOG "SysLog"
|
||||
#define D_CMND_FILELOG "FileLog"
|
||||
#define D_CMND_LOGHOST "LogHost"
|
||||
#define D_CMND_LOGPORT "LogPort"
|
||||
#define D_CMND_IPADDRESS "IPAddress"
|
||||
|
@ -297,6 +297,7 @@ const char WIFI_HOSTNAME[] = WIFI_DEFAULT_HOSTNAME; // Override by user_confi
|
||||
#define TASM_FILE_ZIGBEE_DATA "/zbdata" // Zigbee last known values of devices
|
||||
#define TASM_FILE_AUTOEXEC "/autoexec.bat" // Commands executed after restart
|
||||
#define TASM_FILE_CONFIG "/config.sys" // Settings executed after restart
|
||||
#define TASM_FILE_LOG "/log%d" // Log file
|
||||
|
||||
#ifndef DNS_TIMEOUT
|
||||
#define DNS_TIMEOUT 1000 // Milliseconds
|
||||
|
@ -241,10 +241,7 @@ typedef union {
|
||||
typedef union {
|
||||
uint32_t data; // Allow bit manipulation
|
||||
struct {
|
||||
uint32_t spare00 : 1; // bit 0
|
||||
uint32_t spare01 : 1; // bit 1
|
||||
uint32_t spare02 : 1; // bit 2
|
||||
uint32_t spare03 : 1; // bit 3
|
||||
uint32_t log_file_idx : 4; // bit 0.3 (v14.4.1.2) - FileLog log rotate index
|
||||
uint32_t spare04 : 1; // bit 4
|
||||
uint32_t spare05 : 1; // bit 5
|
||||
uint32_t spare06 : 1; // bit 6
|
||||
@ -696,9 +693,7 @@ typedef struct {
|
||||
uint16_t influxdb_period; // 538 520
|
||||
uint16_t rf_duplicate_time; // 53A 522
|
||||
uint8_t global_sensor_index[3]; // 53C 4C5
|
||||
|
||||
uint8_t free_53F[1]; // 53F
|
||||
|
||||
uint8_t filelog_level; // 53F
|
||||
uint16_t tcp_baudrate; // 540
|
||||
uint16_t button_debounce; // 542
|
||||
uint32_t ipv4_address[5]; // 544
|
||||
|
@ -2649,6 +2649,9 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa
|
||||
|
||||
uint32_t highest_loglevel = Settings->weblog_level;
|
||||
if (Settings->mqttlog_level > highest_loglevel) { highest_loglevel = Settings->mqttlog_level; }
|
||||
#ifdef USE_UFILESYS
|
||||
if (Settings->filelog_level > highest_loglevel) { highest_loglevel = Settings->filelog_level; }
|
||||
#endif // USE_UFILESYS
|
||||
if (TasmotaGlobal.syslog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.syslog_level; }
|
||||
if (TasmotaGlobal.templog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.templog_level; }
|
||||
if (TasmotaGlobal.uptime < 3) { highest_loglevel = LOG_LEVEL_DEBUG_MORE; } // Log all before setup correct log level
|
||||
@ -2697,6 +2700,9 @@ uint32_t HighestLogLevel() {
|
||||
uint32_t highest_loglevel = TasmotaGlobal.seriallog_level;
|
||||
if (Settings->weblog_level > highest_loglevel) { highest_loglevel = Settings->weblog_level; }
|
||||
if (Settings->mqttlog_level > highest_loglevel) { highest_loglevel = Settings->mqttlog_level; }
|
||||
#ifdef USE_UFILESYS
|
||||
if (Settings->filelog_level > highest_loglevel) { highest_loglevel = Settings->filelog_level; }
|
||||
#endif // USE_UFILESYS
|
||||
if (TasmotaGlobal.syslog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.syslog_level; }
|
||||
if (TasmotaGlobal.templog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.templog_level; }
|
||||
if (TasmotaGlobal.uptime < 3) { highest_loglevel = LOG_LEVEL_DEBUG_MORE; } // Log all before setup correct log level
|
||||
|
@ -29,6 +29,9 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
|
||||
D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|"
|
||||
D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOREAD "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|"
|
||||
D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|"
|
||||
#ifdef USE_UFILESYS
|
||||
D_CMND_FILELOG "|"
|
||||
#endif // USE_UFILESYS
|
||||
D_CMND_SERIALBUFFER "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALCONFIG "|" D_CMND_SERIALDELIMITER "|"
|
||||
D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_WIFI "|" D_CMND_DNSTIMEOUT "|"
|
||||
D_CMND_DEVICENAME "|" D_CMND_FN "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|"
|
||||
@ -69,6 +72,9 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
|
||||
&CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution,
|
||||
&CmndModule, &CmndModules, &CmndGpio, &CmndGpioRead, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange,
|
||||
&CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport,
|
||||
#ifdef USE_UFILESYS
|
||||
&CmndFilelog,
|
||||
#endif // USE_UFILESYS
|
||||
&CmndSerialBuffer, &CmndSerialSend, &CmndBaudrate, &CmndSerialConfig, &CmndSerialDelimiter,
|
||||
&CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndWifi, &CmndDnsTimeout,
|
||||
&CmndDevicename, &CmndFriendlyname, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd,
|
||||
@ -922,11 +928,19 @@ void CmndStatus(void)
|
||||
}
|
||||
|
||||
if ((0 == payload) || (3 == payload)) {
|
||||
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_MQTTLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\""
|
||||
D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\""
|
||||
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_MQTTLOG "\":%d,\""
|
||||
#ifdef USE_UFILESYS
|
||||
D_CMND_FILELOG "\":%d,\""
|
||||
#endif // USE_UFILESYS
|
||||
D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\""
|
||||
D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\""
|
||||
D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"),
|
||||
Settings->seriallog_level, Settings->weblog_level, Settings->mqttlog_level, Settings->syslog_level,
|
||||
SettingsText(SET_SYSLOG_HOST), Settings->syslog_port, EscapeJSONString(SettingsText(SET_STASSID1)).c_str(), EscapeJSONString(SettingsText(SET_STASSID2)).c_str(), Settings->tele_period,
|
||||
Settings->seriallog_level, Settings->weblog_level, Settings->mqttlog_level,
|
||||
#ifdef USE_UFILESYS
|
||||
Settings->filelog_level,
|
||||
#endif // USE_UFILESYS
|
||||
Settings->syslog_level, SettingsText(SET_SYSLOG_HOST), Settings->syslog_port,
|
||||
EscapeJSONString(SettingsText(SET_STASSID1)).c_str(), EscapeJSONString(SettingsText(SET_STASSID2)).c_str(), Settings->tele_period,
|
||||
Settings->flag2.data, Settings->flag.data, ToHex_P((unsigned char*)Settings->param, PARAM8_SIZE, stemp2, sizeof(stemp2)),
|
||||
Settings->flag3.data, Settings->flag4.data, Settings->flag5.data, Settings->flag6.data);
|
||||
CmndStatusResponse(3);
|
||||
@ -2147,6 +2161,15 @@ void CmndLogport(void)
|
||||
ResponseCmndNumber(Settings->syslog_port);
|
||||
}
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
void CmndFilelog(void) {
|
||||
if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) {
|
||||
Settings->filelog_level = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(Settings->filelog_level);
|
||||
}
|
||||
#endif // USE_UFILESYS
|
||||
|
||||
void CmndIpAddress(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) {
|
||||
|
@ -1176,6 +1176,9 @@ void PerformEverySecond(void)
|
||||
#ifdef SYSLOG_UPDATE_SECOND
|
||||
SyslogAsync(false);
|
||||
#endif // SYSLOG_UPDATE_SECOND
|
||||
#ifdef USE_UFILESYS
|
||||
FileLoggingAsync(false);
|
||||
#endif // USE_UFILESYS
|
||||
|
||||
ResetGlobalValues();
|
||||
|
||||
@ -1346,6 +1349,9 @@ void Every250mSeconds(void)
|
||||
// Check if log refresh needed in case of fast buffer fill
|
||||
MqttPublishLoggingAsync(true);
|
||||
SyslogAsync(true);
|
||||
#ifdef USE_UFILESYS
|
||||
FileLoggingAsync(true);
|
||||
#endif // USE_UFILESYS
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*\
|
||||
* Every second at 0.25 second interval
|
||||
|
@ -494,6 +494,69 @@ bool TfsRenameFile(const char *fname1, const char *fname2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Log file
|
||||
*
|
||||
* Rotate max 8 x 100kB log files /log1 -> /log2 ... /log8 -> /log1 ...
|
||||
* Keep at least 100kB free on filesystem
|
||||
* Filesystem needs to ba larger than 110kB
|
||||
\*********************************************************************************************/
|
||||
|
||||
void FileLoggingAsync(bool refresh) {
|
||||
static uint32_t index = 1;
|
||||
|
||||
if (!ffs_type || !Settings->filelog_level) { return; }
|
||||
if (refresh && !NeedLogRefresh(Settings->filelog_level, index)) { return; }
|
||||
if (UfsSize() < 110) { return; } // File system too small
|
||||
|
||||
char fname[14];
|
||||
bool file_delete = false;
|
||||
File file;
|
||||
while (1) {
|
||||
snprintf_P(fname, sizeof(fname), PSTR(TASM_FILE_LOG), Settings->mbflag2.log_file_idx +1); // /log1
|
||||
if (file_delete) {
|
||||
ffsp->remove(fname); // Delete previous log file
|
||||
}
|
||||
file = ffsp->open(fname, "a"); // Append
|
||||
if (!file) {
|
||||
file = ffsp->open(fname, "w"); // Make if not exists
|
||||
if (!file) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("FLG: Save failed"));
|
||||
return; // Failed to make file
|
||||
}
|
||||
}
|
||||
if (file.size() > 100000) { // Rotate log file if size over 100k
|
||||
file.close();
|
||||
Settings->mbflag2.log_file_idx++;
|
||||
if ((8 == Settings->mbflag2.log_file_idx) || // Keep max 100k x 8 log files
|
||||
(UfsFree() < 110)) { // Keep free space around 100k
|
||||
Settings->mbflag2.log_file_idx = 0;
|
||||
file_delete = true;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBCAM
|
||||
WcInterrupt(0); // Stop stream if active to fix TG1WDT_SYS_RESET
|
||||
#endif
|
||||
char* line;
|
||||
size_t len;
|
||||
while (GetLog(Settings->filelog_level, &index, &line, &len)) {
|
||||
// This will timeout on ESP32-webcam
|
||||
// But now solved with WcInterrupt(0) in support_esp.ino
|
||||
file.write((uint8_t*)line, len -1);
|
||||
snprintf_P(fname, sizeof(fname), PSTR("\r\n"));
|
||||
file.write((uint8_t*)fname, 2);
|
||||
}
|
||||
#ifdef USE_WEBCAM
|
||||
WcInterrupt(1);
|
||||
#endif
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* File command execute support
|
||||
\*********************************************************************************************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user