This version of the Smart Socket makes use of the Sonoff S55 waterproof mains outlet. Available for many different countries - the French version has 16A relay and pass-through earth. It is suitable for external mounting, handy for smart control of outside lighting and water features etc. It could also be used to make a smart extension cable, with room inside for the TX RX Hack if wished. It uses an ESP8285 with 1Mb flash memory, which is sufficient to run the Smart Socket script. The flexible rubber cover visible at bottom right of the pic offers external user-button access. A small translucent window diagonally opposite (top left) allows the onboard status led to be visible. The pcb has vacant facility for the usual Sonoff programming pins - powered by the UART for flashing, the onboard gpio0 user button allows boot to flash mode. This demo video shows how to flash the Sonoff S55 with Annex, and briefly how to use the Smart Socket after. The script below is the original Smart Socket script, copied here plus some of its write-up just for convenience. (see the original Smart Switch / Socket projects for more info about the Smart Socket capabilities) . The Smart Socket can be used 'standalone' by itself, or can
interact with other EasyNet devices if wished. So for example a Smart Switch might control one or more Smart Sockets (all using exactly the same script with identical network configuration). EasyNet is entirely optional and transparent though, so simply ignore it if not needed.An EasyNet device can be addressed by its Nodename, or by partial Groupname, or by its IP address, or "All". If
no meaningfull nodename is assigned (because you forgot or couldn't be
bothered at the time), the script will assign itself a unique nodename. So
consider a scenario where several EasyNet devices with the same default
scripts all received arbitrary DHCP addresses from the router and you
don't know anything about any of it !!It is actually quite simple to find out what's what... All
EasyNet nodes will respond to the name "ALL", and all nodes will
respond to "Reply", "Blink", and "BlinkIP" UDP instructions. So sending "ALL REPLY" from the UDP console will cause all nodes to reply with their Nodename and IP address. Once
you know the nodenames you can send each in turn a "Blink" instruction
to show their physical location by blinking their LED. They
already replied with their Nodename and IP address anyway, but sending
"BlinkIP" to a Nodename would cause it to locally blink out its IP
address on its LED. The only reason for knowing device IP
addresses is to connect to them from a browser for user management,
because they are not needed for device interactions.
Basic:
title$ = "EasyNet Smart Switch/Socket - by Electroguard - developed on Annex 1.39 beta 1"
nodename$ = "" 'Assign a unique node name of your choice (if you forget, it will be called "Node" + its node IP) groupname$ = "Sonoff\Smart\Switch\Socket\Relay" 'concatenated group names are searched for a partial match localIP$ = WORD$(IP$,1) netIP$ = WORD$(localIP$,1,".") + "." + WORD$(localIP$,2,".") + "." + WORD$(localIP$,3,".") + "." nodeIP$ = WORD$(localIP$,4,".") udpport = 5001 'change to suit your own preference, but don't forget to do the same for all nodes if nodename$ = "" then nodename$ = "Node" + nodeIP$ showsettings = 0 showtitle = 1 showID = 0 '=1 to show local identity info showbuttons = 1 '=1 to show onscreen system buttons showclock = 0 '=1 to show clock and schedule options showscheduled = 0 '=1 to show scheduled alarm On and Off times showcycled = 0 '=1 to show cycleOn and cycleOff options showswmodes = 0 '=1 to show harware button and switch mode checkboxes showtools = 0 '=1 to show onscreen system buttons showtherm = 0 '=1 to show temperature display showstat = 0 '=1 to enable thermostat options 'filename$ = word$(BAS.FILENAME$,1,".") + ".ini" 'Un-comment this line to save settings to 'this scriptname'.ini filename$ = "/program/smartswitch.ini" 'Uncomment this line to save to a specfied file fontpath$ = "/font/" 'path to optional font file fontfile$ = "dig7monoitalic.ttf" 'filename.ext of optional font file instructionslist$ = "Reply Report BlinkIP Blink Save Load " 'List of Subdir branches available as remote triggers instructionslist$ = instructionslist$ + "Relay1On Relay1Off Toggle1 Cycle1On Cycle1Off" 'List of Subdir branches available as remote triggers setpoint = 22 'thermostat setpoint statlist$ = "fan,heater" statmode$ = "fan" 'fan switches relay on if temp above setpoint, heater switches relay on if temp below setpoint. dallaspin = 1 'Dallas 1-wire temperature sensor pin temp$ = str$(val(tempr$(dallaspin,1)),"%2.1f") newtemp$ = "" enablestat = 0 '=1 to enable thermostat switching enablescheduledOn = 0 '=1 to enable scheduled On time enablescheduledOff = 0 '=1 to enable scheduled Off time ontime$ = "8:01" offtime$ = "8:02" unitslist$ = "secs, mins, hours, days" secs = 1: mins = secs * 60: hours = mins * 60: days = hours * 24 enabledelayon = 0 '=1 enable cycleOn delay ondelay = 7 'cycleOn delay ondelunits$ = "days" ondelaycountdown = -1 enabletimedon = 1 '=1 enable cycleOn duration onduration = 1 'cycleOn duration ondurunits$ = "mins" ondurationcountdown = -1 enabledelayoff = 1 '=1 enable cycleOff delay offdelay = 10 'cycleOff duration offdelunits$ = "secs" offdelaycountdown = -1 enabletimedoff = 1 '=1 enable cycleOff duration offduration = 30 'cycleOff duration offdurationcountdown = -1 offdurunits$ = "secs" instruction$ = "" 'variable to hold incoming instruction RXmsg$ = "" 'variable to hold incoming message data$ = "" 'variable to hold any incoming data which follows the instruction retryq$ = "" 'variable to hold all unexpired messages still waiting to be acknowledged qdelimiter$ = "|" 'separates messages in the retryq time2live = 30 'sent-message unacknowledged lifetime in seconds led1pin = 13: led1off = 1: pin.mode led1pin, output: pin(led1pin) = led1off relay1pin = 12: relay1noff = 0: pin.mode relay1pin, output: pin(relay1pin) = relay1noff 'using active high qpio12 for relay1 switchpin = 3: switchoff = 1: pin.mode switchpin, input, pullup 'switch normally high active low switchmode = 1 '1=bi-state lever switch, 0=momentary press to toggle button interrupt switchpin, switched buttonpin = 0: pin.mode buttonpin, input, pullup 'using active low gpio0 button buttonmode = 0 '1=bi-state lever switch, 0=momentary press to toggle button interrupt buttonpin, pressed start=0: stop=0 'used by button-pressed subroutine to differentiate between short and long presses debounce = 100 longpress=3000 'longpress set high at 3 secs to minimise accidental triggering of blinkIP ledstat$ = "green" blinks = 10 'blink default number of blinks, can be over-ridden by sending "nodename blink number_of_blinks" 'gosub load 'ini file mechanism is not fully implemented gosub paint onhtmlchange changed onhtmlreload paint timer0 1000, ticker timer1 1000, Retry 'periodic timer to keep resending unACKed msgs until they expire udp.begin(udpport) onudp udpRX wlog "Started: " + time$ + " on " + date$ wait paint: cls autorefresh 1000 a$ = a$ + |<br><div id='message' data-var='clicked' onclickx='cmdButton(this)' style='display: table; margin-right:auto;margin-left:auto;text-align:center;'>| if showtitle = 1 then a$ = a$ + title$ + "<br><br>" if showID = 1 then a$ = a$ + |<table align='center'><tr><td>| a$ = a$ + |Node name:</td><td>| + textbox$(nodename$,"tbname") + |</td></tr><tr><td>| a$ = a$ + cssid$("tbname", "color:Darkcyan;font-size:1.2em;width:150px;") a$ = a$ + |local IP:</td><td>| + localIP$ + |</td></tr><tr><td>| a$ = a$ + |UDP port:</td><td>| + textbox$(udpport,"tb40") + |</td></tr></td></tr></table><br><br>| endif if showbuttons = 1 then a$ = a$ + button$("Instant On",relay1on) + string$(9," ") + button$("Toggle", toggle1, "butled") + string$(9," ") + button$("Instant Off",relay1off) + |<br><br>| a$ = a$ + cssid$("butled", "height:3em; font-size:1.5em; border-radius:.4em; padding:.5em; color:white; background:" + ledstat$ + ";") endif if showclock = 1 then a$ = a$ + |<div style='display: table; margin-right:auto;margin-left:auto;text-align:center;borderx:1px solid gray;'>| a$ = a$ + |<style> @font-face { font-family: myfont; src: url('| + fontpath$ + fontfile$ + |');} </style><br>| a$ = a$ + |<div id='clock' style='font-family:myfont;background:lightcyan;color:dimgray;font-size:2.9em;border:1px solid gray;text-align:center;| a$ = a$ + |display: table; margin-right:auto;margin-left:auto;padding-left:.4em;padding-right:.4em;'>| + time$ + |</div><br>| endif if showscheduled = 1 then a$ = a$ + |<div style='display: table; margin-right:auto;margin-left:auto;text-align:center;borderx:1px solid gray;'>| a$ = a$ + checkbox$(enablescheduledon) + " " + |On Time:| + textbox$(ontime$,"tb40") + string$(9," ") a$ = a$ + checkbox$(enablescheduledoff) + " " + |Off Time:</td><td>| + textbox$(offtime$,"tb40") + |<br>| a$ = a$ + |</div>| endif html a$ pause 200 a$ = "" if (showtherm = 1) or (showstat = 1) then a$ = a$ + |<div style='display: table; margin-right:auto;margin-left:auto;text-align:center;borderx:1px solid gray;'>| a$ = a$ + |<br><div id='temp' style='font-family: myfont;background:LightGoldenRodYellow ;color:dimgray;font-size:1.8em;text-align:center;border:1px solid gray;| a$ = a$ + |display: table; margin-right:auto;margin-left:auto;border-radius:3em;padding-left:.4em;padding-right:.3em;'>| + temp$ + "˚" + |</div>| a$ = a$ + "<br>" if showstat = 1 then a$ = a$ + button$(" < ", statdown) + " " + textbox$(setpoint,"tb30") + " " + button$(" > ", statup) + "<br>" a$ = a$ + checkbox$(enablestat) + listbox$(statmode$,statlist$,"tb80") + "<br><br>" endif a$ = a$ + |</div>| endif if showcycled = 1 then a$ = a$ + |<div style='display: table; margin-right:auto;margin-left:auto;text-align:center;borderx:1px solid gray;'>| a$ = a$ + |<table align='center'><tr><td>| a$ = a$ + button$("Controlled On ", cycle1on) + string$(9," ") + |</td><td>| + "On delay " + |</td><td>| a$ = a$ + " " + checkbox$(enabledelayon) + |</td><td>| + " " + textbox$(ondelay,"tb40") + |</td><td>| + listbox$(ondelunits$,unitslist$,"tb60") + |</td><td>| a$ = a$ + string$(9," ") + " On duration " + |</td><td>| + checkbox$(enabletimedon) + |</td><td>| + " " + textbox$(onduration,"tb40") + |</td><td>| + listbox$(ondurunits$,unitslist$,"tb60") + |</td></tr><br><tr><td>| a$ = a$ + button$("Controlled Off ", cycle1off) + string$(9," ") + |</td><td>| + "Off delay " + |</td><td>| a$ = a$ + " " + checkbox$(enabledelayoff) + |</td><td>| + " " + textbox$(offdelay,"tb40") + |</td><td>| + listbox$(offdelunits$,unitslist$,"tb60") + |</td><td>| a$ = a$ + string$(9," ") + " Off duration " + |</td><td>| + checkbox$(enabletimedoff) + |</td><td>| + " " + textbox$(offduration,"tb40") + |</td><td>| + listbox$(offdurunits$,unitslist$,"tb60") + |</td></tr></table><br>| a$ = a$ + |</div>| endif if showtools = 1 then a$ = a$ + |<div style='display: table; margin-right:auto;margin-left:auto;text-align:center;borderx:1px solid gray;'>| a$ = a$ + "<br>" + button$("Blink", blink) + " " + textbox$(blinks,"tb40") + string$(9," ") a$ = a$ + button$("Blink IP", blinkip) + string$(9," ") a$ = a$ + button$("Send", sendudp) + string$(9," ") a$ = a$ + button$("Save settings", save) + "<br>" a$ = a$ + |</div>| endif if showswmodes = 1 then a$ = a$ + "<br> gpio0 On/Off flip switch " + checkbox$(buttonmode) + " or momentary toggle button<br>" a$ = a$ + " gpio" + str$(switchpin) + " On/Off flip switch " + checkbox$(switchmode) + " or momentary toggle button<br>" endif a$ = a$ + "<br>ShowSettings:" + checkbox$(showsettings) if showsettings = 1 then a$=a$+", ShowTitle:"+checkbox$(showtitle)+", ShowID:"+checkbox$(showid)+", Buttons:"+checkbox$(showbuttons) a$=a$+", ShowClock:"+checkbox$(showclock)+", ShowScheduled:"+checkbox$(showscheduled) a$=a$+", ShowTherm:"+checkbox$(showtherm)+", ShowStat:"+checkbox$(showstat) a$=a$+", ShowCycled:"+checkbox$(showcycled)+", ShowTools:"+checkbox$(showtools)+", ShowSWmodes:"+checkbox$(showswmodes)+"<br>"+"<br>" endif a$ = a$ + cssid$("tb30", "width:30; text-align:center; color:teal; background:GhostWhite;") a$ = a$ + cssid$("tb40", "width:40; text-align:center; color:teal; background:GhostWhite;") a$ = a$ + cssid$("tb60", "width:60; text-align:center; color:teal; background:GhostWhite;") a$ = a$ + cssid$("tb80", "width:80; text-align:center; color:teal; background:GhostWhite;") a$ = a$ + |</div>| html a$ a$ = "" return settings: if visibility$ = "Hide" then visibility$ = "Show" else visibility$ = "Hide" refresh return changed: ch$ = HtmlEventVar$ if instr(ch$,"show") = 1 then gosub paint if len(word$(ontime$,2,":")) = 1 then ontime$ = replace$(ontime$,":",":0") if len(word$(offtime$,2,":")) = 1 then offtime$ = replace$(offtime$,":",":0") return ticker: if showclock = 1 then jscall |_$('clock').innerHTML = "| + time$ + |"| ' updates the digital clock display if (showtherm = 1) or (enablestat = 1) then newtemp$ = str$(val(tempr$(dallaspin,1)),"%2.1f") if (newtemp$ <> temp$) then temp$ = newtemp$ jscall |_$('temp').innerHTML = "| + temp$ + "˚" + |"| ' updates the temp display endif endif if enablestat = 1 then if val(temp$) < setpoint then 'turn heater on or fan off if (statmode$ = "heater") and (pin(relay1pin) = relay1noff) then if relay1noff = 0 then pin(relay1pin) = 1 else pin(relay1pin) = 0 html cssid$("butled", "background:red;") endif if (statmode$ = "fan") and (pin(relay1pin) <> relay1noff) then pin(relay1pin) = relay1noff html cssid$("butled", "background:green;") endif endif if (val(temp$) > setpoint) then if (statmode$ = "heater") and (pin(relay1pin) <> relay1noff) then pin(relay1pin) = relay1noff html cssid$("butled", "background:green;") endif if (statmode$ = "fan") and (pin(relay1pin) = relay1noff) then pin(relay1pin) = 1 - relay1noff html cssid$("butled", "background:red;") endif endif endif if (enablescheduledon = 1) and (pin(relay1pin) = relay1noff) then if (val(word$(ontime$,1,":")) = val(word$(time$,1,":"))) and (val(word$(ontime$,2,":")) = val(word$(time$,2,":"))) then gosub relay1on endif if (enablescheduledoff = 1) and (pin(relay1pin) <> relay1noff) then if (val(word$(offtime$,1,":")) = val(word$(time$,1,":"))) and (val(word$(offtime$,2,":")) = val(word$(time$,2,":"))) then gosub relay1off endif if ondelaycountdown >= 0 then if pin(led1pin) = 0 then pin(led1pin) = 1 else pin(led1pin) = 0 if ondelaycountdown > 0 then ondelaycountdown = ondelaycountdown -1 else ondelaycountdown = -1 gosub relay1on COMMAND "m=" + ondurunits$ if enabletimedon = 1 then ondurationcountdown = onduration * m endif endif if ondurationcountdown >= 0 then if pin(led1pin) = 0 then pin(led1pin) = 1 else pin(led1pin) = 0 if ondurationcountdown > 0 then ondurationcountdown = ondurationcountdown -1 else ondurationcountdown = -1 gosub relay1off endif endif if offdelaycountdown >= 0 then if pin(led1pin) = 0 then pin(led1pin) = 1 else pin(led1pin) = 0 if offdelaycountdown > 0 then offdelaycountdown = offdelaycountdown -1 else offdelaycountdown = -1 gosub relay1off COMMAND "m=" + offdurunits$ if enabletimedoff = 1 then offdurationcountdown = offduration * m endif endif if offdurationcountdown >= 0 then if pin(led1pin) = 0 then pin(led1pin) = 1 else pin(led1pin) = 0 if offdurationcountdown > 0 then offdurationcountdown = offdurationcountdown -1 else offdurationcountdown = -1 gosub relay1on endif endif return statup: setpoint = setpoint + 1 newtemp$ = "" refresh return statdown: setpoint = setpoint - 1 if setpoint < 0 then setpoint = 0 newtemp$ = "" refresh return udpRX: RXmsg$ = udp.read$ if ucase$(word$(RXmsg$,1)) = "ACK" then gosub ACK 'echoed reply from successfully received message, original msg can be removed from queue else target$ = ucase$(word$(RXmsg$,1)) 'Target may be NodeName or GroupName or "ALL" or localIP address if (target$=localIP$) OR (target$=ucase$(nodename$)) OR (instr(ucase$(groupname$),target$)>0) OR (target$="ALL") then instruction$ = trim$(ucase$(word$(RXmsg$,2))) 'Instruction is second word of message data$ = "": getdata data$,RXmsg$," ",2 'extract any data that follows the instruction if word.find(ucase$(instructionslist$),instruction$) > 0 then if (ucase$(instruction$) <> "ACK") and (instr(ucase$(data$),"ID=") > 0) then udp.reply "ACK " + RXmsg$ 'ACKnowledge the incoming msg endif gosub instruction$ 'branch to action the corresponding instruction subroutine else udp.reply RXmsg$ + " INSTRUCTION NOT RECOGNISED" endif 'word.find endif '(target$=localIP$) endif 'ACK return ACK: msg$ = "": getdata msg$, RXmsg$, " ", 1 pos = word.find(retryq$,msg$,qdelimiter$) if pos > 0 then retryq$ = word.delete$(retryq$,pos,qdelimiter$) return RETRY: if word.count(retryq$, qdelimiter$) > 0 then if retryq$ <> "" then wlog "queue=" + retryq$ msg$ = word$(retryq$,1,qdelimiter$) 'grab first unACKed msg in the queue retryq$ = word.delete$(retryq$,1,qdelimiter$) 'chop msg off front of queue expire$ = "" WordParse expire$, msg$, "ID=", " " 'parse out ID= expire time if msg$ <> "" then 'compare expire time to current unix time if dateunix(date$) + timeunix(time$) > val(expire$) then Send "LOG ERROR: Node " + Nodename$ + " FAILED SEND - " + msg$ + " not ACKnowledged" else retryq$ = retryq$ + msg$ + qdelimiter$ udp.write netip$ + "255", udpport, msg$ wlog "retry " + msg$ endif endif endif return sendudp: sendmsg$ = sendmsg$ + " ID=" + str$(dateunix(date$) + timeunix(time$) + time2live, "%10d", 1) retryq$ = retryq$ + sendmsg$ + qdelimiter$ udp.write netip$ + "255", udpport, sendmsg$ return sub SendQ(sendmsg$) sendmsg$ = sendmsg$ + " ID=" + str$(dateunix(date$) + timeunix(time$) + time2live, "%10d", 1) retryq$ = retryq$ + sendmsg$ + qdelimiter$ udp.write netip$ + "255", udpport, sendmsg$ end sub sub Send(sendmsg$) udp.write netip$ + "255", udpport, sendmsg$ end sub sub GetData(ret$, v$, sep$, pos) 'extracts everything from the msg after the Instruction and puts into data$ (thanks cicciocb) local i, p, q p = 1 for i = 1 to pos p = instr(p + 1, v$, sep$) if p > 0 then p = p + len(sep$) next i if p = 0 then ret$ = "" else q = instr(p+1, v$, sep$) if q = 0 then q = 999 ret$ = mid$(v$, p) end if end sub sub WordParse(ret$, full$, search$, sep$) 'extracts value from option=value (thanks cicciocb) local p, b$ p = instr(full$, search$) if p <> 0 then b$ = mid$(full$, p + len(search$)) ret$ = word$(b$, 1, sep$) else ret$ = "" end if end sub load: ' Loads settings from file ... not yet fully implemented a$ = "" if FILE.EXISTS(filename$) > 0 then a$ = FILE.READ$(filename$) if WORD.GETPARAM$(a$,"nodename") <> "" then nodename$ = WORD.GETPARAM$(a$,"nodename") if WORD.GETPARAM$(a$,"ondelay") <> "" then ondelay = val(WORD.GETPARAM$(a$,"ondelay")) if WORD.GETPARAM$(a$,"onduration") <> "" then onduration = val(WORD.GETPARAM$(a$,"onduration")) if WORD.GETPARAM$(a$,"offdelay") <> "" then offdelay = val(WORD.GETPARAM$(a$,"offdelay")) if WORD.GETPARAM$(a$,"offduration") <> "" then offduration = val(WORD.GETPARAM$(a$,"offduration")) if WORD.GETPARAM$(a$,"udpport") <> "" then udpport = val(WORD.GETPARAM$(a$,"udpport")) endif return save: ' Saves settings to file ... not yet fully implemented a$ = "" if FILE.EXISTS(filename$) > 0 then a$ = FILE.READ$(filename$) WORD.SETPARAM a$, "nodename", nodename$ WORD.SETPARAM a$, "ondelay", str$(ondelay) WORD.SETPARAM a$, "onduration", str$(onduration) WORD.SETPARAM a$, "offdelay", str$(offdelay) WORD.SETPARAM a$, "offduration", str$(offduration) WORD.SETPARAM a$, "udpport", str$(udpport) FILE.SAVE filename$, a$ return blink: if data$ <> "" then blinks = val(data$) ledstate = pin(led1pin) pin(led1pin) = led1off pause 200 for count = 1 to blinks if led1off = 1 then pin(led1pin) = 0 else pin(led1pin) = 1 pause 800 pin(led1pin) = led1off pause 200 next count pause 2000 pin(led1pin) = ledstate 'Restore LED state to its previous state return blinkip: ledstate = pin(led1pin) blinkon = 150 blinkoff = 300 blinkpause = 1000 blinkgap = 1400 pin(led1pin) = led1off pause blinkpause for pos = 1 to len(localIP$) digitchr$ = mid$(localIP$,pos,1) if digitchr$ = "." then pause blinkgap else if digitchr$ = "0" then digit = 10 else digit = val(digitchr$) for count = 1 to digit if led1off = 0 then pin(led1pin) = 1 else pin(led1pin) = 0 pause blinkon if led1off = 0 then pin(led1pin) = 0 else pin(led1pin) = 1 pause blinkoff next count pause blinkpause end if next pos pause blinkgap pin(led1pin) = ledstate return REPLY: udp.reply "Reply from " + Nodename$ return REPORT: udp.reply "Report from " + Nodename$ + " " + instructionslist$ return pressed: interrupt buttonpin, off pause debounce if pin(buttonpin) = 0 then start = millis else stop = millis if buttonmode = 1 then if pin(buttonpin) = 0 and (pin(relay1pin) = relay1noff) then gosub relay1on if pin(buttonpin) = 1 and (pin(relay1pin) <> relay1noff) then gosub relay1off else if stop > start then if stop - start < longpress then gosub toggle1 else gosub blinkip endif endif interrupt buttonpin, pressed return switched: interrupt switchpin, off pause debounce if pin(switchpin) <> switchoff then if switchmode = 1 then gosub relay1on else gosub toggle1 else if switchmode = 1 then gosub relay1off endif interrupt switchpin, switched return relay1on: if pin(relay1pin) = relay1noff then if relay1noff = 0 then pin(relay1pin) = 1 else pin(relay1pin) = 0 endif indicator = 0 pin(led1pin) = 1-led1off html cssid$("butled", "background:red;") ondelaycountdown = -1 offdelaycountdown = -1 ondurationcountdown = -1 offdurationcountdown = -1 return relay1off: if pin(relay1pin) <> relay1noff then pin(relay1pin) = relay1noff indicator = 1 pin(led1pin) = led1off html cssid$("butled", "background:green;") ondelaycountdown = -1 offdelaycountdown = -1 ondurationcountdown = -1 offdurationcountdown = -1 return cycle1on: COMMAND "m=" + ondelunits$ if enabledelayon > 0 then ondelaycountdown = ondelay * m else ondelaycountdown = 0 return cycle1off: COMMAND "m=" + offdelunits$ if enabledelayoff > 0 then offdelaycountdown = offdelay * m else offdelaycountdown = 0 return toggle1: if pin(relay1pin) = relay1noff gosub relay1on else gosub relay1off enablescheduledon = 0 enablescheduledoff = 0 enablestat = 0 enabledelayon = 0 enabledelayoff = 0 enabletimedon = 0 enabletimedoff = 0 ondelaycountdown = -1 offdelaycountdown = -1 ondurationcountdown = -1 offdurationcountdown = -1 return END '-------------------- End --------------------- All of the functionality shown below is available... most is disabled by default but can be enabled individually 'as needed'. See the Smart Switch project for details of how to download and install the 7-segment digital web fonts.
|