Report Bugs Here

Moderator: Mmiscool

User avatar
By Electroguard
#61878 Mmiscool, Esp_Basic can do a lot with just a few lines of code, as shown by the many excellent examples.
But once the script starts growing, there comes a point as more code is added when doing a SAVE starts causing ESP reboots. Once this begins happening, the chances keep increasing that the SAVEd script has been corrupted, and the 'heavier' the script, the more likely that the script will malfunction if it is RUN straight after a rebooted SAVE.

Such problems seem to be significantly reduced by doing a 2nd SAVE before trying to RUN.
Doing a 2nd (non-rebooted) SAVE allows things to keep progressing for a while, but eventually strange unpredictable symptoms can start appearing, typically showing up as incorrectly displayed web components in the browser (see the attached screendumps).
Image

Sometimes the same symptoms persist until doing another 2nd SAVE... suggesting the symptoms were being caused by a corrupted script until it was subsequently overwritten.

Image

But other times, merely doing a browser Back and re-RUN may fix the problems or change the symptoms...

Image

...suggesting the changeable symptoms are caused by something more sinister than script corruption.

Image


Sometimes this 'quantum weirdness' can be bypassed by repeatedly doing subsequent saves, but other times the symptoms persist even after multiple saves - which could be due to a script bug, but by now is likely to be caused by a corrupted Esp_Basic interpreter.

I understand that the size and complexity of my dev projects can show up symptoms which might not otherwise be apparent, and I've dealt with the situation as best I can for a long time. But the progressively worsening problems and inevitable outcome is proving an insurmountable obstruction to making the most of Esp_Basic, and if left unchecked I fear it will be a growing deterrent causing people to avoid attempting very much... which would be a great shame.
So I feel the onus is on me to bring the matter to your attention in case it's something you would wish to know.

It would obviously be very beneficial if Esp_Basic could elegently "End due to insufficient resources" rather than lose control and cause script or interpreter corruption.
So in case it may be useful if an investigation is considered, I have enclosed a script which exhibits all of those unpredictable and illogical symptoms mentioned above. I've been using 1Mb V3 A65 and Firefox because it is better at handling the frequent reboot disconnections. The hacked state of the script contents is not important, it's merely offered to demonstrate the interpreter problems.
There are 3 different functionality flags at the top of the script for enabling 'memguage' (shows ramfree), 'debugmode' (shows a debug message window), 'showtime' (shows elapsed time).
Currently all 3 are commented out so the script has a better chance of initially being SAVEd and RUN ok.
If any 1 feature is enabled by uncommenting it, it can usually be persuaded to work ok on its own by doing a 2nd clean SAVE straight after the inevitable rebooted save.
But if more than 1 feature is enabled at the same time, the script will not RUN for me, but instead will crash and reboot every time. So the difference of enabling more than 1 feature is evidently pushing Esp_Basic over some sort of invisible threshold which is causing it to fall off a cliff.
Is it possible that the invisible 'Safe/Unsafe' threshold might have some tangible value which could be monitored by Esp_Basic for flagging up its own sanity check and error message to prevent it from jumping off the cliff?

Also, weird symptoms of interpreter corruption are a particularly difficult problem to notice if you're busy chasing the usual mixed bag of dev bugs.
So it would be very handy if Esp_Basic could include its own self-diagnosis anti-corruption health-check facility - perhaps each different build might include its own checksum hash, and the interpreter could simply scan memory to create a live checksum for comparison... if not done automatically at start-up, then perhaps on demand from a 'Scan for Corruption' button on the SETUP page?



Code: Select allmemclear
'Un-comment any of the 3 below to show that any of them work ok by themselves, but not enough memory for 2 or more.

'debugmode = "y" 'Un-comment to show debug messages
'memguage = "y"  'Un-comment to show memory usage guage
'showtime = "y"     'Un-comment to show elapsed time

if memguage = "y" then
 max = ramfree()
 min = 1000
 memfree = ramfree()
endif
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 = upper("some") 'Optional way of being addressed by sub groups (ie: PIRs, LIGHTs, etc)
globalname = upper("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
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)
pulsepin = 16  'Optional Pulse timer led showing device is alive
relaypin = 2   '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)
led2pin = 15   'Led2 gpio01
led2off = 1    'Default led2 pin off state (allows configuring led pin for active high or active low operation)
relay2pin = 12 'Set to the required Relay2 control pin
relay2off = 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
if led2off = 1 then io(po,led2pin,1) else io(po,led2pin,0) 'initialise led2 to its off state
if relay2off = 1 then io(po,relay2pin,1) else io(po,relay2pin,0) 'initialise relay2 to its off state
'if ledpin = 1 then gpio1reset()
ondelay = 0
ondurat = 3000
offdelay = 1000
offdurat = 4000
on2delay = 2000
on2durat = 6000
off2delay = 0
off2durat = 5000
usercmds = "MyCommand " 'Add your own user commands here, remember to add a corresponding uppercase named branch
commoncmds = " Toggle Toggle2 Relay Relay2"   'Common commands
systemcmds = " Blinks BlinkIP ? Help ! Ping Debug MemGuage Exit Reboot "   'System commands
vocabulary = usercmds & " " & commoncmds & " " & systemcmds
payload = ""
sentq = ""
qos = 0        'quality of service, number of unacknowledged transmit retries before giving up
qid = 0        'unique id of sentq msgs
ims = ""       'input  message stream - local, serial, serial2, udp
oms = "local"  'output message stream - local, serial, serial2, udp
source = ""    'optional source name or address
target = ""    'list of intended subcribers names, group names, and/or IP addresses
words = 0
start = 0      'used by MultiMode button-pressed timer
stop = 0       'used by MultiMode button-pressed timer
numblinks = 5
etime = ""
days = 0
hours = 0
mins = 0
secs = 0
if serial1 = "y" then serialbranch [SERIAL1MSG]
if serial2 = "y" then serial2branch [SERIAL2MSG]
if udp = "y" then
 udpbegin udpport
 udpbranch [UDPMSG]
endif
interrupt buttonpin, [PRESSED]
[HOME]
cls
html |<!DOCTYPE html>|
html |<h2 style="width:100%;color: blue;text-align:center;margin:auto;display:block;">| & title & |</h2>|
html |<hr>|
if memguage = "y" then
 html |<table style="width:100%;margin:auto;text-align:center;">|
 html | <tr style="top-padding:0px;bottom-padding:0px;">|
 html |  <td style="text-align:left;color: red;">1000 min </td>|
 html |  <td style="color:orange;text-align:center;">avail |
 textbox memfree
 cssid htmlid(), "color:black;text-align:center;"
 html |</td>|
 html |  <td style="text-align:right;color:green;">max | & max & |</td>|
 html | </tr>|
 html |</table>|
 meter memfree, min, max '   ***************  MEMORY  METER  *******************
 cssid htmlid(), "width:100%; height:10px; color:red; background-color:blue;display:block;"
endif
html "<BR>"
html |<table style="font-size: 20px; color:rgb(128,128,128);">|
html |  <tr>|
html |    <td>Localname: </td>|
html |    <td style="color: darkblue;"><b>| & localname & |</b></td>|
html |  </tr>|
html |  <tr>|
html |   <td>Groupname: </td>|
html |  <td style="color: darkviolet;">| & groupname & |</td>|
html |  </tr>|
html |  <tr>|
html |   <td>Globalname: </td>|
html |  <td style="color: orange;">| & globalname & |</td>|
html |  </tr>|
html |  <tr>|
html |   <td>IP address: </td>|
html |  <td style="color: darkgreen;">| & localIP & |</td>|
html |  </tr>|
html |  <tr>|
html |   <td>UDP port: </td>|
html |  <td style="color: darkred;">| & udpport & |</td>|
html |  </tr>|
if showtime = "y" then
 html |  <tr>|
 html |   <td>Elapsed time: </td>|
 html |  <td style="color: grey;">|
 tmp = "width:20px;padding:0px;text-align:right;border:0;font-size:18px;color: grey;"
 textbox days
 cssid htmlid(), tmp
 html |d: |
 textbox hours
 cssid htmlid(), tmp
 html |h: |
 textbox mins
 cssid htmlid(), tmp
 html |m: |
 textbox secs
 cssid htmlid(), tmp
 html |s|
 html |  </td>|
 html |  </tr>|
endif
html |  <tr>|
html |   <td> </td>|
html |  </tr>|
html |</table>|
html |<br><br>|
html |<table style="width:100%;font-size:20px;color:rgb(128,128,128);">|
html | <tr style="top-padding:0px;bottom-padding:0px;">|
html |  <td style="width:200px;text-align:left;">Received Message:  </td>|
html |  <td style="background-color: GhostWhite;color:gray;;width:50%;">|
'payload = "display incoming messages"
textbox payload
tmp = "font-size:20px;background-color:cyan;color:gray;width:100%;text-align:center;padding:6px;border-radius:13px;"
cssid htmlid(), tmp
html |  </td>|
html |  <td style="padding-right:20px;width:200px;text-align:right;cursor:pointer;">  </td>|
html | </tr>|
html | <tr style="top-padding:0px;bottom-padding:0px;">|
html |  <td style="width:200px;text-align:left;">  </td>|
html |  <td style="">  </td>|
html |  <td style="width:200px;text-align:left;height:40px;">  </td>|
html | </tr>|
html | <tr style="top-padding:0px;bottom-padding:0px;">|
html |  <td style="width:200px;text-align:left;">Transmit Message: </td>|
html |  <td style="background-color: white;color:blue;">|
messageout = "Toggle2"
textbox messageout
tmp = "font-size:20px;color:darkblue;width:100%;margin:auto;padding:6px;text-align:center;background-color:GhostWhite;"
cssid htmlid(), tmp
html |  </td>|
html |  <td style="width:200px;padding:6px;text-align:left"> |
oms="Local"
dropdown oms, "Local,Serial1,Serial2,UDP"
cssid htmlid(), "background-color:yellow;padding:2px;"
button "Send", [SEND]
cssid htmlid(), "padding-left:3px;height:27px;"
html |  </td>|
html | </tr>|
html |</table>|
if debugmode == "y" then
 debugmsg = ""       
 html |<table style="width:100%;font-size:20px;color:rgb(128,128,128);position: fixed; bottom: 20;">|
 html | <tr style="top-padding:0px;bottom-padding:0px;">|
 html |  <td style="width:200px;text-align:left;">Debug Message: </td>|
 html |  <td style="">|
 textbox debugmsg
 cssid htmlid(),"font-size:20px;background-color:whitesmoke;color:red;width:100%;height:40px;margin:auto;padding:6px;"
 html |  </td>|
 memfree = ramfree()
 html |  <td style="padding-right:20px;width:200px;text-align:right;">|
 'tmp = "font-size:16px;color:yellow;margin:auto;padding:2px;text-align:center;background-color:red;"
 'textbox memfree
 'cssid htmlid(), tmp
 html |  </td>|
 html | </tr>|
 html |</table>|
endif
html "<BR><BR>"
udpwrite netIP & "255", udpport, "Node " & Localname & " started."
if memguage = "y" then memfree = ramfree()
timer 1000, [PULSE]
wait

[PULSE]
'if io(laststat,pulsepin) = 1 then io(po,ledpin,0) else io(po,ledpin,1)
secs=secs + 1
counter1 = counter1 + 1
if io(laststat,pulsepin) = 1 then
 io(po,pulsepin,0)
else
 io(po,pulsepin,1)
endif
if secs > 59 then
 secs = 0
 mins = mins + 1
endif
if mins > 59 then
 mins = 0
 hours = hours + 1
endif
if hours > 23 then
 hours = 0
 days = days + 1
endif
'etime = days & "days : " & hours & "hours : " & mins & "mins :" & secs & "secs"
'if secs = 10 then debugmsg = etime
if memguage = "y" then memfree = ramfree()
wait

[SEND]
target = ""
qos = 0
payload = messageout
if oms="Local" then
 if instr(payload,"target=") = 0 then payload = trim(payload) & " target=" & localname
 gosub [PARSER]
else
 gosub [PUBLISH]       
endif
if memguage = "y" then memfree = ramfree()
wait
       
[PUBLISH]
'debugmsg = payload & " oms=" & oms
if qos>0 then
 ' retries = qos
 qid = mins + secs
 payload = payload & " " & qid'
 start retries timer
 sentq = payload & "*" & sentq
 debugmsg = "Publish " & sentq
 serialprintln "PUBLISH sentq=" & sentq
endif
if oms="Local" then
 target = localname
 gosub [PARSER]
else
 if oms="Serial1" then
  serialprintln payload
 else
  if oms="Serial2" then
   serial2println payload
  else
   if oms="UDP" then
    udpwrite netIP & "255", udpport, payload
   endif
  endif
 endif
endif
if memguage = "y" then memfree = ramfree()
wait
                   
[SERIAL1MSG]
serialinput payload
if asc(right(payload,1)) <33 then payload = left(payload,len(payload)-1)
ims="serial1"
gosub [PARSER]
if memguage = "y" then memfree = ramfree()
return

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

[UDPMSG]
payload = udpread()
ims="udp"
gosub [PARSER]
if memguage = "y" then memfree = ramfree()
return

[PARSER]
if memguage = "y" then memfree = ramfree()
payload = trim(payload)
if payload = "" then return
if asc(right(payload,1)) < 33 then payload = left(payload,len(payload) - 1
qos = 0
source = ""
target = ""
words = 0
'serialprintln "Before Payload="&payload
do
 words = words + 1
 tmp = word(payload,words)
'    serialprintln "Words count="&words &", Tmp="&tmp   
'    serialprintln "Target="&target&", QOS="&qos&", ims="&ims&", oms="&oms&", source="&source
 if tmp <> "" then
  pos = instr(tmp,"target=")
  if pos > 0 then
   target = word(tmp,2,"=")
'    payload = replace(payload," " & tmp,"")
  endif
  pos = instr(tmp,"qos=")
  if pos > 0 then
   qos = word(tmp,2,"=")
   payload = replace(payload," " & tmp,"")
  endif
  pos = instr(tmp,"qid=")
  if pos > 0 then
   qid = word(tmp,2,"=")
'    payload = replace(payload," " & tmp,"")
  endif
  pos = instr(tmp,"ims=")
  if pos > 0 then
   ims = word(tmp,2,"=")
   payload = replace(payload," " & tmp,"")
  endif
  pos = instr(tmp,"source=")
  if pos > 0 then
   source = word(tmp,2,"=")
   payload = replace(payload," " & tmp,"")
  endif
 else
'    serialprintln "Blank tmp. Words count="&words &", Tmp="&tmp   
  words = words - 1
 endif
loop while tmp <> ""
'    serialprintln "After Payload="&payload
'    serialprintln "Words count="&words &", Tmp="&tmp   
'    serialprintln "Target="&target&", QOS="&qos&", ims="&ims&", oms="&oms&", source="&source
if upper(target)=upper("Local") then target = localname
target = upper(target)
'debugmsg = "Parser payload='"&payload&"', Target='"&target&"', Qos='"&qos&"', ims='"&ims&"', Source='"&source
if instr(target,localname)>0 or instr(target,groupname)>0 or instr(target,globalname)>0 or target=localIP then
 if instr(upper(payload)," ACK") <> 0 then gosub [ACKIN] else gosub [SUBSCRIBE]
else
 debugmsg = "'"&payload & "': Not a target for '" & target &"', Qos='"&qos
endif
if memguage = "y" then memfree = ramfree()
return

[SUBSCRIBE]
debugmsg = "SUBSCRIBE, payload=" & payload
tmp = upper(word(payload,1))
if debugmode = "x" then html "Subscribe 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 == "x" then html tmp & "<BR>"
 if ims="udp" then udpreply tmp
 if ims="serial1" then serialprintln tmp
 if ims="serial2" then serial2println tmp
endif
if memguage = "y" then memfree = ramfree()
return

[ACKOUT]
if ims="udp" then udpreply payload & " ACK"
if ims="serial1" then serialprintln payload & " ACK"
if ims="serial2" then serial2println payload & " ACK"
if memguage = "y" then memfree = ramfree()
return
   
[ACKIN]
'sentq = "" 'dev test xxxxxx
'debugmsg = "ACKIN, payload=" & payload & ", SentQ=" & sentq
'end
words = 0
do
 words = words + 1
 tmp = word(sentq,words,"*")
'    serialprintln "Words count="&words &", Tmp="&tmp   
'    serialprintln "Target="&target&", QOS="&qos&", ims="&ims&", oms="&oms&", source="&source
 if instr(tmp, qid) <> 0 then sentq = replace(sentq,tmp & "*","")
loop while tmp <> ""
serialprintln "ACKOUT sentq=" & sentq
'Target="&target&", QOS="&qos&", ims="&ims&", oms="&oms&", source="&source'clear all vars
debugmsg = "ACKIN: sentq=" & sentq
if memguage = "y" then memfree = ramfree()
return

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

[PING]
[!]
udpreply localname & " " & localIP & " PING acknowledged"
serialprintln localname & " " & localIP & " PING acknowledged"
html localname & " " & localIP & " acknowledged<BR>"
if memguage = "y" then memfree = ramfree()
return

[BLINKS]
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
if memguage = "y" then memfree = ramfree()
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
if memguage = "y" then memfree = ramfree()
return
         
[EXIT]
end

[REBOOT]
reboot

[HELP]
[?]
return

[TOGGLE]
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)
if memguage = "y" then memfree = ramfree()
return

[RELAY]
if upper(word(payload,2)) = "ON" then gosub [RELAYON]
if upper(word(payload,2)) = "OFF" then gosub [RELAYOFF]
if upper(word(payload,2)) = "TOGGLE" then gosub [TOGGLE]
if upper(word(payload,2)) = "CYCLEON" then gosub [CYCLEON]
if upper(word(payload,2)) = "CYCLEOFF" then gosub [CYCLEOFF]
if memguage = "y" then memfree = ramfree()
return

[RELAYON]
if io(laststat,relaypin) <> relayoff then return
if relayoff = 0 then io(po,relaypin,1) else io(po,relaypin,0)
if ledoff = 0 then io(po,ledpin,1) else io(po,ledpin,0)
if memguage = "y" then memfree = ramfree()
return

[RELAYOFF]
if io(laststat,relaypin) = relayoff then return
if relayoff = 0  then io(po,relaypin,0) else io(po,relaypin,1)
if ledoff = 0 then io(po,ledpin,0) else io(po,ledpin,1)
if memguage = "y" then memfree = ramfree()
return

[CYCLEON]
if ondelay <> 0 then delay ondelay
if relayoff = 0 then io(po,relaypin,1) else io(po,relaypin,0)
if ledoff = 0 then io(po,ledpin,1) else io(po,ledpin,0)
if ondurat = 0 then return
delay ondurat
gosub [RELAYOFF]
if memguage = "y" then memfree = ramfree()
return
       
[CYCLEOFF]
if offdelay <> 0 then delay offdelay
if relayoff = 0 then io(po,relaypin,0) else io(po,relaypin,1)
if ledoff = 0 then io(po,ledpin,0) else io(po,ledpin,1)
if offdurat = 0 then goto return
delay offdurat
goto [RELAYON]
if memguage = "y" then memfree = ramfree()
return
       
[RELAY2]
if upper(word(payload,2)) = "ON" then gosub [RELAY2ON]
if upper(word(payload,2)) = "OFF" then gosub [RELAY2OFF]
if upper(word(payload,2)) = "TOGGLE" then gosub [TOGGLE2]
if upper(word(payload,2)) = "CYCLEON" then gosub [CYCLE2ON]
if upper(word(payload,2)) = "CYCLEOFF" then gosub [CYCLE2OFF]
return

[RELAY2ON]
if io(laststat,relay2pin) <> relay2off then return
if relay2off = 0 then io(po,relay2pin,1) else io(po,relay2pin,0)
if led2off = 0 then io(po,led2pin,1) else io(po,led2pin,0)
if memguage = "y" then memfree = ramfree()
return

[RELAY2OFF]
if io(laststat,relay2pin) = relay2off then return
if relay2off = 0  then io(po,relay2pin,0) else io(po,relay2pin,1)
if led2off = 0 then io(po,led2pin,0) else io(po,led2pin,1)
if memguage = "y" then memfree = ramfree()
return

[TOGGLE2]
if io(laststat,led2pin) = 1 then io(po,led2pin,0) else io(po,led2pin,1)
if io(laststat,relay2pin) = 1 then io(po,relay2pin,0) else io(po,relay2pin,1)
if memguage = "y" then memfree = ramfree()
return

[CYCLE2ON]
if on2delay <> 0 then delay on2delay
if relay2off = 0 then io(po,relay2pin,1) else io(po,relay2pin,0)
if led2off = 0 then io(po,led2pin,1) else io(po,led2pin,0)
if on2durat = 0 then return
delay on2durat
gosub [RELAY2OFF]
if memguage = "y" then memfree = ramfree()
return
       
[CYCLE2OFF]
if off2delay <> 0 then delay off2delay
if relay2off = 0 then io(po,relay2pin,0) else io(po,relay2pin,1)
if led2off = 0 then io(po,led2pin,0) else io(po,led2pin,1)
if off2durat = 0 then goto return
delay off2durat
gosub [RELAY2ON]
if memguage = "y" then memfree = ramfree()
return
User avatar
By forlotto
#62062 I likely missed some user variables that you have created but I count 69 so you are possibly over that number anyways this is first.

Your 3 functionality flags could be trimmed to one variable with different values

111 might mean all 3 on
011 last 2 on
001 last one on
101 first and last on
010 middle on
100 first on only
110 first two on

Your if statements could take care of the checking you could use other values to make it easier for your if statements now the flags represent what you define in your if statements using a single variable to cover all 3 variables with a single variable. Just a thought.

Second I would like to point out it is good to leave spaces between "=" and "&" in the past this has caused issues through various builds so I stick to this for syntax.

There are other things in your code that I am not sure of if they are correct as well. I will point them out.

There may be other things like ghost bugs:

- HTML buffer overflow
- Number of gui items
- number of subs without a return
- number of returns IDK don't recall which it was that caused a bug I think it was without a return so it could prevent loops I would assume good safety protocol I guess if so but maybe not needed.
- # of variables
- syntax it is a lot of code to go over and I may have missed a few things.

Not trying to say that it should not work but just personal observations it is likely that it could work but tbh it is one holy moley of a code to read through.

But I made comments the numbers are just trying to count variables. Now I do not know if the limit of variables also includes variables used by basic to function to some degree like pin stats etc... So it is possible that you go way over at some point on variables would have to ask mike on this one.

Code: Select allmemclear
'Un-comment any of the 3 below to show that any of them work ok by themselves, but not enough memory for 2 or more.

67 'debugmode = "y" 'Un-comment to show debug messages
68 'memguage = "y"  'Un-comment to show memory usage guage
 69 'showtime = "y"     'Un-comment to show elapsed time

if memguage = "y" then
 55 max = ramfree()
56  min = 1000
57 memfree = ramfree()
endif
1 localIP = ip()     
2 pos = instrrev(localIP,".")
3 netIP = left(localIP,pos)
4 nodeIP = mid(localIP,pos+1)
5 title = "EasyNet"
6 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
7 groupname = upper("some") 'Optional way of being addressed by sub groups (ie: PIRs, LIGHTs, etc)
globalname = upper("all") 'Optional way of being addressed by large groups or systems (ie: CCTV, HouseAlarm, etc)
8 udpport = 5001     'Dev default, so change to suit, different ports could be used for different separated systems
9 udp = "y"
10 serial1 = "y"
11 serial2 = "y"
12 buttonmode = "MultiMode" 'Quick press (<2s) to toggle led, long press (>2s)to blink ip
13 buttonpin = 0  'Uses gpio00 flashing button by default, change to suit (needs pullup resistor).
14 buttonoff = 1  'Default botton OFF state
15 ledpin = 1     'Uses onboard gpio01 blue led by default, change to suit
16 ledoff = 1     'Default led pin off state (allows configuring led pin for active high or active low operation)
17 pulsepin = 16  'Optional Pulse timer led showing device is alive
18 relaypin = 2   'Set to the required Relay control pin
19 relayoff = 0   'Default relay OFF state - Allows for use of active high or active low relay (or alternative output)
20 led2pin = 15   'Led2 gpio01
21 led2off = 1    'Default led2 pin off state (allows configuring led pin for active high or active low operation)
22 relay2pin = 12 'Set to the required Relay2 control pin
23 relay2off = 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
if led2off = 1 then io(po,led2pin,1) else io(po,led2pin,0) 'initialise led2 to its off state
if relay2off = 1 then io(po,relay2pin,1) else io(po,relay2pin,0) 'initialise relay2 to its off state
'if ledpin = 1 then gpio1reset()
24 ondelay = 0
25 ondurat = 3000
26 offdelay = 1000
27 offdurat = 4000
28 on2delay = 2000
29 on2durat = 6000
30 off2delay = 0
31 off2durat = 5000
32 usercmds = "MyCommand " 'Add your own user commands here, remember to add a corresponding uppercase named branch
33 commoncmds = " Toggle Toggle2 Relay Relay2"   'Common commands
34 systemcmds = " Blinks BlinkIP ? Help ! Ping Debug MemGuage Exit Reboot "   'System commands
35 vocabulary = usercmds & " " & commoncmds & " " & systemcmds
36 payload = ""
37 sentq = ""
38 qos = 0        'quality of service, number of unacknowledged transmit retries before giving up
39 qid = 0        'unique id of sentq msgs
40 ims = ""       'input  message stream - local, serial, serial2, udp
41 oms = "local"  'output message stream - local, serial, serial2, udp
42 source = ""    'optional source name or address
43 target = ""    'list of intended subcribers names, group names, and/or IP addresses
44 words = 0
45 start = 0      'used by MultiMode button-pressed timer
46 stop = 0       'used by MultiMode button-pressed timer
47 numblinks = 5
48 etime = ""
49 days = 0
50 hours = 0
51 mins = 0
52 secs = 0
if serial1 = "y" then serialbranch [SERIAL1MSG]
if serial2 = "y" then serial2branch [SERIAL2MSG]
if udp = "y" then
 udpbegin udpport
 udpbranch [UDPMSG]
endif
interrupt buttonpin, [PRESSED]
[HOME]
cls
html |<!DOCTYPE html>|
html |<h2 style="width:100%;color: blue;text-align:center;margin:auto;display:block;">| & title & |</h2>|
html |<hr>|
if memguage = "y" then
 html |<table style="width:100%;margin:auto;text-align:center;">|
 html | <tr style="top-padding:0px;bottom-padding:0px;">|
 html |  <td style="text-align:left;color: red;">1000 min </td>|
 html |  <td style="color:orange;text-align:center;">avail |
 textbox memfree
 cssid htmlid(), "color:black;text-align:center;"
 html |</td>|
 html |  <td style="text-align:right;color:green;">max | & max & |</td>|
 html | </tr>|
 html |</table>|
 meter memfree, min, max '   ***************  MEMORY  METER  *******************
 cssid htmlid(), "width:100%; height:10px; color:red; background-color:blue;display:block;"
endif
html "<BR>"
html |<table style="font-size: 20px; color:rgb(128,128,128);">|
html |  <tr>|
html |    <td>Localname: </td>|
html |    <td style="color: darkblue;"><b>| & localname & |</b></td>|
html |  </tr>|
html |  <tr>|
html |   <td>Groupname: </td>|
html |  <td style="color: darkviolet;">| & groupname & |</td>|
html |  </tr>|
html |  <tr>|
html |   <td>Globalname: </td>|
html |  <td style="color: orange;">| & globalname & |</td>|
html |  </tr>|
html |  <tr>|
html |   <td>IP address: </td>|
html |  <td style="color: darkgreen;">| & localIP & |</td>|
html |  </tr>|
html |  <tr>|
html |   <td>UDP port: </td>|
html |  <td style="color: darkred;">| & udpport & |</td>|
html |  </tr>|
if showtime = "y" then
 html |  <tr>|
 html |   <td>Elapsed time: </td>|
 html |  <td style="color: grey;">|
 tmp = "width:20px;padding:0px;text-align:right;border:0;font-size:18px;color: grey;"
 textbox days
 cssid htmlid(), tmp
 html |d: |
 textbox hours
 cssid htmlid(), tmp
 html |h: |
 textbox mins
 cssid htmlid(), tmp
 html |m: |
 textbox secs
 cssid htmlid(), tmp
 html |s|
 html |  </td>|
 html |  </tr>|
endif
html |  <tr>|
html |   <td> </td>|
html |  </tr>|
html |</table>|
html |<br><br>|
html |<table style="width:100%;font-size:20px;color:rgb(128,128,128);">|
html | <tr style="top-padding:0px;bottom-padding:0px;">|
html |  <td style="width:200px;text-align:left;">Received Message:  </td>|
html |  <td style="background-color: GhostWhite;color:gray;;width:50%;">|
'payload = "display incoming messages"
textbox payload
tmp = "font-size:20px;background-color:cyan;color:gray;width:100%;text-align:center;padding:6px;border-radius:13px;"
cssid htmlid(), tmp
html |  </td>|
html |  <td style="padding-right:20px;width:200px;text-align:right;cursor:pointer;">  </td>|
html | </tr>|
html | <tr style="top-padding:0px;bottom-padding:0px;">|
html |  <td style="width:200px;text-align:left;">  </td>|
html |  <td style="">  </td>|
html |  <td style="width:200px;text-align:left;height:40px;">  </td>|
html | </tr>|
html | <tr style="top-padding:0px;bottom-padding:0px;">|
html |  <td style="width:200px;text-align:left;">Transmit Message: </td>|
html |  <td style="background-color: white;color:blue;">|
53 messageout = "Toggle2"
textbox messageout
tmp = "font-size:20px;color:darkblue;width:100%;margin:auto;padding:6px;text-align:center;background-color:GhostWhite;"
cssid htmlid(), tmp
html |  </td>|
html |  <td style="width:200px;padding:6px;text-align:left"> |
oms="Local"
dropdown oms, "Local,Serial1,Serial2,UDP"
cssid htmlid(), "background-color:yellow;padding:2px;"
button "Send", [SEND]
cssid htmlid(), "padding-left:3px;height:27px;"
html |  </td>|
html | </tr>|
html |</table>|
if debugmode == "y" then
 54 debugmsg = ""       
 html |<table style="width:100%;font-size:20px;color:rgb(128,128,128);position: fixed; bottom: 20;">|
 html | <tr style="top-padding:0px;bottom-padding:0px;">|
 html |  <td style="width:200px;text-align:left;">Debug Message: </td>|
 html |  <td style="">|
 textbox debugmsg
 cssid htmlid(),"font-size:20px;background-color:whitesmoke;color:red;width:100%;height:40px;margin:auto;padding:6px;"
 html |  </td>|
 memfree = ramfree()
 html |  <td style="padding-right:20px;width:200px;text-align:right;">|
 'tmp = "font-size:16px;color:yellow;margin:auto;padding:2px;text-align:center;background-color:red;"
 'textbox memfree
 'cssid htmlid(), tmp
 html |  </td>|
 html | </tr>|
 html |</table>|
endif
html "<BR><BR>"
udpwrite netIP & "255", udpport, "Node " & Localname & " started."
if memguage = "y" then memfree = ramfree()
timer 1000, [PULSE]
wait

[PULSE]
'if io(laststat,pulsepin) = 1 then io(po,ledpin,0) else io(po,ledpin,1)
secs=secs + 1 <-------------------- MISSING SPACES IN CODE!!!!!!!!!!!!!!!!!!!!!! <------------------------------------------------------------!!!!!!!!!!!!!!!!!
55 counter1 = counter1 + 1
if io(laststat,pulsepin) = 1 then
 io(po,pulsepin,0)
else
 io(po,pulsepin,1)
endif
if secs > 59 then
 secs = 0
 mins = mins + 1
endif
if mins > 59 then
 mins = 0
 hours = hours + 1
endif
if hours > 23 then
 hours = 0
 days = days + 1
endif
'etime = days & "days : " & hours & "hours : " & mins & "mins :" & secs & "secs"
'if secs = 10 then debugmsg = etime
if memguage = "y" then memfree = ramfree()
wait

[SEND]
target = ""
qos = 0
payload = messageout
if oms="Local" then <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
 if instr(payload,"target=") = 0 then payload = trim(payload) & " target=" & localname
 gosub [PARSER]
else
 gosub [PUBLISH]       
endif
if memguage = "y" then memfree = ramfree()
wait
       
[PUBLISH]
'debugmsg = payload & " oms=" & oms
if qos>0 then
 ' retries = qos
 qid = mins + secs
 payload = payload & " " & qid'
 start retries timer ??????????????????????????????????????????????????????????????????????????????????????????????????? is this correct syntax ???????????????????????????????????????????????????
 sentq = payload & "*" & sentq
 debugmsg = "Publish " & sentq
 serialprintln "PUBLISH sentq=" & sentq
endif
if oms="Local" then <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
 target = localname
 gosub [PARSER]
else
 if oms="Serial1" then <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
  serialprintln payload
 else
  if oms="Serial2" then <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
   serial2println payload
  else
   if oms="UDP" then <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
    udpwrite netIP & "255", udpport, payload
   endif
  endif
 endif
endif
if memguage = "y" then memfree = ramfree()
wait
                   
[SERIAL1MSG]
serialinput payload
if asc(right(payload,1)) <33 then payload = left(payload,len(payload)-1)
ims="serial1" <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
gosub [PARSER]
if memguage = "y" then memfree = ramfree()
return

[SERIAL2MSG]
serial2input payload
if asc(right(payload,1)) <33 then payload = left(payload,len(payload)-1)
ims="serial2" <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
gosub [PARSER]
if memguage = "y" then memfree = ramfree()
return

[UDPMSG]
payload = udpread()
ims="udp" <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
gosub [PARSER]
if memguage = "y" then memfree = ramfree()
return

[PARSER]
if memguage = "y" then memfree = ramfree()
payload = trim(payload)
if payload = "" then return
if asc(right(payload,1)) < 33 then payload = left(payload,len(payload) - 1
qos = 0
source = ""
target = ""
words = 0
'serialprintln "Before Payload="&payload
do
 words = words + 1
 tmp = word(payload,words)
'    serialprintln "Words count="&words &", Tmp="&tmp   
'    serialprintln "Target="&target&", QOS="&qos&", ims="&ims&", oms="&oms&", source="&source
 if tmp <> "" then
  pos = instr(tmp,"target=")
  if pos > 0 then
   target = word(tmp,2,"=")
'    payload = replace(payload," " & tmp,"")
  endif
  pos = instr(tmp,"qos=")
  if pos > 0 then
   qos = word(tmp,2,"=")
   payload = replace(payload," " & tmp,"")
  endif
  pos = instr(tmp,"qid=")
  if pos > 0 then
   qid = word(tmp,2,"=")
'    payload = replace(payload," " & tmp,"")
  endif
  pos = instr(tmp,"ims=")
  if pos > 0 then
   ims = word(tmp,2,"=")
   payload = replace(payload," " & tmp,"")
  endif
  pos = instr(tmp,"source=")
  if pos > 0 then
   source = word(tmp,2,"=")
   payload = replace(payload," " & tmp,"")
  endif
 else
'    serialprintln "Blank tmp. Words count="&words &", Tmp="&tmp   <<<<<------------------------------------------------ NO SPACES One set of quotes? "&tmp ??? <<<<<<<----------------------------------------------------------
  words = words - 1
 endif
loop while tmp <> ""
'    serialprintln "After Payload="&payload
'    serialprintln "Words count="&words &", Tmp="&tmp  <<<<<------------------------------------------------ NO SPACES One set of quotes? "&tmp ??? <<<<<<<----------------------------------------------------------
'    serialprintln "Target="&target&", QOS="&qos&", ims="&ims&", oms="&oms&", source="&source <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
if upper(target)=upper("Local") then target = localname <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
target = upper(target)
'debugmsg = "Parser payload='"&payload&"', Target='"&target&"', Qos='"&qos&"', ims='"&ims&"', Source='"&source <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
if instr(target,localname)>0 or instr(target,groupname)>0 or instr(target,globalname)>0 or target=localIP then <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
 if instr(upper(payload)," ACK") <> 0 then gosub [ACKIN] else gosub [SUBSCRIBE]
else
 debugmsg = "'"&payload & "': Not a target for '" & target &"', Qos='"&qos <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
endif
if memguage = "y" then memfree = ramfree()
return

[SUBSCRIBE]
debugmsg = "SUBSCRIBE, payload=" & payload
tmp = upper(word(payload,1))
if debugmode = "x" then html "Subscribe 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 == "x" then html tmp & "<BR>"
 if ims="udp" then udpreply tmp <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
 if ims="serial1" then serialprintln tmp <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
 if ims="serial2" then serial2println tmp <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
endif
if memguage = "y" then memfree = ramfree()
return

[ACKOUT]
if ims="udp" then udpreply payload & " ACK" <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
if ims="serial1" then serialprintln payload & " ACK" <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
if ims="serial2" then serial2println payload & " ACK" <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
if memguage = "y" then memfree = ramfree()
return
   
[ACKIN]
'sentq = "" 'dev test xxxxxx
'debugmsg = "ACKIN, payload=" & payload & ", SentQ=" & sentq
'end
words = 0
do
 words = words + 1
 tmp = word(sentq,words,"*")
'    serialprintln "Words count="&words &", Tmp="&tmp   
'    serialprintln "Target="&target&", QOS="&qos&", ims="&ims&", oms="&oms&", source="&source
 if instr(tmp, qid) <> 0 then sentq = replace(sentq,tmp & "*","")
loop while tmp <> "" ???????????????????????????????????????????????????? Is this correct syntax ????????????????????????????????????????????????????
serialprintln "ACKOUT sentq=" & sentq <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
'Target="&target&", QOS="&qos&", ims="&ims&", oms="&oms&", source="&source'clear all vars <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
debugmsg = "ACKIN: sentq=" & sentq <<<<<------------------------------------------------ NO SPACES <<<<<<<----------------------------------------------------------
if memguage = "y" then memfree = ramfree()
return

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

[PING]
[!] ????????????????????????????????????????????????????????????????????????? Two subs crammed together?
udpreply localname & " " & localIP & " PING acknowledged"
serialprintln localname & " " & localIP & " PING acknowledged"
html localname & " " & localIP & " acknowledged<BR>"
if memguage = "y" then memfree = ramfree()
return

[BLINKS]
58 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))
59 data = ""
delay 200
60 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
if memguage = "y" then memfree = ramfree()
return

[BLINKIP]
oldstate = io(laststat,ledpin) 'remember original state
61 blinkon = 200
62 blinkoff = 400
63 blinkpause = 1000
64 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)
 65 digitchr = mid(localIP,pos,1)
 if digitchr = "." then
  delay blinkgap
 else
  if digitchr = "0" then 66 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
if memguage = "y" then memfree = ramfree()
return
         
[EXIT]
end

[REBOOT]
reboot

[HELP]
[?] ???????????????????????????????????????????????????????????????????????????????????????????????????????? two subs jammed together this causes issues in my experience ???????????????????????????????
return

[TOGGLE]
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)
if memguage = "y" then memfree = ramfree()
return

[RELAY]
if upper(word(payload,2)) = "ON" then gosub [RELAYON] ?????????????????????????? This may be causing new Variables to be created you are already at 69 variables. NOT SURE Just trying to help ???????????????????
if upper(word(payload,2)) = "OFF" then gosub [RELAYOFF]
if upper(word(payload,2)) = "TOGGLE" then gosub [TOGGLE]
if upper(word(payload,2)) = "CYCLEON" then gosub [CYCLEON]
if upper(word(payload,2)) = "CYCLEOFF" then gosub [CYCLEOFF]
if memguage = "y" then memfree = ramfree()
return

[RELAYON]
if io(laststat,relaypin) <> relayoff then return
if relayoff = 0 then io(po,relaypin,1) else io(po,relaypin,0)
if ledoff = 0 then io(po,ledpin,1) else io(po,ledpin,0)
if memguage = "y" then memfree = ramfree()
return

[RELAYOFF]
if io(laststat,relaypin) = relayoff then return
if relayoff = 0  then io(po,relaypin,0) else io(po,relaypin,1)
if ledoff = 0 then io(po,ledpin,0) else io(po,ledpin,1)
if memguage = "y" then memfree = ramfree()
return

[CYCLEON]
if ondelay <> 0 then delay ondelay
if relayoff = 0 then io(po,relaypin,1) else io(po,relaypin,0)
if ledoff = 0 then io(po,ledpin,1) else io(po,ledpin,0)
if ondurat = 0 then return
delay ondurat
gosub [RELAYOFF]
if memguage = "y" then memfree = ramfree()
return
       
[CYCLEOFF]
if offdelay <> 0 then delay offdelay
if relayoff = 0 then io(po,relaypin,0) else io(po,relaypin,1)
if ledoff = 0 then io(po,ledpin,0) else io(po,ledpin,1)
if offdurat = 0 then goto return
delay offdurat
goto [RELAYON]
if memguage = "y" then memfree = ramfree()
return
       
[RELAY2]
if upper(word(payload,2)) = "ON" then gosub [RELAY2ON]
if upper(word(payload,2)) = "OFF" then gosub [RELAY2OFF]
if upper(word(payload,2)) = "TOGGLE" then gosub [TOGGLE2]
if upper(word(payload,2)) = "CYCLEON" then gosub [CYCLE2ON]
if upper(word(payload,2)) = "CYCLEOFF" then gosub [CYCLE2OFF]
return

[RELAY2ON]
if io(laststat,relay2pin) <> relay2off then return
if relay2off = 0 then io(po,relay2pin,1) else io(po,relay2pin,0)
if led2off = 0 then io(po,led2pin,1) else io(po,led2pin,0)
if memguage = "y" then memfree = ramfree()
return

[RELAY2OFF]
if io(laststat,relay2pin) = relay2off then return
if relay2off = 0  then io(po,relay2pin,0) else io(po,relay2pin,1)
if led2off = 0 then io(po,led2pin,0) else io(po,led2pin,1)
if memguage = "y" then memfree = ramfree()
return

[TOGGLE2]
if io(laststat,led2pin) = 1 then io(po,led2pin,0) else io(po,led2pin,1)
if io(laststat,relay2pin) = 1 then io(po,relay2pin,0) else io(po,relay2pin,1)
if memguage = "y" then memfree = ramfree()
return

[CYCLE2ON]
if on2delay <> 0 then delay on2delay
if relay2off = 0 then io(po,relay2pin,1) else io(po,relay2pin,0)
if led2off = 0 then io(po,led2pin,1) else io(po,led2pin,0)
if on2durat = 0 then return
delay on2durat
gosub [RELAY2OFF]
if memguage = "y" then memfree = ramfree()
return
       
[CYCLE2OFF]
if off2delay <> 0 then delay off2delay
if relay2off = 0 then io(po,relay2pin,0) else io(po,relay2pin,1)
if led2off = 0 then io(po,led2pin,0) else io(po,led2pin,1)
if off2durat = 0 then goto return
delay off2durat
gosub [RELAY2ON]
if memguage = "y" then memfree = ramfree()
return



Food for thought
"if great things were not hard everyone would do great things because everyone is capable of great things some are just more persistent at doing great things and failing until they accomplish something great." -forlotto
User avatar
By Electroguard
#62077 Forlotto, the very first word of my post named the person it was intended for, then it went on to explain the reason, clearly stating that the script content was not the issue but it was merely provided as a means of demonstrating some serious esp_basic issues that might otherwise be missed.
Mmiscool... the size and complexity of my dev projects can show up symptoms which might not otherwise be apparent ... so I feel the onus is on me to bring the matter to your attention in case it's something you would wish to know - in case it may be useful if an investigation is considered, I have enclosed a script which exhibits all of those unpredictable and illogical symptoms mentioned above... The hacked state of the script contents is not important, it's merely offered to demonstrate the interpreter problems.

I only stick my neck out nowadays if I think it may be in Esp_Basics best interests, therefore I didn't want to sit idly by watching people abandon Esp_Basic because of instability and unreliability (which I know has already happened). I also already know to expect such unwelcome 'criticism' to be wasted effort, but at least I know I am trying to do my best for Esp_Basic, which is all that really matters.

So the script you needlessly commented on was just an old battle-scarred crippled relic that was abandoned long ago because of accumulated damage caused by interpreter malfunctions and corruptions. The battered script was merely offered to use as already-proven bait for tempting out the hidden interpreter demons that I (and others) know are lurking deep within, in case mmiscool had sufficient interest to want to investigate for himself. Which means your comments were completely off-target and wasted effort - but at least you bothered to comment pal, so thanks for that.

Listen, you've twice given me the impression that you think the vars limit is 70, but when I asked mmiscool to clarify that situation back in Nov, he said Maximum 100 variables (not including arrays)
http://www.esp8266.com/viewtopic.php?f=45&t=12409
He stated...
Variable names, 10 characters
Branch labels, 10 characters
No limit on number of gui items
Maximum 100 variables (not including arrays)
Script length limit, 5000 lines

There's no mention of such crucial info in any of the docs B.T.W., so perhaps PhilTilson may want to include it in his ofline docs.
User avatar
By forlotto
#62205 Indeed just spent some time trying to point out some possibles the better part of a couple of hours trying to pick out some possibilities hrmmmm back in NOV 100var limit oh ok I suppose its possible there is a lot of limits and none of those are documented I requested them to be documented if we dig or if he gets time I guess it could be added.

The Interpreter is a great thing for basic things no issues it seems when things grow larger you run into these types of issues but you do have a lot of variables.

I'll leave you to it I suppose I figured I would try and aid a bit and just point out some possibles for you. But anyways take care EG.