Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
|
I needed a tiny device to control a light over wifi that could be accessed by anyone connected to a specific router. I Found the most compact way was to use an ESP8266 with NODEMCU firmware. I did get ready to use codes for the project but the AP settings had to be hardcoded. So I made the GUI from scratch using html and LUA with a GUI for configuring WIFI settings.
print("Get available APs")
wifi.setmode(wifi.STATION)
wifi.sta.getap(function(t)
available_aps = ""
if t then
for k,v in pairs(t) do
ap = string.format("%-10s",k)
ap = trim(ap)
available_aps = available_aps .. "<option value='".. ap .."'>".. ap .."</option>"
end
setup_server(available_aps)
end
end)
local unescape = function (s)
s = string.gsub(s, "+", " ")
s = string.gsub(s, "%%(%x%x)", function (h)
return string.char(tonumber(h, 16))
end)
return s
end
function setup_server(aps)
print("Setting up Wifi AP")
wifi.setmode(wifi.SOFTAP)
cfg = {}
cfg.ssid = "ESP8266 HOME AUTOMATION";
cfg.pwd = "password"
wifi.ap.config(cfg)
wifi.ap.setip({ip="192.168.1.1",netmask="255.255.255.0",gateway="192.168.1.1"})
print("Setting up webserver")
srv = nil
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
conn:on("receive", function(client,request)
local buf = ""
local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
if(method == nil)then
_, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP")
end
local _GET = {}
if (vars ~= nil)then
for k, v in string.gmatch(vars, "(%w+)=([^%&]+)&*") do
_GET[k] = unescape(v)
end
end
if (_GET.psw ~= nil and _GET.ap ~= nil and _GET.ipTCP ~= nil) then
client:send("Saving data..")
file.open("config.txt", "w+")
file.writeline(_GET.ap)
file.writeline(_GET.psw)
file.writeline(_GET.ipTCP)
file.writeline(_GET.nmsk)
file.writeline(_GET.gty)
file.close()
--node.compile("config.lua")
--file.remove("config.lua")
client:send(buf)
node.restart()
end
buf = "<html><body>"
buf = buf .. "<br><h3 style = \"color: #fc970e; text-align: center; font-size: 40px; padding: 10px\">Configuration utility</h3>"
buf = buf .. "<form style = \"border-radius: 20px; border:4px;text-align: center; border-style: solid; padding: 10px; border-color: #4eb0fd\" method='get' action='http://" .. wifi.ap.getip() .."'><br>"
buf = buf .. "<d style = \"font-family: Arial; font-size: 30px; color: #4eb0fd\">Select access point: </d> <select name='ap'>" .. aps .. "</select><br><br>"
buf = buf .. "<d style = \"font-family: Arial; font-size: 30px; color: #4eb0fd\">Enter wifi password: </d> <input style = \" height: 20px; width: 200px; text-align: center;\" type='password' value = 'password' name='psw'></input><br><br>"
buf = buf .. "<d style = \"font-family: Arial; font-size: 30px; color: #4eb0fd\">Server-IP: </d><input style = \" height: 20px; width: 200px; text-align: center;\" name='ipTCP' value='192.168.1.100'></input><br><br>"
buf = buf .. "<d style = \"font-family: Arial; font-size: 30px; color: #4eb0fd\">Netmask : </d><input style = \" height: 20px; width: 200px; text-align: center;\" name='nmsk' value='255.255.255.0'></input><br><br>"
buf = buf .. "<d style = \"font-family: Arial; font-size: 30px; color: #4eb0fd\">Gateway : </d><input style = \" height: 20px; width: 200px; text-align: center;\" name='gty' value='192.168.1.1'></input><br><br>"
buf = buf .. "<button type='submit' style = \"font-size: 25px; border-color: #1ef59d; border-radius: 20px; background-color: #0dc2ee; color: #fbfcfc\">Save</button>"
buf = buf .. "</form></body></html>"
client:send(buf)
client:close()
collectgarbage()
end)
end)
print("Please connect to: " .. wifi.ap.getip())
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
file.open("config.txt","r");
SSID = file.readline():gsub("%s+$", "");
PASS = file.readline():gsub("%s+$", "");
IP = file.readline():gsub("%s+$", "");
NETMSK = file.readline():gsub("%s+$", "");
GTY = file.readline():gsub("%s+$", "");
file.close();
wifi.setmode(wifi.STATION)
cfg = {
ip= IP,
netmask= NETMSK,
gateway= GTY
}
wifi.sta.setip(cfg)
--Your router wifi network's SSID and password
wifi.sta.config(SSID,PASS)
--Automatically connect to network after disconnection
wifi.sta.autoconnect(1)
print ("\r\n")
--Print network ip address on UART to confirm that network is connected
print(wifi.sta.getip())
--Create server and send html data, process request from html for relay on/off.
srv=net.createServer(net.TCP)
srv:listen(80,function(conn) --change port number if required. Provides flexibility when controlling through internet.
conn:on("receive", function(client,request)
local html_buffer = "";
local html_buffer1 = "";
local html_buffer2 = "";
local html_buffer3 = "";
local html_buffer4 = "";
local html_buffer5 = "";
local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
if(method == nil)then
_, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
end
local _GET = {}
if (vars ~= nil)then
for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
_GET[k] = v
end
end
html_buffer = html_buffer.."<!DOCTYPE html>";
html_buffer = html_buffer.."<html>";
html_buffer = html_buffer.."<title>DB's IOT Server</title>";
html_buffer = html_buffer.."</head>";
html_buffer = html_buffer.."<body style = \"color: #d8fafe\">";
html_buffer = html_buffer.."<table align = \"center\" color = \"#aaaaff\" style = \"border-width: 4px; border-style: solid; border-color: #4eb0fd; padding:18px ; border-radius:18px\">";
html_buffer = html_buffer.."<thead>";
html_buffer = html_buffer.."<title>IOT Server</title>";
html_buffer = html_buffer.."<tr>";
html_buffer = html_buffer.."<th colspan = \"2\" style = \"border-width:3px; border-color: #fcd4fb; border-style: solid; border-radius:18px; font-size: 90px; font-family: Arial; padding: 12px; color: #f09b19 \">IOT Server</th>";
html_buffer = html_buffer.."</tr>";
html_buffer = html_buffer.."<tr>";
html_buffer = html_buffer.."<th style = \"background-color: #e8fcfe ; padding: 6px; font-size: 42px; color: #4eb0fd; margin:20px\" >Relay 1</th>";
html_buffer1 = html_buffer1.."<th style = \"background-color: #e8fcfe ; padding: 6px; font-size: 42px; color: #4eb0fd; margin:20px\" >Relay 2</th>";
html_buffer1 = html_buffer1.."</tr>";
html_buffer1 = html_buffer1.."</thead>";
html_buffer1 = html_buffer1.."<tbody style = \"background-color: #d8fafe \">";
html_buffer1 = html_buffer1.."<tr align = \"center\">";
html_buffer1 = html_buffer1.."<td style = \"border: 2WHIRLPOOLpx\">";
html_buffer1 = html_buffer1.."<a href=\"?pin=ON1\"><button style = \"color: #4eb0fd; width:110px; font-family:Arial; font-size: 45px; border-radius: 30px; margin:20px; padding:5px\">ON</button></a>";
html_buffer1 = html_buffer1.."</td>";
html_buffer1 = html_buffer1.."<td>";
html_buffer1 = html_buffer1.."<a href=\"?pin=ON2\"><button style = \"color: #4eb0fd; width:110px; font-family:Arial; font-size: 45px; border-radius: 30px; margin:20px; padding:5px\">ON</button></a>";
html_buffer1 = html_buffer1.."</td> ";
html_buffer1 = html_buffer1.."</tr>";
html_buffer1 = html_buffer1.."<tr align = \"center\">";
html_buffer2 = html_buffer2.."<td>";
html_buffer2 = html_buffer2.."<a href=\"?pin=OFF1\"><button style = \"color: #4eb0fd; width:110px; font-family:Arial; font-size: 45px; border-radius: 30px; margin:20px;padding:5px\">OFF</button></a>";
html_buffer2 = html_buffer2.."</td>";
html_buffer2 = html_buffer2.."<td>";
html_buffer2 = html_buffer2.."<a href=\"?pin=OFF2\"><button style = \"color: #4eb0fd; width:110px; font-family:Arial; font-size: 45px; border-radius: 30px; margin:20px; padding:5px\">OFF</button></a>";
html_buffer2 = html_buffer2.."</td>";
html_buffer2 = html_buffer2.."</tr>";
html_buffer2 = html_buffer2.."</tbody>";
html_buffer2 = html_buffer2.."</table>";
html_buffer2 = html_buffer2.."</body>";
html_buffer2 = html_buffer2.."</html>";
local _on,_off = "",""
if(_GET.pin == "ON1")then
gpio.write(Relay1, gpio.HIGH);
elseif(_GET.pin == "OFF1")then
gpio.write(Relay1, gpio.LOW);
elseif(_GET.pin == "ON2")then
gpio.write(Relay2, gpio.LOW);
elseif(_GET.pin == "OFF2")then
gpio.write(Relay2, gpio.HIGH);
end
--Buffer is sent in smaller chunks as due to limited memory ESP8266 cannot handle more than 1460 bytes of data.
client:send(html_buffer);
client:send(html_buffer1);
client:send(html_buffer2);
client:close();
collectgarbage();
end)
end)
Relay1 = 1
Relay2 = 4
Rst1 = 5
gpio.mode(Rst1, gpio.INPUT);
gpio.mode(Relay1, gpio.OUTPUT)
gpio.write(Relay1, gpio.LOW);
gpio.mode(Relay2, gpio.OUTPUT)
gpio.write(Relay2, gpio.HIGH);
if(gpio.read(Rst1) == 0)then
print("Configuration mode")
dofile("conf.lua");
else
print("Server mode")
dofile("server.lua");
end
Comments