gemu2015 / Sonoff-Tasmota

Tasmota Fork TCS34725,PN532_i2,ccc1101 Moritz support,m5stack 4,7 epaper, hotplug drivers
GNU General Public License v3.0
24 stars 19 forks source link

Rolling log using scripting file system #48

Closed pkkrusty closed 1 year ago

pkkrusty commented 1 year ago

Have you looked for this feature in other issues and in the docs?

Is your feature request related to a problem? Please describe.
Would like to log data to flash space, but need to limit file size to available flash in ESP32 (300KB). Thus need rolling log to add new data and delete oldest data. Data is tab/carriage return delimited.

Describe the solution you'd like
Some help with the code for that. Beyond my abilities at the moment, but maybe needs additional functions? If you could add an example in the scripting docs, I think that would be a very helpful starting point for people to use for their customs logging code.

Describe alternatives you've considered
I could delete the whole file and start over when it gets too big, but that isn't as elegant.

Additional context
Add any other context or screenshots about the feature request here.

(Please, remember to close the issue when the problem has been addressed)

gemu2015 commented 1 year ago

this is not supported by standard file systems and can only be solved by copying to a new file here is a working sample (you need my latest fork since i had to implement read line until LF: fr(str fdr 1), the 1 indicates read entire line until LF, not only until TAB or comma like standard string read)

probably i will create a special cmd later to make this easier.

>D 40
IP=192.168.188.106
;must assure that longest line fits in one string
fdr=0
fdw=0
res=0
cnt=0
str=""

>B

; subroutine write to log
#tolog(str)
fdr=fo("/log.txt" a)
if fdr>=0 {
    ; append new entry from str
    fw(str fdr)
    res=fz(fdr)
    if (res>3000) {
        ; shorten file by 1. entry
        ; seek to beginning of file
        fs(fdr 0)
        ; read first string until LF and throw away
        fr(str fdr 1)
        fdw=fo("/tmp.txt" w)
        for cnt 1 1000 1
            res=fa(fdr)
            if res>0 {
                fr(str fdr 1)
                fw(str+"\n" fdw)
            } else {
                break
            }
        next
        ; close files
        fc(fdr)
        fc(fdw)
        ; delete log
        fd("/log.txt")
        ; rename tmp to log
        frn("/tmp.txt" "/log.txt")
    } else {
        fc(fdr)
    }
}

>S
=#tolog(tstamp+"\n")
pkkrusty commented 1 year ago

Thanks, will try it.

gemu2015 commented 1 year ago

ok, i added a cmd for convenience. (log file write) lfw("/log.txt" str 300)

  1. param = name of log file
  2. param = text for complete line (without linefeed, is automatically added)
  3. max desired file size

keep in mind that because we need to copy the file we have only half of disc space available

gemu2015 commented 1 year ago

i forgot you need compile flag

define USE_SCRIPT_FATFS_EXT

pkkrusty commented 1 year ago

What's the limit for the for...loop in terms of cycling through the file? If I have 8000 lines, for a total of ~300k, (38 bytes per line), will I run into buffer/RAM/speed issues? I'll try it, but you may have some thoughts...

pkkrusty commented 1 year ago

Also need #define USE_SCRIPT_FATFS?

pkkrusty commented 1 year ago

Compiling for ESP32 gives error:

/Users/andrew/Tasmota/Tasmota-12-5-0-1/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino: In function 'int32_t script_logfile_write(char*, char*, uint32_t)':
/Users/andrew/Tasmota/Tasmota-12-5-0-1/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino:5930:17: error: invalid conversion from 'char*' to 'const uint8_t*' {aka 'const unsigned char*'} [-fpermissive]
gemu2015 commented 1 year ago

fixed