ESP32 Save problems in Editor

Here we can discuss about the problem found
Post Reply
User avatar
Electroguard
Posts: 836
Joined: Mon Feb 08, 2021 6:22 pm
Has thanked: 268 times
Been thanked: 317 times

ESP32 Save problems in Editor

Post by Electroguard »

Since using Annex32 WiFi BLE CAN 1.43.5 I have become aware of definite problems when saving a script to SD from the Editor (about 650 lines)
The symptoms are that the Save can be very delayed, or sometimes may not happen at all.
Sometimes the Save pauses a few seconds during the Save progress bar, before continuing on to complete the Save .
But often (perhaps 1 in 10) the Save does not even get as far as the progress bar.
If the Save fails to start within about 20 secs I prepare to reboot by doing 'Select All' (Ctl A) then 'Copy' (Ctl C) before I reboot the device by powering it Off then back On followed by Ctl A and Ctl V to paste the latest contents back into the Editor after reconnecting which reloads the browsers cached copy.

Occasionally, just before rebooting I sometimes notice a very late blue successful Save popup just before actually doing the reboot.
This proves that the interpreter had not locked up completely, but was waiting for some sort of response… presumably from the filing system.

So there is most definitely an inconsistent Save to SD delay problem occurring - which can be brief, long, or indefinite - but the interpreter does not appear to crash, because sometimes it actually recovers and completes the Save successfully.


I suspect it may actually be the same problem with the implementation of the FAT32 filing system which has been causing other file-related problems.
User avatar
cicciocb
Site Admin
Posts: 1900
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 407 times
Been thanked: 1271 times
Contact:

Re: ESP32 Save problems in Editor

Post by cicciocb »

Hi Robin,
I don't know if this problem is specific to this version as I already noticed some delay in the past when using the internal storage (not the SD).
I determined that this could be related to a kind of fragmentation of the internal storage area but I never investigated deeply.

Now, if the problem appears on the SDCARD, except if your SDCARD is almost full (very improbable), I must investigate it.
[Local Link Removed for Guests] wrote: [Local Link Removed for Guests]Fri Sep 10, 2021 12:29 pm I suspect it may actually be the same problem with the implementation of the FAT32 filing system which has been causing other file-related problems.
I don't see what problem you are referring to as the file system have not been changed / modified, and the SDK version is still the same.
However, this could be a regression caused by the addition of the newest functionalities.

By the way, I'm curious to know if this happens also on the previous version.

How can I try to reproduce the problem? Simply saving a file with more than 650 lines ?

Thanks
User avatar
Electroguard
Posts: 836
Joined: Mon Feb 08, 2021 6:22 pm
Has thanked: 268 times
Been thanked: 317 times

Re: ESP32 Save problems in Editor

Post by Electroguard »

Hi CiccioCB,

I had not used TFT's for a very long time, so when I did start re-using them to upgrade the syntax of your gui examples to work on the latest firmware, the first thing I did was upgrade to the latest firmware… so I don't know if the previous version also had the same problem or not.

Although it may only be a coincidence, the reason I posted about this bug now (knowing you are tied up with the website rewrite) was because I thought that the file-related delays sounded suspiciously similar to the "Very Slow FATFS" write on ESP32" [Local Link Removed for Guests] which you had responded to.

So none of this is more important than what you've been doing, but it provides more ammunition for when you are ready.

Screenshot-2c.jpg

The FileManager screen dump is to give an idea of SD card contents, and how much free space is available.
The new 8Gb SD has all your gui demo files, plus all my edited copies of them, plus all required graphics (img & icons),
It also has all my ancient TFT File Menu and Apps, along with relevant graphics and fonts and demos.
So although there are a lot of files, there is nothing out of the ordinary, and they take up less than 1Gb, leaving over 7Gb free.

And below is the menu script I've been working on which has shown up the Editor Save problems.
Some things to point out:
FlexyMenu is an attempt to create a re-usable menu that can dynamically resize to differing TFT screen sizes and orientations.
It also has capability to use either gui touch buttons, or hardware buttons (eg:M5stack), or both (using the gui touch buttons as labels for the hardware buttons).
Because of the gui/hardware schizophrenia, the menu options need to be capable of being button navigated up and down to select a desired option, or alternatively any visible option can be touch-selected using the gui.target instruction, irrespective of the currently highlighted item.
Also it needs to be capable of multiple pagefuls of menu items.

But it kept eluding me, so after many days (weeks) of frustration I was forced to give up on my non-working existing code and start again from scratch in a more diagnostic manner immediately above the old code. This allowed me to run my new test code at the top of the script, while building it up slowly from the non-working remnants below.
So although the total script length is about 650 lines, the actual live script length referenced by the interpreter is only the top 242 lines, with everything below it just being unused junk - which I've included for reproducing the problem scenario as accurately as possible.

This strategy did allow me to pin down a gui.handler bug which had been causing the gui.target selection problems.
It seems that the gui handler uses an array for storing the gui item handles, but the gui handler and gui.target instructions seem to have problems when referencing the gui array... and which can be demonstrated by uncommenting line 97. This adds a gui header item in front of the item line handlers, but the bug causes gui.target to reference the handler array absolutely from 0, rather than relatively plus 1, thereby returning the incorrect gui handler (ie: gui.target returns item 2 when item 3 is touched).

Now that the bug is known I can avoid it - so instead of using a gui.textline for displaying the title (as previously) the title is displayed using tft.print (which also has the benefit of allowing transparent text background).

Another symptom of the gui handler array bug is that every gui item creates a new gui handler, rather than re-using previously used gui handlers.
So it is not possible to eg:
items=10
pagelength=3
dim gui_handler(pagelength)
gui.init pagelength+1
item=1
while item < items
for c = 1 to pagelength
line(c) = gui.textline(10,20 * c, 30, 20, str$(item)
item = item + 1
next c
wend


That was just an example off the top of my head to demonstrate that the gui.handler array does not get re-used, but instead will keep using up another new gui handle until it runs out and starts assigning -1
But these are merely problems I expect you would want to be aware of, not problems you are expected to look into.
The menu script works, and is quite impressive even though needing to side-step some limitations.
What Annex CAN do is far more significant than anything it cannot do.

Anyway, if you want to reproduce the Save problems, try changing the numerous user options at the top of the script, then Saving... eventually it should fail.
The variable tb=1 shows nav buttons (which wrap around between beginning and end), tb=2 shows additional page buttons (don't wrap around), tb=3 show reboot button (for gui emulation of M5stack hardware reboot to different Apps etc) and also a Screen dump gui button (but nothing sensible is displayed from the resulting file in Gimp).
The rows of similar variables allow just about everything to be tailored.
The first row of h_variables is for the top header bar (halign=3 is left align title$, 4=centre, 5=right align)
Second row of m_vars control the menu lines (malign=0 gives full page width menu, 3 is left, 4 centre, 5 right)
mh vars are menu hilite options
f vars are footer showing the 3 standard nav buttons.
p vars are for the page buttons
o vars ar for the other buttons (reboot and screen dump)
I was using a wallpaper most of the time, so you might want to add the filename of an available image somewhere around line 17.

It is still a work in progress, but hopefully it can be helpful in tracking down the Save bug, and perhaps even the gui handler bug, if time permits.

Code: [Local Link Removed for Guests]

'gui handler test
' uses a pagelength array of handlers to re-use the same few lines of gui handlers for displaying multiple pages of items
' but instead of re-using, the handler keeps using up extra reserved gui handlers until it runs out and fails with -1
title$="Menu"    'leave blank for no header 
menu$="one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen,twenty"
'  getfiles "/*"  'causes rebooting

xres=320: yres=240: orientation=1
'xres=240: yres=320: orientation=0
M5stack=2         '0=touch buttons only, 1=M5stack hardware buttons only, 2=both hardware and touch buttons
tb=1              '1=nav only, 2=page also, 3=plua reset & printscreen
black=0: white=tft.rgb(255,255,255): red=tft.rgb(255,0,0): green=tft.rgb(0,255,0): blue=tft.rgb(0,0,255)
cyan=green+blue: pink=red+blue: yellow=tft.rgb(255,255,5): orange=tft.rgb(255,165,0) 
lightgrey=tft.rgb(200,200,200): darkgrey=tft.rgb(128,128,128): clear=-1
background=blue
wallpaper$= ""
'wallpaper$= "/img/handy.bmp"     'optional, leave blank if not needed
'wallpaper$= "/img/babys.bmp"     'optional, leave blank if not needed
wallpaperXoffset=0: if (orientation=1) or (orientation=3) then wallpaperYoffset=0 else wallpaperYoffset=44  'wallpaperYoffset=44

hcol=white: hbak=clear: hbor=hbak: hfont=4: halign=4: hxmargin=0: hymargin=2: hxpadding=20: hypadding=0: hxoffset=0: hyoffset=0  'header specs
mcol=black: mbak=white: mpre=red: mbor=white: mfont=3: malign=4: mxmargin=2: mymargin=0: mxpadding=0: mypadding=0: mxoffset=0: myoffset=0  '  menu specs
mhicol=white: mhibak=darkgrey: mhibor=black: mhipre=red   'menu hilite colours
fcol=white: fbak=blue: fpre=red: fbor=white: ffont=4: falign=4: fxmargin=60: fymargin=4: fxpadding=6: fypadding=0: fxoffset=0: fyoffset=0: frad=5  'footer specs
pcol=white: pbak=blue: ppre=red: pbor=white: pfont=4: palign=4: pxmargin=0: pxpadding=10: pxoffset=0: prad=5  'footer specs
ocol=white: obak=blue: opre=red: obor=white: ofont=3: oalign=4: oxmargin=4: oxpadding=8: oxoffset=-0: orad=5  'footer specs
L$="<": M$="=": R$=">": pL$="<<": pR$=">>": RST$="RST": DMP$="DMP"   'nav button texts 
if M5stack>0 then                    'use hardware buttons
 lpin=39: pin.mode lpin,input,pullup: interrupt lpin,lpress
 mpin=38: pin.mode mpin,input,pullup: interrupt mpin,mpress
 rpin=37: pin.mode rpin,input,pullup: interrupt rpin,rpress
endif
debounce=100
gui_items=30
' no user configuration below this only - all user variables above this line
items=word.count(menu$,",")
dim item$(items)
dim handler(gui_items)
longest=0
for item=1 to items
 item$(item) = word$(menu$,item,",") 'or populate item$ array with whatever you prefer
 if len(item$(item)) > longest then longest=len(item$(item))  'record the longest item length
next item
item=1: pageoffset=0  'each offset is a pagelength page of items
tft.init orientation
'gui.init 30, 0 'background  '********* check max gui lines needed
'onerror skip 
'tft.image wallpaper$,wallpaperXoffset, wallpaperYoffset
'gui.autorefresh 50, 1    
'if (orientation=0) or (orientation=2) then sx=Yres: sy=Xres else sx=Xres: sy=Yres
'gui.init gui_items, background    'reserving more than enough gui handlers to re-use for the page lines
gui.autorefresh 50, 1    
xsf=0: ysf=0
gosub showit
wait


sub getfiles(search$)
menu$=""
f$=file.dir$(search$)
menu$=f$
wlog f$
while f$ <> ""
 f$=file.dir$
 wlog f$ 
 menu$=menu$+","+f$
 pause 15
wend
pause 9000
end sub


showit:
lookup mfont
mb=yres-mymargin: fh=(8*ffont)+(fypadding*2): if M5stack <> 1 then mb=mb-fyoffset-fymargin-fh 
my=mymargin+myoffset
if malign=0 then mw=xres-(mxmargin*2) else mw=(longest+(mxpadding*2))*xsf*mfont
mx=fix((xres)/2) - fix(mw/2)
mh=(ysf*mfont)+mypadding 
gui.init gui_items, background
tft.image wallpaper$,wallpaperXoffset, wallpaperYoffset
header$=title$ 
if header$ > ""
 lookup hfont
 hw=(len(header$)*hfont*xsf)
 if halign=3 then hx=hxmargin
 if halign=4 then hx=fix(xres/2) - fix(hw/2)
 if halign=5 then hx=xres-hxmargin-hw
 hh=(ysf*hfont)+(hypadding*2)
 hy=hymargin+hypadding+hyoffset
 tft.text.font hfont
 tft.text.color hcol,hbak
 tft.text.pos hx,hy
 tft.print header$  
 my=hy+hh+mymargin+myoffset
 
' gui.line(0,my,320,my,yellow)  'if this line is uncommented to add a gui item it makes the gui.target item incorrect

endif
pagelength=cint((mb-my-(mymargin*2))/mh)
lines=pagelength
if (lines+pageoffset) > items then lines = (items-pageoffset)
lookup mfont
for line = 0 to lines-1 
 pos = line+1+(pageoffset*pagelength)
 if items >= pos then  
  line$=item$(pos)
  if malign=3 then mx=mxmargin+mxoffset
  if malign=4 then mx=(fix(xres/2)) - (fix(mw/2))
  if malign=5 then mx=xres-mxmargin-mxpadding-mxoffset-mw
  mh=(ysf*mfont)
  handler(line) = GUI.button(mx,my+(mh*(line)),mw, mh, line$, mfont)
  gui.setevent handler(line),1,selected 
 else
  handler(line) = GUI.button(mx, my+(mh*(line)), mw, mh, string$(longest," "), mfont)
 endif
 if pos=item then Gui.SetColor handler(line),mhicol,mhibak,mhipre,mhibor else Gui.SetColor handler(line),mcol,mbak,mpre,mbor'
next line
if M5stack <> 1 then
 fy=yres-fymargin-fyoffset-fh
 if tb=3 then
  lookup ofont
  ow=(len(rst$)*ofont*xsf)+(fxpadding*2): ox=oxmargin+oxoffset
  rst=GUI.button(ox,fy,ow,fh,rst$,ofont,orad,0,1,ocol,obak,opre,obor): gui.setevent rst,1,Reset
  ow=(len(dmp$)*ofont*xsf)+(fxpadding*2): ox=xres-ow-oxmargin-oxoffset
  dmp=GUI.button(ox,fy,ow,fh,dmp$,ofont,orad,0,1,ocol,obak,opre,obor): gui.setevent dmp,1,ScreenDump 
  pxmargin=oxmargin+ow+oxpadding
 endif
 if tb>1 then
  lookup pfont
  pw=(len(pL$)*pfont*xsf)+(fxpadding*2): px=pxmargin+pxoffset
  plbut=GUI.button(px,fy,pw,fh,pL$,pfont,prad,0,1,pcol,pbak,ppre,pbor): gui.setevent plbut,1,PageLeft
  pw=(len(pR$)*pfont*xsf)+(fxpadding*2): px=xres-pw-pxmargin-pxoffset
  prbut=GUI.button(px,fy,pw,fh,pR$,pfont,prad,0,1,pcol,pbak,ppre,pbor): gui.setevent prbut,1,PageRight 
  fxmargin=pxmargin+pw+pxpadding
 endif
 lookup ffont
 fw=(len(L$)*ffont*xsf)+(fxpadding*2): fx=fxmargin+fxoffset
 lbut=GUI.button(fx,fy,fw,fh,L$,ffont,frad,0,1,fcol,fbak,fpre,fbor): gui.setevent lbut,1,NavLeft
 fw=(len(R$)*ffont*xsf)+(fxpadding*2): fx=xres-fw-fxmargin-fxoffset
 rbut=GUI.button(fx,fy,fw,fh,R$,ffont,frad,0,1,fcol,fbak,fpre,fbor): gui.setevent rbut,1,NavRight 
 fw=(len(M$)*ffont*xsf)+(fxpadding*2): fx=fix(xres/2)-fix(fw/2)
 mbut=GUI.button(fx,fy,fw,fh,M$,ffont,frad,0,1,fcol,fbak,fpre,fbor): gui.setevent mbut,1,NavMid  
endif
wlog "ramfree="+str$(ramfree)
pause debounce
return

sub lookup(font) 'the following scale factors work for me, but can be changed to suit if preferred
Select case font
case 1: xsf=6.6: ysf=8
case 2: xsf=3.7: ysf=8
case 3: xsf=4.0: ysf=8
case 4: xsf=3.5: ysf=8
case 5: xsf=3.7: ysf=8
case else:  xsf=6: ysf=8
end select
end sub

PageLeft:
item=item-pagelength: dec pageoffset 
if item < 1 then item=1: pageoffset=0
if pageoffset < 0 then pageoffset=0  
gosub showit
return

PageRight:
item=item+pagelength
if item > items then item = items 
pageoffset=fix(item/pagelength)
gosub showit
return

Reset:
wlog "Rebooting"
pause 3000
reboot
gosub showit
return

ScreenDump:
wlog "Save screen to file"
tft.save "/dumpfile.dat"
pause 3000
gosub showit
return

NavLeft:
dec item
if item < 1 then item = items: pageoffset=fix(item/pagelength)
if (item mod pagelength) = 0 then dec pageoffset 
gosub showit
return

NavRight:
inc item
if item > items then item = 1: pageoffset=0
if (item mod pagelength) > 0 then pageoffset=fix(item/pagelength)
gosub showit
return

NavMid:
gui.init 5,yellow
wlog "selected="+item$(item)
'do soething with the selected item$(item)
line$=" "+item$(item)+" "
sfont=5: lookup sfont
sw=(len(line$)*sfont*xsf)
sx=fix(xres/2)-fix(sw/2)
sh=(8*sfont)
sy=fix(yres/2)-fix(sh/2)
sel=GUI.button(sx,sy,sw,sh,line$,sfont,0,1,1,yellow,black,red,magenta)
pause 3000
gosub showit
return

selected:
gui.init 5,red
wlog "target="+str$(gui.target)
item = gui.target+1+(pageoffset*pagelength)
wlog "selected="+item$(item)
'do soething with the selected item$(item)
line$=" "+item$(item)+" "
sfont=5: lookup sfont
sw=(len(line$)*sfont*xsf)
sx=fix(xres/2)-fix(sw/2)
sh=(8*sfont)
sy=fix(yres/2)-fix(sh/2)
sel=GUI.button(sx,sy,sw,sh,line$,sfont,0,1,1,yellow,black,red)
pause 3000
gosub showit
return

sub inc(it)
it=it+1
end sub

sub dec(it)
it=it-1
end sub

END '------------------  END  -------------------




'touch.calib: reboot         'uncomment to run once and re-calibrate after changing screen orientation          
M5stack=2                    '0 for touch buttons only, 1 for M5stack hardware buttons only, 2 for both
Xres=320: Yres=240           'TFT screen size
'Xres=480: Yres=320          'TFT screen size for 4"
orientation=1                '0=Portrait, 1=Landscape, 2=Portrait reversed, 3=Landscape reversed
'pre-define some useful colours
black=0: white=tft.rgb(255,255,255): red=tft.rgb(255,0,0): green=tft.rgb(0,255,0): blue=tft.rgb(0,0,255)
cyan=green+blue: pink=red+blue: orange=tft.rgb(255,165,0): yellow=tft.rgb(255,255,5) 
lightgrey=tft.rgb(200,200,200): darkgrey=tft.rgb(128,128,128): clear=-1
background=black: buttoncolour=black: buttonbackground=lightgrey: buttontouched=darkgrey
background=blue '*****************
wallpaper$= "/img/handy.bmp"     'optional, leave blank if not needed
'wallpaper$= "/img/babys.bmp"     'optional, leave blank if not needed
wallpaperXoffset=0: if (orientation=1) or (orientation=3) then wallpaperYoffset=0 else wallpaperYoffset=44  'wallpaperYoffset=44

title$=""        'leave blank to omit top headet
title$=" Flexy Menu "        'leave blank to omit top headet
titleFont=4
titleAlign=3                 '3 for left, 4 for middle, 5 for right
titleColour=yellow
titleBackground=blue
titleBorder=white
titleXmargin=0
titleYmargin=0
titleXpadding=0 
titleYpadding=3 
titleYoffset=0 

buttonFont=3
LeftTouch$="<"
MidTouch$="OK"
RightTouch$=">"
buttonColour=blue'black
buttonBackground=lightgrey
buttonTouched=red
buttonborder=black
buttonRadius=6
buttonXmargin=10
buttonYmargin=1
buttonXpadding=16
buttonYpadding=2

windowBackground=clear           'can be clear or -1 for transparent, or any valid solid colour 
'windowBackground=0 'darkgrey           'can be clear or -1 for transparent, or any valid solid colour 
windowFrame=blue
windowXmargin=0
windowYmargin=0
windowXpadding=0
windowYpadding=0
windowYoffset=0

menu$="one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen"
menuFont=4
menuAlign=0      '0=full width-margins, 1=fit longest item
menuColour=cyan
menuBackground=blue
menuHiliteText=blue
menuHiliteBack=white
menuPressed=red
menuBorder=menuBackground
menuRadius=0
menuSelect=red
menuXmargin=2
menuYmargin=0
menuXpadding=2
menuYpadding=0
menuYoffset=1
stats=3           '0none, 1=pages,2=items, 3=pages+items, 4=items+pages, 5=clear line, 6 test numbers, 6 user info 
statAlign=4      '0=top left, 1=top middle, 2=top right, 3=mid left, 4=mid middle, 5=mid right
statFont=3
statColour=blue
statBackground=clear
statBorder=statBackground
statwindow=clear
statXmargin=1
statYmargin=2
statXpadding=0
statYpadding=0
'statAlign=4
'------ script start -------

tft.init orientation
gui.init 30, background  '********* check max gui lines needed
'onerror skip 
tft.image wallpaper$,wallpaperXoffset, wallpaperYoffset
gui.autorefresh 50, 1    
if (orientation=0) or (orientation=2) then sx=Yres: sy=Xres else sx=Xres: sy=Yres
xcentre=fix((sx/2)-1): ycentre=fix((sy/2)-1): 'screen centre coordinates
ww=sx-(windowXmargin*2)   'window width
wx=sx-ww-windowXmargin    'window horizontal origin
wh=sy-(windowYmargin*2)   'window height
wy=sy-wh-windowYmargin    'initial window vertical origin (will change if gui items added)       
    windowBackground=clear
    if windowBackground=clear then window=gui.rect(wx,wy,ww,wh,windowFrame) else window=gui.box(wx,wy,ww,wh,windowBackground,windowFrame) 
sf=0                      'scale factor to adjust width of different fonts from sub lookup
debounce=100
line=0: lines=0: pos=1: offset=0
items=word.count(menu$,",")
dim item$(items)
'dim handler(items)
longest=0
for c=1 to items
 item$(c) = word$(menu$,c,",")
 if len(item$(c)) > longest then longest=len(item$(c))
next c
pagelength=0: line=0: page=0: pages=0
wlog "longest="+str$(longest)
wlog "ramfree="+str$(ramfree)+"     flashfree="+str$(fix(flashfree/1000000))+"Mb"

if M5stack>0 then                    'use hardware buttons
 lpin=39: pin.mode lpin,input,pullup: interrupt lpin,lpress
 mpin=38: pin.mode mpin,input,pullup: interrupt mpin,mpress
 rpin=37: pin.mode rpin,input,pullup: interrupt rpin,rpress
endif
gosub display

'if menu$>"" then gosub menu
wait


display:
'title$=""
tx=0
if title$>"" then
 lookup titlefont
 tw=(len(title$) * titleFont * sf) + (titleXpadding * 2)
 if titleAlign=3 then tx=titleXmargin
 if titleAlign=4 then tx=xcentre-fix(len(title$)/2 * sf * titlefont) - titleXpadding
 if titleAlign=5 then tx=sx-titleXmargin-tw
 th=(8*titleFont) + (titleYpadding * 2)
 ty=titleYmargin+titleYoffset
 title=GUI.Textline(tx, ty, tw, th, title$, titleFont, titleColour, titleBackground, titleBorder)  
 gui.setstyle title, 4, titleXpadding
 wy=wy+th
 wh=wh-th
endif
if M5stack<>1 then gosub touchNav  'use touch buttons
if stats>0 then  
 item=1: page=1: pages=2
 select case stats   '0none, 1=pages,2=items, 3=pages+items, 4=items+pages, 5=clear line, 6 test numbers, 6 user info 
 case 1: stat$="Page "+str$(page)+" of "+str$(pages) 'Pages
 case 2: stat$=str$(item)+" of "+str$(items)         'Items
 case 3: stat$=time$                                 'Time
 case 4: stat$=" "                                   'blank
 case 5: stat$="12345"                               'test info
 case else: stat$="enter your own User info here"    'user info
 end select

 lookup statFont
 stat1$="Page "+str$(page)+" of "+str$(pages)         'Pages
 stat2$="Item "+str$(item)+" of "+str$(items)         'Items
  stat1w=(len(stat1$) * sf * statFont) + (statXmargin) 'stats width
  stat2w=(len(stat2$) * sf * statFont) + (statXmargin) 
 if statAlign < 3 then 
  if stat1w > stat2w then statw=stat1w else statw=stat2w
 else 
  statw=stat1w + statXpadding + stat2w
 endif
 stath=(8*statFont)+(statYpadding*2)                     'stats height
 select case statAlign
 case 0: 'wlog "top left"
  staty=ty+statYmargin: by=ty: bh=th
  if titleAlign=3 then statX=tx+tw+statXmargin: bx=tx+tw: bw=sx  else statx=statXmargin: bx=0: bw=sx-tx 
 case 1: 'wlog "top middle"
  staty=ty+statYmargin:  by=ty: bh=th
  if titleAlign=3 then statX=fix(tw+((sx-tw)/2)) - fix(statw/2): bx=tx+tw: bw=sx else statX=fix(tx/2) - fix(statw/2): bx=0: bw=sx-tx
 case 2: 'wlog "top right"
  staty=ty+statYmargin:  by=ty: bh=th
  if titleAlign=3 then statX=sx-statw-(statXmargin*2): bx=tx+tw: bw=sx else statx=tx-statw-(statXmargin*2): bx=0: bw=sx-tx  
 case 3: 'middle left"
  by=ty+th: bh=stath+(statYmargin*2): bx=0: bw=sx
  statx=statXmargin
  staty=ty+th+statYmargin
  wh=wh-stath-statYmargin
  wy=staty+stath+windowYmargin 
 case 4: 'middle middle
  by=ty+th: bh=stath+(statYmargin*2): bx=0: bw=sx
  statX=fix((sx)/2) - fix(statw/2)
  staty=ty+th+statYmargin
  wh=wh-stath-statYmargin
  wy=staty+stath+windowYmargin 
 case 5: 'middle right
  by=ty+th: bh=stath+(statYmargin*2): bx=0: bw=sx
  statX=sx-statw-statXmargin 
  staty=ty+th+statYmargin
  wh=wh-stath-statYmargin
  wy=staty+stath+windowYmargin 
 case 6: 'bottom left
  wh=wh-stath-statYmargin
  by=by-stath-(statYmargin*2): bh=stath+(statYmargin*2): bx=0: bw=sx
  statx=statXmargin
  staty=by+statYmargin 
 case 7: 'bottom middle
  wh=wh-stath-statYmargin
  by=by-stath-(statYmargin*2): bh=stath+(statYmargin*2): bx=0: bw=sx
  statX=fix((sx)/2) - fix(statw/2)
  staty=by+statYmargin
 case 8: 'bottom right
  wh=wh-stath-statYmargin
  by=by-stath-(statYmargin*2): bh=stath+(statYmargin*2): bx=0: bw=sx
  statX=sx-statw-statXmargin 
  staty=by+statYmargin
 case else
 end select
 
'statwindow=green
 if statwindow>0 then gui.box(bx+1,by,bw-1,bh,statwindow,windowframe) 'fill stat window with statwindow colour
 if statAlign < 3 then 
 statw=(len(stat$) * sf * statFont) + (statXpadding) 
  if stat1$>"" then stat1=GUI.Textline(statx+statxmargin,staty, statw, stath, stat1$, statFont, statColour, statBackground, statBorder,4)  
  if stat2$>"" then stat2=GUI.Textline(statx+statxmargin,staty+stath+statypadding, statw, stath, stat2$, statFont, statColour)', statBackground, statBorder,4)  
 else
  if stat1$>"" then stat1=GUI.Textline(statx+statxmargin,staty, stat1w, stath, stat1$, statFont, statColour, statBackground, statBorder,4)  
  if stat2$>"" then stat2=GUI.Textline(statx+stat1w+statxpadding,staty, stat2w, stath, stat2$, statFont, statColour)', statBackground, statBorder,4)  
 endif
 gui.setcolor stat2,blue,cyan
endif
'  windowBackground=red' darkgrey  '*************************
if windowBackground=clear then window=gui.rect(wx,wy,ww,wh,windowFrame) else window=gui.box(wx,wy,ww,wh,windowBackground,windowFrame) 
if menu$>"" then gosub menu
return

menu:
menufont=3
lookup menuFont
 menuAlign=1
 menuXmargin=4
 menuXpadding=1
' menuBackground=clear
 menuBorder=white
if menuAlign=0 then mw=sx-(menuXmargin*2) else mw=(longest+(menuXpadding*2)) * sf * menuFont
mx=fix((sx)/2) - fix(mw/2)
mh=(8*menuFont) + menuYpadding 
my=wy+1+menuYmargin+menuYoffset
page=1:line=1
pagelength=fix((wh-2-(menuYmargin*2)-menuYpadding) / mh)
dim handler(pagelength)
pos=5
pages=fix(items / pagelength)
if items mod pagelength > 0 then pages=pages+1
'spy "276"
gosub showlist
' stat1$="Page "+str$(page)+" of "+str$(pages)         'Pages
' stat2$="Item "+str$(pos+offset)+" of "+str$(items)         'Items
'gui.settext stat1, stat1$ 
'gui.settext stat2, stat2$ 
return

showlist:
lines = pagelength' else lines=(items mod pagelength)
'wlog lines
if (lines+offset) > items then lines = (items-offset)
for c = 1 to pagelength 
if items > (c + offset) then 
 line$ = string$(menuXpadding," ") + item$(c+offset) + string$(menuXpadding," ")
else 
line$=string$(longest," ")
endif
wlog str$(c)+"," + line$
item=c+offset
handler(c)=GUI.button(mx+menuXpadding, my+(mh*(c-1)),mw-menuXpadding, mh, line$, menuFont, menuRadius, 0, 1, menuColour, menuBackground, menuPressed, white )'menuBorder)  
'GUI.button(mx+menuXpadding, my+(mh*(c-1)),mw-menuXpadding, mh, str$(c), menuFont, menuRadius, 0, 1, menuColour, menuBackground, menuPressed, white )'menuBorder)  
if c=pos then Gui.SetColor handler(c), menuHiliteText, menuHiliteBack, menuPressed', menuHiliteBorder
wlog "handler(c)="+str$(handler(c))
'pause 50
next c
 stat1$="Page "+str$(page)+" of "+str$(pages)         'Pages
 stat2$="Item "+str$(pos+offset)+" of "+str$(items)         'Items
gui.settext stat1, stat1$ 
gui.settext stat2, stat2$ 
spy "showlist"
'line=1
return

clearlist:
for c = 1 to pagelength 'lines 
 line$ = string$(longest," ")
 handler(c)=GUI.button(mx+menuXpadding, my+(mh*(c-1)),mw-menuXpadding, mh, line$, menuFont, menuRadius, 0, 1, menuColour, menuBackground, menuPressed, white )'menuBorder)  
next c
return


sub spy(from$)
wlog "spyig from "+from$
wlog " pos="+str$(pos)+", offset="+str$(offset)+", page="+str$(page)+", pages="+str$(pages)
wlog " line="+str$(line)+", lines="+str$(lines)+", pagelength="+str$(pagelength)+",  items="+str$(items)
end sub

sub lookup(font) 'the following scale factors work for me, but can be changed to suit if preferred
if font=1 then sf=6.5 else if font=2 then sf=3.5 else if font=3 then sf=4.2 else if font=4 then sf=3.5 else sf=3.7
end sub

selected:
selection$ = word$(menu$,(item*page),",")
wlog selection$
return

ok:
   gosub selected             
return

xxxxleft:
' Gui.SetColor handler(line), menuColour, menuBackground, menuPressed, menuBorder
 pos = pos-1
   if pos<1 then pos=lines: offset=offset-1
   if offset<0 then pos=lines: offset=items-lines: gosub clearlist
  gosub showlist
spy " left after"
' Gui.SetColor handler(line), menuHiliteText, menuHiliteBack, menuPressed', menuHiliteBorder
'   gosub display
return

right:
wlog line
' Gui.SetColor handler(line), menuColour, menuBackground, menuPressed, menuBorder
   pos = pos + 1
   if pos > items then pos = 1: offset = 0
   if pos > lines then offset = offset+lines: pos = 1 ': gosub clearlist 'lines
   if offset+lines > items then offset = 0: pos=1: gosub clearlist
    gosub showlist
'    line=1
'   endif 
spy "right"
' Gui.SetColor handler(line), menuHiliteText, menuHiliteBack, menuPressed', menuHiliteBorder
'   gosub display
return


touchNav:
if (orientation=0) or (orientation=2) then buttonXmargin=buttonXmargin+18 else buttonXmargin=buttonXmargin+40 
lookup buttonFont
'=1 then sf=6.5 else if buttonFont=2 then sf=3.5 else if buttonFont=3 then sf=4.3 else if buttonFont=4 then sf=3.5 else sf=3.7
 bw=(len(MidTouch$) * sf * buttonFont) + (buttonXpadding * 2)
 bx=Xcentre-fix(bw/2)
 bh=(8*buttonFont) + (buttonYpadding * 2)
 wh=wh-bh-buttonYpadding
 by=sy-bh-buttonYmargin 
 mbut=GUI.button(bx,by,bw,bh,MidTouch$,buttonFont,buttonRadius) 
 gui.setcolor mbut, buttoncolour, buttonbackground, buttontouched, buttonborder

 bw=(len(LeftTouch$) * sf * buttonFont) + (buttonXpadding * 2)
 bx=buttonXmargin
 lbut=GUI.button(bx,by,bw,bh,LeftTouch$,buttonFont,buttonRadius)  
 gui.setcolor lbut, buttoncolour, buttonbackground, buttontouched, buttonborder

 bw=(len(RightTouch$) * sf * buttonFont) + (buttonXpadding * 2)
 bx=sx-buttonXmargin-bw
 rbut=GUI.button(bx,by,bw,bh,RightTouch$,buttonFont,buttonRadius)  
 gui.setcolor rbut, buttoncolour, buttonbackground, buttontouched, buttonborder

 gui.setevent mbut,1,mtouch  'where to jump when middle button touched 
 gui.setevent lbut,1,ltouch  'where to jump when left   button touched 
 gui.setevent rbut,1,rtouch  'where to jump when right  button touched 
return


mtouch:
gui.setcolor title, white, red     'changes title bar colours just to show some touch activity 
gosub ok
pause debounce
return

ltouch:
gui.setcolor title, black, green   'changes title bar colours just to show some touch activity 
gosub left
pause debounce
return

rtouch:
gui.setcolor title, black, yellow  'changes title bar colours just to show some touch activity 
gosub right
pause debounce
return


mpress:
if (pin(mpin)=0) then gui.setcolor title, black, orange  'changes title colour to show button pressed
gosub ok
pause debounce
return

lpress:
if (pin(lpin)=0) then gui.setcolor title, black, cyan   'changes title colour to show button pressed
gosub left
pause debounce
return

rpress:
if (pin(rpin)=0) then gui.setcolor title, black, pink   'changes title colour to show button pressed
gosub right
pause debounce
return

end '------ End -------
You do not have the required permissions to view the files attached to this post.
User avatar
Electroguard
Posts: 836
Joined: Mon Feb 08, 2021 6:22 pm
Has thanked: 268 times
Been thanked: 317 times

Re: ESP32 Save problems in Editor

Post by Electroguard »

I've been sick as a dog since the original post, so have not done anything.
But is not a problem for me to test future menu development using an earlier firmware, so what previous version do you want me to test with... would Annex32 1.43.3 CAN BLE be ok ? or do you want earlier ?

BTW, the problem seemed more noticeable when doing small quick parameter changes - which may have amplified the situation because the script had not halted on error, and I was too impatient to click Stop before Saving small variable changes. And although I can't be sure in hindsight, but I think I noticed delayed writes to the wlog window even after the script had been Stopped.

So to avoid bottlenecks, and give Annex the best chance of coping with the complex script, I changed my programming habits to click Stop, Clear Ram and clear the wlog window before Saving and Running any edits.

I must have thought it beneficial to give Annex that extra time to catch its breath, else I probably wouldn't have persevered doing it... which might be significant, because it could suggest the problem may not actually be file-related.
User avatar
cicciocb
Site Admin
Posts: 1900
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 407 times
Been thanked: 1271 times
Contact:

Re: ESP32 Save problems in Editor

Post by cicciocb »

Hi Robin,
sorry but I'm doing other stuff actually so cannot deeply investigate.
So far I cannot easily reproduce the problem, such it seems the case for you.
I'll continue to test
User avatar
cicciocb
Site Admin
Posts: 1900
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 407 times
Been thanked: 1271 times
Contact:

Re: ESP32 Save problems in Editor

Post by cicciocb »

HI Robin,
I did some tests with the version 1.43.5 with a 16GB SDCARD.

I cannot reproduce the problem .

See this video
User avatar
Electroguard
Posts: 836
Joined: Mon Feb 08, 2021 6:22 pm
Has thanked: 268 times
Been thanked: 317 times

Re: ESP32 Save problems in Editor

Post by Electroguard »

I suspect it is a busy Annex bottleneck delay Francesco (rather than File system), which can take several seconds (or sometimes never) to unravel.

When a script halts on error it is already halted, so there is nothing bottled up to get untangled.
But if the script is still running when (eg:) editing a variable, I suspect the Save causes Annex to queue up the request until after untangling the existing running script, but things may get scrambled.

I've made it happen on a completely different script which also has complex gui.component handling (the gui.handler bug won't be helping).

The obvious short-term answer is try to remember to Stop the script before Saving edits, but I find I am now frequently clicking the Stop button on an already stopped script because there is no obvious indication of whether the script is running or not.

So the addition of a 'script-running' indicator to the Editor might be useful (especially if coupled to a single combined Run/Stop toggle button).

Or perhaps some sort of Editor feedback might be available whereby editing a script could automatically stop the running script before the edits are Saved.
User avatar
cicciocb
Site Admin
Posts: 1900
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 407 times
Been thanked: 1271 times
Contact:

Re: ESP32 Save problems in Editor

Post by cicciocb »

Robin, It is probably a network problems, maybe the module is too far from the router or you have multiple subnets.

It could also be a power supply problem.
User avatar
Electroguard
Posts: 836
Joined: Mon Feb 08, 2021 6:22 pm
Has thanked: 268 times
Been thanked: 317 times

Re: ESP32 Save problems in Editor

Post by Electroguard »

Thanks for the suggestions sir, but my development power supply is rock solid, as is my wifi connection (exactly because it is next to a subnet repeater).

As you know, rather than 'halt-on-error' I prefer seeking my own viable work-arounds to problems, then raise awareness of issues to potential benefit Annex in the future... so if I'm the only person affected it can be forgotten about, but if others experience similar problems then there's already been a 'heads up'.
The queued bottleneck delays are not holding me back, and maybe nobody else will ever be affected - but if it does ever need a fix, then a relatively simple future solution could be a toggle button to Stop or Run the script and which changes colour depending on whether the script is running or not.

I only briefly mentioned the gui.handler array referencing problems because I thought you might already be aware of it (due to the frequent use of gui.init in secondary gui example pages), but if you are not already aware I can raise a specific detailed bug report about it if you wish... else I will keep on tiptoing around the bug and move on, now that I have it pinned down. If not fixed though, the problem will probably affect others after your excellent gui examples are published which will make people want to start using the gui objects more.
User avatar
cicciocb
Site Admin
Posts: 1900
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 407 times
Been thanked: 1271 times
Contact:

Re: ESP32 Save problems in Editor

Post by cicciocb »

Hi Robin,
about the file save delay, I hope that someone else will raise this problem as I cannot reproduce this problem on my configuration.

About the GUI, I still did not analysed your code (not very easy to understand) but I suppose that you are redrawing the objects each time when you want change any attribute.

I fact as soon as the objects are created, you can simply modify one of the parameters (text, color, border, etc) and it will be updated by the GUI when the gui.refresh command is run or automatically with gui.autorefresh.
So, for example, if you want change the text from black to white, you can simply use the command gui.setcolor and run a gui.refresh (or it will be done automatically by gui.autorefresh).

So the logic is :
- 1) create all the objects with the initial parameters
- 2) change any attribute during the execution of the code
- 3) refresh with gui.refresh or automatically with gui.autorefresh

As soon as the page changes, a new gui.init is required and the objects for the new page can be created taking into account that the new page will be drawn only when the command gui.refresh is executed.
Post Reply