- Fri Oct 14, 2016 8:03 am
#56511
Variables in esp basic come in to existence when a value is assigned to it.
No, that is what
should happen, but I am pointing out a bug which brings new unwanted variables into existence without assigning any value to them. The following snippet should help illustrate the problem...
Code: Select allmemclear
print "OK" 'prints the specified quoted text
print BUG 'this is not specified text, nor is it a declared variable with assigned contents, it is a bug!
BUG = BUG 'the bug created an error variable without any assigned data, and populated it with its own confused name
print BUG 'this is now an unwanted bug variable with unwanted and unspecified contents
emptyvar = "" 'This is correct, it creates an empty variable by asigning it nul contents
print emptyvar 'prints empty contents
emptyvar = emptyvar 'still empty, does not confuse contents with the var name
print emptyvar 'prints empty contents again to prove no confusion with var name
emptyvar = 12345 'assign numeric value to empty variable
print emptyvar 'correctly prints contents of the variable
It is not always possible or practical to pre-assign values to all variables - not all optional variable will necessarilly be required, and perhaps not even initially known.
I am starting a re-write of EasyNet for V3. The aim is for a generic network node script which is configurable for a multitude of different purposes even though the main script with all the network framework remains the same and is common for all. The main difference in the huge personality changes between a PIR sensor, an Infra-red Receiver or Transmitter node, a Mains Monitor Receiver and Transmitter etc, is achieved by selecting different uses for the gpio00 input button, and different uses for the optional relay outputs.
The gpio00 button is configurable from a dropdown list, ie: dropdown "MultiMode,BlinkFullIP,BlinkShortIP,ToggleButton,FlipSwitch,Sensor,Monitor,IR", buttonmode.
All those different possible uses require their own sets of parameters which are only relevent when used in the chosen users configuration. The sets of parameters for unused options should remain undefined.
The program also needs to cater for the possibility of 1 relay as with the Sonoff, or 2 relays as with an ElectroDragon, or even possibly 4 or 8 if used with an SPI or I2C multi-IO expansion module.
But each relay potentially requires a set of parameters, ie:
relaypin=12, relaylogic=0, relaystartup=off, relayondelay=0, relayoffdelay=0, relayonduration=9, relayoffduration=0.
It would be completely impractical to pre-define all those sets of parameters for 8 different relays on the off-chance that they may occasionally be required, when the chances are that no relays may be used by a lot of people a lot of the time.
So it makes sense to create a script which has just a few essential pre-defined example variables specified at the top of the script, which then automatically declares any others which are need for that configuration and assigns them defaults, which may be overwritten by any available saved variables if read back in from flash memory. Any new user edits would be saved to flash and subsequently overwrite all pre-defined defaults each time. This would avoid all variables needing to be explicitely pre-declared even if empty, and unnecessarilly and wastefully saved to flash every time... only non-defaults need be saved.
That could be easily achieved if the undeclared variables bug didn't keep mistakingly creating unwanted variables with unwanted contents when tested for empty using if var == "".
But until that is fixed, it will require explicitely pre-defining all required variables, which in practice will probably mean doing individual tailored scripts for each required configuration by ripping out all references to all optional variables which are not used by that specific configuration, but which cannot be tested for.
Just to give a better idea of the scale of things, I've included the snippet below, which doesn't include all required variables, but shows what I was working my way through until coming up against the undeclared variables bug problem, which prevented me from subsequently declaring numeric variables after testing a non-existing var name for empty.
I fleetingly considered avoiding all numeric variables and using all text conversions instead... but I'm not masochistic enough.
Code: Select all[INIT]
localIP = ip()
gosub [IPSPLIT]
if opmode == "" or opmode == "opmode" then opmode = "Node"
if localname == "" or localname == "localname" then localname = opmode & nodeIP
if groupname == "" or groupname == "groupname" then groupname = opmode
if globalname == "" or globalname == "globalname" then globalname = "ALL"
if udpport == "" or udpport == "udpport" then udpport = 5001
if description == "description" then description = ""
if debugmode == "" or debugmode == "debugmode" then debugmode = "normal"
if buttonmode == "" or buttonmode == "buttonmode" then buttonmode = "MultiMode"
if voicemode == "On" then gosub [VOICEINIT]
'if voicemode == "" then voicemode = "Off"
'if userpage == "" then userpage = "Normal"
if relaylogic == "" or relaylogic == "relaylogic" then relaylogic = 1
'if relaylogic == "" or relaylogic == "relaylogic" then relaylogic = 1
if startmode == "" or startmode == "startmode" then startmode = "Off"
if startmode == "On" then
if relaylogic == 0 then io(po,relaypin,1) else io(po,relaypin,0)
if ledlogic == 0 then io(po,ledpin,1) else io(po,ledpin,0)
else
if relaylogic == 0 then io(po,relaypin,0) else io(po,relaypin,1)
if ledlogic == 0 then io(po,ledpin,0) else io(po,ledpin,1)
endif
interrupt buttonpin, [PRESSED]
return
[READVARS]
tmp = read("Title")
if tmp <> "" then title = tmp
tmp = read("Name")
if tmp <> "" then localname = tmp
tmp = read("Global")
if tmp <> "" then globalname = tmp
tmp = read("Group")
if tmp <> "" then groupname = tmp
tmp = read("Description")
if tmp <> "" then description = tmp
tmp = read("Opmode")
if tmp <> "" then opmode = tmp
tmp = read("Debugmode")
if tmp <> "" then debugmode = tmp
tmp = read("Buttonmode")
if tmp <> "" then buttonmode = tmp
tmp = read("Voicemode")
if tmp <> "" then voicemode = tmp
tmp = read("UDPport")
if tmp <> "" then udpport = val(tmp)
tmp = read("Ondelay")
if tmp <> "" then ondelay = val(tmp)
tmp = read("Offdelay")
if tmp <> "" then offdelay = val(tmp)
tmp = read("Onduration")
if tmp <> "" then onduration = val(tmp)
tmp = read("Offduration")
if tmp <> "" then offduration = val(tmp)
tmp = read("Blinks")
if tmp <> "" then numblinks = val(tmp)
return
[SAVEVARS]
if debugmode <> "silent" then udpreply localname & " Save to Flash acknowledged"
if title <> "" and title <> "title" then write Title title
if localname <> "" and localname <> "localname" then write Name, localname
if groupname <> "" and groupname <> "groupname" then write Group, groupname
if globalname <> "" and globalname <> "globalname" then write Global, globalname
if description <> "" and description <> "description" then write Description, description
if udpport <> "" and udpport <> "udpport" then write UDPport, udpport
if opmode <> "" and opmode <> "opmode" then write Opmode, opmode
if debugmode <> "" then write Debugmode, debugmode
if buttonmode <> "" then write Buttonmode, buttonmode
if voicemode <> "" then write Voicemode, voicemode
if ondelay <> "" then write Ondelay, ondelay
if offdelay <> "" then write Offdelay, offdelay
if onduration <> "" then write Onduration, onduration
if offduration <> "" then write Offduration, offduration
if numblinks <> "" then write Blinks, numblinks
if startmode <> "" then write Startmode, startmode
if userpage <> "" then write Userpage, userpage
return