Right logging system must not be overloaded by the log files amount.
So, if the storage is limited - any logging must be looped.
The system log file name is hardcoded, the max file size also.
Actual Arduino's SD-card class can open file only for READ, WRITE or APPEND. No TRUNCATE is possible (i do not prefer to make a custom class from the standard one), so the looping is made by the file deleting and re-creation - please, help to update for better way in the Inline-C code (sub "write_sys_log"): new line is added to the end of text, oldest first file part - is truncated.
	
	
	
	
	
	
	
		
			
			
			
			
			
		
	
	
	
		
	
	
		
	
	
	
	
	
	
	
	
		
			
			
			
			
			
		
	
	
	
		
	
	
		
	
			
			So, if the storage is limited - any logging must be looped.
The system log file name is hardcoded, the max file size also.
Actual Arduino's SD-card class can open file only for READ, WRITE or APPEND. No TRUNCATE is possible (i do not prefer to make a custom class from the standard one), so the looping is made by the file deleting and re-creation - please, help to update for better way in the Inline-C code (sub "write_sys_log"): new line is added to the end of text, oldest first file part - is truncated.
			
				esp_sd module:
			
		
		
		Private Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Type KeyValueType(key() As Byte, value() As Byte)
    Dim Ready_flag As Boolean
    Public HOUR As Byte, DATE As Byte, MONTH As Byte, YEAR As Byte
End Sub
Sub Start_SD(tag As Byte)
    If tag = 0 Then
        Log("Start SD...")
    Else
        Log("Try to re-start SD...")
    End If
    Dim res As Byte = RunNative("setup_sd", Null)
    If res = 0 Then
        Log("SD card - setup error.")
        Ready_flag = False
        Return
    Else
        Ready_flag = True
    End If
 
End Sub
Sub Add_Looped_Log(line() As Byte) As Boolean
    Return RunNative("looped_log", line)
End Sub
#if C
#include "FS.h"
#include "SD.h"
#include "SPI.h"
B4R::Object returnvalue_esp_sp;
bool appendFile(fs::FS &fs, const char *path, const char *message) {
  //Serial.printf("Appending to file: %s\n", path);
    bool res;
  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return false;
  }
  res = file.print(message);
  if (res) {
    //Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.flush();
  file.close();
  return res;
}
B4R::Object* setup_sd(B4R::Object* o){
    bool begun = SD.begin();
    if (!begun) {
        //Serial.println("Card Mount Failed");
        return returnvalue_esp_sp.wrapNumber((byte)0);
    }else{
        return returnvalue_esp_sp.wrapNumber((byte)1);
    }
}
B4R::Object* save_csv_line(B4R::Object* passedvar){
    _keyvaluetype* tmp = (_keyvaluetype*)B4R::Object::toPointer(passedvar); //structure from B4R
 
    B4R::Array* b = tmp->key;
    char* c = (char*)b->data; //file name, do not forget slash "/file.txt"
    //String key = (String)c;
 
    B4R::Array* b2 = tmp->value;
    char* c2 = (char*)b2->data; //test line for saving to file
    //String value = (String)c2;
    bool res = appendFile(SD, c, c2);
    return returnvalue_esp_sp.wrapNumber((byte)res);
}
B4R::Object* freespace_sd(B4R::Object* o){
    float result;
    uint64_t total = SD.totalBytes() / (1024 * 1024);
    //Serial.printf("totalBytes: %llu MB\n", total);
    uint64_t used = SD.usedBytes() / (1024 * 1024);
    //Serial.printf("usedBytes: %llu MB\n", used);
    result = ((float)total - (float)used) / (float)total * 100;
    //Serial.print("Free %: ");
    //Serial.print(used);
 
       return returnvalue_esp_sp.wrapNumber((float)result);
}
B4R::Object* find_file(B4R::Object* o){
    B4R::Array* b = (B4R::Array*)B4R::Object::toPointer(o);
    char* fname = (char*)b->data;
    if (!SD.exists(fname))
        return returnvalue_esp_sp.wrapNumber((byte)0); //non-existent
    else
        return returnvalue_esp_sp.wrapNumber((byte)1);
}
B4R::Object* create_dir(B4R::Object* o){
    B4R::Array* b = (B4R::Array*)B4R::Object::toPointer(o);
    char* fname = (char*)b->data;
    if (!SD.mkdir(fname))
        return returnvalue_esp_sp.wrapNumber((byte)0); //failed
    else
        return returnvalue_esp_sp.wrapNumber((byte)1);
}
bool deleteFile(fs::FS &fs, const char *path) {
  //Serial.printf("Deleting file: %s\n", path);
  bool res = fs.remove(path);
  return res;
}
bool write_sys_log(fs::FS &fs, const char *path, const char *newline) {
  String data;
  File file = fs.open(path);
  if (file) {
    data = file.readString();
    file.close();
  }
 
  int limit = 10000; //max file size
  data = data + (String)newline;
  if (data.length() > limit) data = data.substring(data.length() - limit);
  deleteFile(SD, path);
  return appendFile(SD, path, data.c_str());
}
B4R::Object* looped_log(B4R::Object* o){
    B4R::Array* b = (B4R::Array*)B4R::Object::toPointer(o);
    char* addline = (char*)b->data;
    if (!write_sys_log(SD, "/syslog.txt", addline))
        return returnvalue_esp_sp.wrapNumber((byte)0);
    else
        return returnvalue_esp_sp.wrapNumber((byte)1);
}
#End If
			
				/syslog.txt file:
			
		
		
		2024-08-25 16:52:06: bme280 sensor: unstable data (corrupted I2C_DATA line);
2024-08-25 16:52:09: No reply: ds1307 clock !;
2024-08-25 16:52:09: No reply: ds1307 clock !; bme280 sensor: unstable data (corrupted I2C_DATA line);
2024-08-25 16:52:09: No reply: ds1307 clock !; No reply: bme280 sensor;
2000-01-01 00:00:80: No reply: ds1307 clock !; bme280 sensor: unstable data (corrupted I2C_DATA line);
2000-01-01 00:00:80: No reply: ds1307 clock !; bme280 sensor: unstable data (corrupted I2C_DATA line);
			
				Last edited: 
			
		
	
							 
				 
 
		 
 
		