Report Bugs Here

Moderator: Mmiscool

User avatar
By Electroguard
#59143 Mmiscool, I know you won't like me telling you this, any more than I like being the one having to tell you, but I think Alpha 64 may have introduced a serious memory problem. I've triple-checked to make sure before 'annoying' you, but have reproduced the same problems 3 times by reverting back to A63 to check things then re-installing A64 and getting the same problems, so it seems more than just coincidence.

There are 2 major symptoms on A64 that I don't get with A63.

1. I had included a memory guage in my script for trying to track down memory leakage problems that I was getting on A63. So it quickly became evident that every time I RUN the A64 script I had less RAMFREE available than the previous time, until eventually there is so little free ram available that the ESP just reboots itself.
This doesn't happen with A63, the memclear instruction causes each re-RUN to start with the same available free ram.

2. But even before able to RUN the script it obviously needs to be SAVED, and whereas on A63 the 'Saved OK' confirmation window only appeared every alternative SAVE as was previously reported, now in A64 it never returns a 'Saved OK' confirmation and it reboots every time - sometimes rebooting itself multiple times on the trot! - so the script never saves or runs correctly.

Perhaps the best way of reproducing my situation is to load the enclosed script on a 4Mb A63 device.
Just SAVE and RUN. If the SAVE causes a reboot the wait till it reconnects and do another SAVE to get the SAVED OK window without the reboot, else the memory is corrupt. RUN the script and note the max available ram to the right of the meter, then browser back and re-run it again to note the same free ram again. If you do that with A64 you will see it reducing every time.

You can check the script stability on A63 by keep sending it a TOGGLE command via serial or udp - the free mem will drop down initially but then stabilise for multiple toggles. Doing the same on A64 will keep eating up free mem till it reboots.

Code: Select allmemclear
max = ramfree()
memfree = ramfree()
'meter memfree, 0, max
'cssid htmlid(), "background-color: yellow; color:red; width: 100%; height:10px;"
localIP = ip()     
pos = instrrev(localIP,".")
netIP = left(localIP,pos)
nodeIP = mid(localIP,pos+1)
title = "EasyNet"
localname = ""     'Populate for clarity, else will be uniquely named "NODE" + last IP address byte
if localname == "" then localname = "Node" & nodeIP
localname = upper(localname)  'Names are deliberately case-insensitive to offer simplest ease of use
groupname = "some" 'Optional way of being addressed by sub groups (ie: PIRs, LIGHTs, etc)
globalname = "all" 'Optional way of being addressed by large groups or systems (ie: CCTV, HouseAlarm, etc)
udpport = "5001"   'Dev default, so change to suit, different ports could be used for different separated systems
'debugmode = "y"
udp = "y"
serial1 = "y"
serial2 = "y"
buttonmode = "MultiMode" 'Quick press (<2s) to toggle led, long press (>2s)to blink ip
buttonpin = 0 'Uses gpio00 flashing button by default, change to suit (needs pullup resistor).
buttonoff = 1 'Default botton OFF state
ledpin = 1    'Uses onboard gpio01 blue led by default, change to suit
ledoff = 1    'Default led pin off state (allows configuring led pin for active high or active low operation)
relaypin = 12   'Set to the required Relay control pin
relayoff = 0 'Default relay OFF state - Allows for use of active high or active low relay (or alternative output)
if ledoff == 1 then io(po,ledpin,1) else io(po,ledpin,0) 'initialise led to its off state
if relayoff == 1 then io(po,relaypin,1) else io(po,relaypin,0) 'initialise relay to its off state
usercmds = "MyCommand " 'Add your own user commands here, remember to add a corresponding uppercase named branch
commoncmds = " Toggle Relay1 Relay2 RelayON RelayOFF "   'Common commands
systemcmds = " Blinks BlinkIP ? Help ! Ping Debug Exit Reboot "   'System commands
vocabulary = usercmds & " " & commoncmds & " " & systemcmds
payload = ""
qos = 0
ims = ""
source = ""
target = ""
words = 0
start = 0     'used by MultiMode button-pressed timer
stop = 0      'used by MultiMode button-pressed timer
numblinks = 5
if serial1 == "y" then serialbranch [SERIAL1MSG]
if serial2 == "y" then serial2branch [SERIAL2MSG]
if udp == "y" then
 udpbegin udpport
 udpbranch [UDPMSG]
endif
interrupt buttonpin, [PRESSED]
html |<h2 style="text-align:center;top-padding:0px;bottom-padding:0px;">|  & title & |</h2>|
'style="color:blue;">'html "<hr>"
meter memfree, 1000, max
cssid htmlid(), "width:100%;"
html |<p style="text-align:right;">Max available memory=| & max & |</p>|
print
html "<BR>"
html "Localname: " & localname & "<BR>"
html "Groupname: " & groupname & "<BR>"
html "Globalname: " & globalname & "<BR>"
html "IP address: " & localIP & "<BR>"
html "UDP port: " & udpport
html "<BR><BR>"
memfree = ramfree()
button "Help", [HELP]
wait

[SERIAL1MSG]
serialinput payload
if asc(right(payload,1)) <33 then payload = left(payload,len(payload)-1)
payload = payload & " ims=serial1"
gosub [PARSER]
return

[SERIAL2MSG]
serial2input payload
if asc(right(payload,1)) <33 then payload = left(payload,len(payload)-1)
payload = payload & " ims=serial2"
gosub [PARSER]
return

[UDPMSG]
payload = udpread()
payload = payload & " ims=udp"
gosub [PARSER]
return

[PARSER]
memfree = ramfree()
'html "."
'print
'return 
if debugmode == "y" and instr(payload,"ims=serial1") > 0 then html "Serial1 Message Received<BR>"
if debugmode == "y" and instr(payload,"ims=serial2") > 0 then html "Serial2 Message Received<BR>"
if debugmode == "y" and instr(payload,"ims=udp") > 0 then html "UDP Message Received<BR>"
if asc(right(payload,1)) < 33 then payload = left(payload,len(payload) - 1
qos = 0
ims = ""
source = ""
target = ""
words = 0
memfree = ramfree()
'html "Parser " & ramfree() & "<BR>"
'return
do 'count payload words after controls have been extracted
 words = words + 1 'count words
 tmp = word(payload,words)
 if tmp <> "" then
  pos = instr(tmp,"target=")
  if pos > 0 then
   target = word(tmp,2,"=")
   'payload = trim(replace(payload," " & tmp,""))
   words = words + 1
  endif
  pos = instr(tmp,"qos=")
  if pos > 0 then
   qos = word(tmp,2,"=")
   'payload = trim(replace(payload," " & tmp,""))
   words = words + 1
  endif
  pos = instr(tmp,"ims=")
  if pos > 0 then
   ims = word(tmp,2,"=")
   'payload = trim(replace(payload, " " & tmp,""))
   words = words + 1
  endif
  pos = instr(tmp,"source=")
  if pos > 0 then
   source = word(tmp,2,"=")
   'payload = trim(replace(payload, " " & tmp,""))
   words = words + 1
  endif
 endif
loop while tmp <> ""

if debugmode == "y" then
 html "payload=" & payload & ", (length=" & len(payload) & "), (words=" & words & ")<br>"
endif
if target == "" then target = localname else target = upper(target)  'Subsribers list
target = upper(target)
if debugmode == "y" then html "source=" & source & "target=" & target & ", qos=" & qos & "ims=" & ims & "<br>"
if instr(target,localname)>0 or instr(target,groupname)>0 or instr(target,globalname)>0 or instr(target,localIP)>0 then
 if instr(upper(payload),"ACK") <> 0 then gosub [ACKIN] else gosub [SUBSCRIBE]
else
 if debugmode == "y" then html "Not a target for payload " & payload & "<br>"
endif
return

[SUBSCRIBE]
tmp = upper(word(payload,1))
if debugmode == "y" then html "command=" & tmp & ", length=" & len(tmp) & "<BR>"
if instr(upper(vocabulary),tmp) > 0 then
 if qos > 0 then gosub [ACKOUT]
 gosub "[" & tmp & "]"
else
 tmp = "ERROR: Command (" & tmp & ") not recognised in Payload (" & payload & ")"
 if debugmode == "y" then html tmp & "<BR>"
 if ims=="udp" then udpreply tmp
 if ims=="serial1" then serialprintln tmp
 if ims=="serial2" then serial2println tmp
endif
return

[ACKIN]
sentq = "tim|blinks 5 qos=2|fred target=local|" 'dev test xxxxxx
payload = replace(payload," ACK","")
sentq = replace(sentq,payload & "|","")
return


[PRESSED]
if io(laststat,buttonpin) == 0 then start = millis() else stop = millis()
if stop > start then
 if stop-start < 2000 then gosub [TOGGLE] else gosub [BLINKIP]
endif
memfree = ramfree()
wait

[TOGGLE]
'html ramfree() & "<BR>"
if io(laststat,ledpin) = 1 then io(po,ledpin,0) else io(po,ledpin,1)
if io(laststat,relaypin) = 1 then io(po,relaypin,0) else io(po,relaypin,1)
return

[PING]
[!]
'if debugmode == "y" then udpreply localname & " PING Declare IP acknowledged "
udpreply localname & " " & localIP & " PING acknowledged"
serialprintln localname & " " & localIP & " PING acknowledged"
html localname & " " & localIP & " acknowledged<BR>"
return

[BLINKS]
'if debugmode == "y" then udpreply localname & " Blinks acknowledged. Params=" & params
let oldstate = io(laststat,ledpin) 'Remember LED state before blinking
io(po,ledpin,ledoff)
if val(word(payload,2)) > 0 and val(word(payload,2)) < 99 then numblinks = val(word(payload,2))
data = ""
delay 200
for count = 1 to numblinks
if ledoff == 0 then io(po,ledpin,1) else io(po,ledpin,0)
delay 600
if ledoff == 0 then io(po,ledpin,0) else io(po,ledpin,1)
delay 400
next count
delay 2000
io(po,ledpin,oldstate)  'Restore LED state to its prior value
return

[BLINKIP]
oldstate = io(laststat,ledpin) 'remember original state
blinkon = 200
blinkoff = 400
blinkpause = 1000
blinkgap = 1400
if ledoff == 0 then io(po,ledpin,0) else io(po,ledpin,1) ' turn led off
delay blinkpause
for pos = 1 to len(localIP)
 digitchr = mid(localIP,pos,1)
 if digitchr == "." then
 delay blinkgap
 else
  if digitchr = "0" then digit = val("10") else digit = val(digitchr)
  for count = 1 to digit
   if ledoff == 0 then io(po,ledpin,1) else io(po,ledpin,0)
   delay blinkon
   if ledoff == 0 then io(po,ledpin,0) else io(po,ledpin,1)
   delay blinkoff
  next count
  delay blinkpause
 end if
next pos
delay blinkgap
io(po,ledpin,oldstate) 'restore to original state
return

[EXIT]
end

[REBOOT]
reboot

[DEBUG]
if upper(word(payload,2)) == "OFF" or upper(word(payload,2)) == "n" then debugmode = "n"
if upper(word(payload,2)) == "ON" or upper(word(payload,2)) == "y" then debugmode = "y"
return

[HELP]
[?]
tmp = "Syntax: COMMAND  [params] [options]"
'if ims="" or debugmode == "y" then html "<br>" & tmp & "<br>"
if ims="" then html "<br>" & tmp & "<br>"
if ims="serial1" then serialprintln tmp
if ims="serial2" then serial2println tmp
if ims="udp" then udpreply tmp
tmp = "User commands: "
if usercmds == "" then tmp = tmp & " (no user commands defined)" else tmp = tmp & usercmds
if ims="" or debugmode == "y" then html tmp & "<br>"
if ims="serial1" then serialprintln tmp
if ims="serial2" then serial2println tmp
if ims="udp" then udpreply tmp
tmp = "Common commands: " & commoncmds
if ims="" or debugmode == "y" then html tmp & "<br>"
if ims="serial1" then serialprintln tmp
if ims="serial2" then serial2println tmp
if ims="udp" then udpreply tmp
tmp = "System commands: " & systemcmds
if ims="" or debugmode == "y" then html tmp & "<br>"
if ims="serial1" then serialprintln tmp
if ims="serial2" then serial2println tmp
if ims="udp" then udpreply tmp
tmp = "Params: " & "command dependent - eg: On, Off, Y, N, temp_value etc"
if ims="" or debugmode == "y" then html tmp & "<br>"
if ims="serial1" then serialprintln tmp
if ims="serial2" then serial2println tmp
if ims="udp" then udpreply tmp
tmp = "Options: "
tmp = tmp & " target=(subscribers list), qos=(number of unacknowledged transmit retries)"
if ims="" or debugmode == "y" then html tmp & "<br>"
if ims="serial1" then serialprintln tmp
if ims="serial2" then serial2println tmp
if ims="udp" then udpreply tmp
tmp = "Automatic System Options: "
tmp = tmp & " ims=(input msg stream), ACK (subscriber QoS>0 received msg acknowledgement)"
if ims="" or debugmode == "y" then html tmp & "<br>"
if ims="serial1" then serialprintln tmp
if ims="serial2" then serial2println tmp
if ims="udp" then udpreply tmp
if ims <> "" then return
memfree = ramfree()
wait
User avatar
By trackerj
#59158 Thanks Mmiscool, much better, A64 was almost unusable. Still some erros when saving (see below) but at least is not rebooting every time "Save" button is pressed:

Code: Select allError at line 0:
Error at line 0: Halted
start save
Error at line 0:
Error at line 0: Halted
/MPRSx8.bas/31
/MPRSx8.bas/86
/MPRSx8.bas/98
end of save!!
Error at line 0:
Error at line 0: Halted
User avatar
By Electroguard
#59159 Yes, as TrackerJ says, A65 is now usable again.

TJ, I've found with the 'every alternative save' situation that if RUNning after a rebooted save you can expect all sorts of problems. You need to do a second save straight after the rebooted one to get the Saved OK window without a reboot in between.
I think the line 0 errors probably occur anyway if it is not autorun, but I haven't tried proving it yet.